]> git.lizzy.rs Git - plan9front.git/blob - sys/src/cmd/ratfs/main.c
exec(2): fix prototypes
[plan9front.git] / sys / src / cmd / ratfs / main.c
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
49 usage(void)
50 {
51         fprint(2, "ratfs [-d] [-c conffile] [-f ctlfile] [-m mountpoint]\n");
52         exits("usage");
53 }
54
55 void
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
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
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
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*
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
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
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
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
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 }