xref: /plan9/sys/src/cmd/ratfs/main.c (revision 9a747e4fd48b9f4522c70c07e8f882a15030f964)
1 #include "ratfs.h"
2 
3 #define	SRVFILE		"/srv/ratify"
4 #define MOUNTPOINT	"/mail/ratify"
5 #define	CTLFILE		"/mail/lib/blocked"
6 #define	CONFFILE	"/mail/lib/smtpd.conf.ext"
7 
8 typedef struct Filetree	Filetree;
9 
10 	/* prototype file tree */
11 struct	Filetree
12 {
13 	int	level;
14 	char	*name;
15 	ushort	type;
16 	int	mode;
17 	ulong	qid;
18 };
19 
20 	/* names of first-level directories - must be in order of level*/
21 Filetree	filetree[] =
22 {
23 	0,	"/",		Directory,	0555|DMDIR,	Qroot,
24 	1,	"allow",	Addrdir,	0555|DMDIR,	Qallow,
25 	1,	"delay",	Addrdir,	0555|DMDIR,	Qdelay,
26 	1,	"block",	Addrdir,	0555|DMDIR,	Qblock,
27 	1,	"dial",		Addrdir,	0555|DMDIR,	Qdial,
28 	1,	"deny",		Addrdir,	0555|DMDIR,	Qdeny,
29 	1,	"trusted",	Trusted,	0777|DMDIR,	Qtrusted,	/* creation allowed */
30 	1,	"ctl",		Ctlfile,	0222,		Qctl,
31 	2,	"ip",		IPaddr,		0555|DMDIR,	Qaddr,
32 	2,	"account",	Acctaddr,	0555|DMDIR,	Qaddr,
33 	0,	0,		0,		0,		0,
34 
35 };
36 
37 int	debugfd = -1;
38 int	trustedqid = Qtrustedfile;
39 char	*ctlfile =	CTLFILE;
40 char	*conffile =	CONFFILE;
41 
42 #pragma	varargck	type	"I"	Cidraddr*
43 
44 static	int	ipconv(Fmt*);
45 static	void	post(int, char*);
46 static	void	setroot(void);
47 
48 void
usage(void)49 usage(void)
50 {
51 	fprint(2, "ratfs [-d] [-c conffile] [-f ctlfile] [-m mountpoint]\n");
52 	exits("usage");
53 }
54 
55 void
main(int argc,char * argv[])56 main(int argc, char *argv[])
57 {
58 	char *mountpoint = MOUNTPOINT;
59 	int p[2];
60 
61 	ARGBEGIN {
62 	case 'c':
63 		conffile = ARGF();
64 		break;
65 	case 'd':
66 		debugfd = 2;		/* stderr*/
67 		break;
68 	case 'f':
69 		ctlfile = ARGF();
70 		break;
71 	case 'm':
72 		mountpoint = ARGF();
73 		break;
74 	} ARGEND
75 	if(argc != 0)
76 		usage();
77 
78 	fmtinstall('I', ipconv);
79 	setroot();
80 	getconf();
81 	reload();
82 
83 	/* get a pipe and mount it in /srv */
84 	if(pipe(p) < 0)
85 		fatal("pipe failed: %r");
86 	srvfd = p[0];
87 	post(p[1], mountpoint);
88 
89 	/* start the 9fs protocol */
90 	switch(rfork(RFPROC|RFNAMEG|RFENVG|RFFDG|RFNOTEG|RFREND)){
91 	case -1:
92 		fatal("fork: %r");
93 	case 0:
94 		/* seal off standard input/output */
95 		close(0);
96 		open("/dev/null", OREAD);
97 		close(1);
98 		open("/dev/null", OWRITE);
99 
100 		close(p[1]);
101 		fmtinstall('F', fcallfmt); /* debugging */
102 		io();
103 		fprint(2, "ratfs dying\n");
104 		break;
105 	default:
106 		close(p[0]);
107 		if(mount(p[1], -1, mountpoint, MREPL|MCREATE, "") < 0)
108 			fatal("mount failed: %r");
109 	}
110 	exits(0);
111 }
112 
113 static void
setroot(void)114 setroot(void)
115 {
116 	Filetree *fp;
117 	Node *np;
118 	int qid;
119 
120 	root = 0;
121 	qid = Qaddr;
122 	for(fp = filetree; fp->name; fp++) {
123 		switch(fp->level) {
124 		case 0:		/* root */
125 		case 1:		/* second level directory */
126 			newnode(root, fp->name, fp->type, fp->mode, fp->qid);
127 			break;
128 		case 2:		/* lay down the Ipaddr and Acctaddr subdirectories */
129 			for (np = root->children; np; np = np->sibs){
130 				if(np->d.type == Addrdir)
131 					newnode(np, fp->name, fp->type, fp->mode, qid++);
132 			}
133 			break;
134 		default:
135 			fatal("bad filetree");
136 		}
137 	}
138 	dummy.d.type = Dummynode;
139 	dummy.d.mode = 0444;
140 	dummy.d.uid = "upas";
141 	dummy.d.gid = "upas";
142 	dummy.d.atime = dummy.d.mtime = time(0);
143 	dummy.d.qid.path = Qdummy;				/* for now */
144 }
145 
146 static void
post(int fd,char * mountpoint)147 post(int fd, char *mountpoint)
148 {
149 
150 	int f;
151 	char buf[128];
152 
153 	if(access(SRVFILE,0) >= 0){
154 		/*
155 		 * If we can open and mount the /srv node,
156 		 * another server is already running, so just exit.
157 		 */
158 		f = open(SRVFILE, ORDWR);
159 		if(f >= 0 && mount(f, -1, mountpoint, MREPL|MCREATE, "") >= 0){
160 				unmount(0, mountpoint);
161 				close(f);
162 				exits(0);
163 		}
164 		remove(SRVFILE);
165 	}
166 
167 	/*
168 	 * create the server node and post our pipe to it
169 	 */
170 	f = create(SRVFILE, OWRITE, 0666);
171 	if(f < 0)
172 		fatal("can't create %s", SRVFILE);
173 
174 	sprint(buf, "%d", fd);
175 	if(write(f, buf, strlen(buf)) != strlen(buf))
176 		fatal("can't write %s", SRVFILE);
177 
178 	close(f);
179 }
180 
181 /*
182  *  print message and die
183  */
184 void
fatal(char * fmt,...)185 fatal(char *fmt, ...)
186 {
187 	va_list arg;
188 	char buf[8*1024];
189 
190 	va_start(arg, fmt);
191 	vseprint(buf, buf + (sizeof(buf)-1) / sizeof(*buf), fmt, arg);
192 	va_end(arg);
193 
194 	fprint(2, "%s: %s\n", argv0, buf);
195 	exits(buf);
196 }
197 
198 /*
199  *  create a new directory node
200  */
201 Node*
newnode(Node * parent,char * name,ushort type,int mode,ulong qid)202 newnode(Node *parent, char *name, ushort type, int mode, ulong qid)
203 {
204 	Node *np;
205 
206 	np = mallocz(sizeof(Node), 1);
207 	if(np == 0)
208 		fatal("out of memory");
209 	np->d.name = atom(name);
210 	np->d.type = type;
211 	np->d.mode = mode;
212 	np->d.mtime = np->d.atime = time(0);
213 	np->d.uid = atom("upas");
214 	np->d.gid = atom("upas");
215 	np->d.muid = atom("upas");
216 	if(np->d.mode&DMDIR)
217 		np->d.qid.type = QTDIR;
218 	np->d.qid.path = qid;
219 	np->d.qid.vers = 0;
220 	if(parent){
221 		np->parent = parent;
222 		np->sibs = parent->children;
223 		parent->children = np;
224 		parent->count++;
225 	} else {
226 		/* the root node */
227 		root = np;
228 		np->parent = np;
229 		np->children = 0;
230 		np->sibs = 0;
231 	}
232 	return np;
233 }
234 
235 void
printnode(Node * np)236 printnode(Node *np)
237 {
238 	fprint(debugfd, "Node at %p: %s (%s %s)", np, np->d.name, np->d.uid, np->d.gid);
239 	if(np->d.qid.type&QTDIR)
240 		fprint(debugfd, " QTDIR");
241 	fprint(debugfd, "\n");
242 	fprint(debugfd,"\tQID: %llud.%lud Mode: %lo Type: %d\n", np->d.qid.path,
243 			np->d.qid.vers, np->d.mode, np->d.type);
244 	fprint(debugfd, "\tMod: %.15s  Acc: %.15s Count: %d\n", ctime(np->d.mtime)+4,
245 			ctime(np->d.atime)+4, np->count);
246 	switch(np->d.type)
247 	{
248 	case Directory:
249 		fprint(debugfd, "\tDirectory Child: %p", np->children);
250 		break;
251 	case Addrdir:
252 		fprint(debugfd, "\tAddrdir Child: %p", np->children);
253 		break;
254 	case IPaddr:
255 		fprint(debugfd, "\tIPaddr Base: %p Alloc: %d BaseQid %lud", np->addrs,
256 			np->allocated, np->baseqid);
257 		break;
258 	case Acctaddr:
259 		fprint(debugfd, "\tAcctaddr Base: %p Alloc: %d BaseQid %lud", np->addrs,
260 			np->allocated, np->baseqid);
261 		break;
262 	case Trusted:
263 		fprint(debugfd, "\tTrusted Child: %p", np->children);
264 		break;
265 	case Trustedperm:
266 		fprint(debugfd, "\tPerm Trustedfile: %I", &np->ip);
267 		break;
268 	case Trustedtemp:
269 		fprint(debugfd, "\tTemp Trustedfile: %I", &np->ip);
270 		break;
271 	case Ctlfile:
272 		fprint(debugfd, "\tCtlfile");
273 		break;
274 	case Dummynode:
275 		fprint(debugfd, "\tDummynode");
276 		break;
277 	default:
278 		fprint(debugfd, "\tUnknown Node Type\n\n");
279 		return;
280 	}
281 	fprint(debugfd, " Parent %p Sib: %p\n\n", np->parent, np->sibs);
282 }
283 
284 void
printfid(Fid * fp)285 printfid(Fid *fp)
286 {
287 	fprint(debugfd, "FID: %d (%s %s) Busy: %d Open: %d\n", fp->fid, fp->name,
288 		fp->uid, fp->busy, fp->open);
289 	printnode(fp->node);
290 }
291 
292 void
printtree(Node * np)293 printtree(Node *np)
294 {
295 	printnode(np);
296 	if(np->d.type == IPaddr
297 		|| np->d.type == Acctaddr
298 		|| np->d.type == Trustedperm
299 		|| np->d.type == Trustedtemp)
300 			return;
301 	for (np = np->children; np; np = np->sibs)
302 		printtree(np);
303 }
304 
305 static int
ipconv(Fmt * f)306 ipconv(Fmt *f)
307 {
308 	Cidraddr *ip;
309 	int i, j;
310 	char *p;
311 
312 	ip = va_arg(f->args, Cidraddr*);
313 	p = (char*)&ip->ipaddr;
314 	i = 0;
315 	for (j = ip->mask; j; j <<= 1)
316 		i++;
317 	return fmtprint(f, "%d.%d.%d.%d/%d", p[3]&0xff, p[2]&0xff, p[1]&0xff, p[0]&0xff, i);
318 }
319