tmain.c - plan9port - [fork] Plan 9 from user space
git clone git://src.adamsgaard.dk/plan9port
Log
Files
Refs
README
LICENSE
---
tmain.c (9655B)
---
     1 #include 
     2 #include 
     3 #include 
     4 #include 
     5 #include 
     6 #include "dat.h"
     7 #include "fns.h"
     8 
     9 enum
    10 {
    11         Maxfdata        = 8192,
    12         Maxiosize        = IOHDRSZ+Maxfdata,
    13 };
    14 
    15 void io(int);
    16 void rversion(void);
    17 void        rattach(void);
    18 void        rauth(void);
    19 void        rclunk(void);
    20 void        rcreate(void);
    21 void        rflush(void);
    22 void        ropen(void);
    23 void        rread(void);
    24 void        rremove(void);
    25 void        rsession(void);
    26 void        rstat(void);
    27 void        rwalk(void);
    28 void        rwrite(void);
    29 void        rwstat(void);
    30 
    31 static int        openflags(int);
    32 static void        usage(void);
    33 
    34 #define Reqsize (sizeof(Fcall)+Maxfdata)
    35 
    36 Fcall *req;
    37 Fcall *rep;
    38 
    39 uchar mdata[Maxiosize];
    40 char fdata[Maxfdata];
    41 uchar statbuf[STATMAX];
    42 
    43 
    44 extern Xfsub        *xsublist[];
    45 extern int        nclust;
    46 
    47 jmp_buf        err_lab[16];
    48 int        nerr_lab;
    49 char        err_msg[ERRMAX];
    50 
    51 int        chatty;
    52 int        nojoliet;
    53 int        noplan9;
    54 int norock;
    55 
    56 void    (*fcalls[Tmax])(void);
    57 
    58 static void
    59 initfcalls(void)
    60 {
    61         fcalls[Tversion]=        rversion;
    62         fcalls[Tflush]=        rflush;
    63         fcalls[Tauth]=        rauth;
    64         fcalls[Tattach]=        rattach;
    65         fcalls[Twalk]=                rwalk;
    66         fcalls[Topen]=                ropen;
    67         fcalls[Tcreate]=        rcreate;
    68         fcalls[Tread]=                rread;
    69         fcalls[Twrite]=        rwrite;
    70         fcalls[Tclunk]=        rclunk;
    71         fcalls[Tremove]=        rremove;
    72         fcalls[Tstat]=                rstat;
    73         fcalls[Twstat]=        rwstat;
    74 }
    75 
    76 void
    77 main(int argc, char **argv)
    78 {
    79         int srvfd, pipefd[2], stdio;
    80         Xfsub **xs;
    81         char *mtpt;
    82 
    83         initfcalls();
    84         stdio = 0;
    85         mtpt = nil;
    86         ARGBEGIN {
    87         case '9':
    88                 noplan9 = 1;
    89                 break;
    90         case 'c':
    91                 nclust = atoi(EARGF(usage()));
    92                 if (nclust <= 0)
    93                         sysfatal("nclust %d non-positive", nclust);
    94                 break;
    95         case 'f':
    96                 deffile = EARGF(usage());
    97                 break;
    98         case 'r':
    99                 norock = 1;
   100                 break;
   101         case 's':
   102                 stdio = 1;
   103                 break;
   104         case 'v':
   105                 chatty = 1;
   106                 break;
   107         case 'J':
   108                 nojoliet = 1;
   109                 break;
   110         case 'm':
   111                 mtpt = EARGF(usage());
   112                 break;
   113         default:
   114                 usage();
   115         } ARGEND
   116 
   117         switch(argc) {
   118         case 0:
   119                 break;
   120         case 1:
   121                 srvname = argv[0];
   122                 break;
   123         default:
   124                 usage();
   125         }
   126 
   127         iobuf_init();
   128         for(xs=xsublist; *xs; xs++)
   129                 (*(*xs)->reset)();
   130 
   131         if(stdio) {
   132                 pipefd[0] = 0;
   133                 pipefd[1] = 1;
   134         } else {
   135                 close(0);
   136                 close(1);
   137                 open("/dev/null", OREAD);
   138                 open("/dev/null", OWRITE);
   139                 if(pipe(pipefd) < 0)
   140                         panic(1, "pipe");
   141 
   142                 if(post9pservice(pipefd[0], srvname, mtpt) < 0)
   143                         sysfatal("post9pservice: %r");
   144                 close(pipefd[0]);
   145         }
   146         srvfd = pipefd[1];
   147 
   148         switch(rfork(RFNOWAIT|RFNOTEG|RFFDG|RFPROC)){
   149         case -1:
   150                 panic(1, "fork");
   151         default:
   152                 _exits(0);
   153         case 0:
   154                 break;
   155         }
   156 
   157         io(srvfd);
   158         exits(0);
   159 }
   160 
   161 void
   162 io(int srvfd)
   163 {
   164         int n, pid;
   165         Fcall xreq, xrep;
   166 
   167         req = &xreq;
   168         rep = &xrep;
   169         pid = getpid();
   170         fmtinstall('F', fcallfmt);
   171 
   172         for(;;){
   173                 /*
   174                  * reading from a pipe or a network device
   175                  * will give an error after a few eof reads.
   176                  * however, we cannot tell the difference
   177                  * between a zero-length read and an interrupt
   178                  * on the processes writing to us,
   179                  * so we wait for the error.
   180                  */
   181                 n = read9pmsg(srvfd, mdata, sizeof mdata);
   182                 if(n < 0)
   183                         break;
   184                 if(n == 0)
   185                         continue;
   186                 if(convM2S(mdata, n, req) == 0)
   187                         continue;
   188 
   189                 if(chatty)
   190                         fprint(2, "9660srv %d:<-%F\n", pid, req);
   191 
   192                 errno = 0;
   193                 if(!waserror()){
   194                         err_msg[0] = 0;
   195                         if(req->type >= nelem(fcalls) || !fcalls[req->type])
   196                                 error("bad fcall type");
   197                         (*fcalls[req->type])();
   198                         poperror();
   199                 }
   200 
   201                 if(err_msg[0]){
   202                         rep->type = Rerror;
   203                         rep->ename = err_msg;
   204                 }else{
   205                         rep->type = req->type + 1;
   206                         rep->fid = req->fid;
   207                 }
   208                 rep->tag = req->tag;
   209 
   210                 if(chatty)
   211                         fprint(2, "9660srv %d:->%F\n", pid, rep);
   212                 n = convS2M(rep, mdata, sizeof mdata);
   213                 if(n == 0)
   214                         panic(1, "convS2M error on write");
   215                 if(write(srvfd, mdata, n) != n)
   216                         panic(1, "mount write");
   217                 if(nerr_lab != 0)
   218                         panic(0, "err stack %d");
   219         }
   220         chat("server shut down");
   221 }
   222 
   223 static void
   224 usage(void)
   225 {
   226         fprint(2, "usage: %s [-v] [-9Jr] [-s] [-f devicefile] [srvname]\n", argv0);
   227         exits("usage");
   228 }
   229 
   230 void
   231 error(char *p)
   232 {
   233         strecpy(err_msg, err_msg+sizeof err_msg, p);
   234         nexterror();
   235 }
   236 
   237 void
   238 nexterror(void)
   239 {
   240         longjmp(err_lab[--nerr_lab], 1);
   241 }
   242 
   243 void*
   244 ealloc(long n)
   245 {
   246         void *p;
   247 
   248         p = malloc(n);
   249         if(p == 0)
   250                 error("no memory");
   251         return p;
   252 }
   253 
   254 void
   255 setnames(Dir *d, char *n)
   256 {
   257         d->name = n;
   258         d->uid = n+Maxname;
   259         d->gid = n+Maxname*2;
   260         d->muid = n+Maxname*3;
   261 
   262         d->name[0] = '\0';
   263         d->uid[0] = '\0';
   264         d->gid[0] = '\0';
   265         d->muid[0] = '\0';
   266 }
   267 
   268 void
   269 rversion(void)
   270 {
   271         if(req->msize > Maxiosize)
   272                 rep->msize = Maxiosize;
   273         else
   274                 rep->msize = req->msize;
   275         rep->version = "9P2000";
   276 }
   277 
   278 void
   279 rauth(void)
   280 {
   281         error("9660srv: authentication not required");
   282 }
   283 
   284 void
   285 rflush(void)
   286 {
   287 }
   288 
   289 void
   290 rattach(void)
   291 {
   292         Xfs *xf;
   293         Xfile *root;
   294         Xfsub **xs;
   295 
   296         chat("attach(fid=%d,uname=\"%s\",aname=\"%s\")...",
   297                 req->fid, req->uname, req->aname);
   298 
   299         if(waserror()){
   300                 xfile(req->fid, Clunk);
   301                 nexterror();
   302         }
   303         root = xfile(req->fid, Clean);
   304         root->qid = (Qid){0, 0, QTDIR};
   305         root->xf = xf = ealloc(sizeof(Xfs));
   306         memset(xf, 0, sizeof(Xfs));
   307         xf->ref = 1;
   308         xf->d = getxdata(req->aname);
   309 
   310         for(xs=xsublist; *xs; xs++)
   311                 if((*(*xs)->attach)(root) >= 0){
   312                         poperror();
   313                         xf->s = *xs;
   314                         xf->rootqid = root->qid;
   315                         rep->qid = root->qid;
   316                         return;
   317                 }
   318         error("unknown format");
   319 }
   320 
   321 Xfile*
   322 doclone(Xfile *of, int newfid)
   323 {
   324         Xfile *nf, *next;
   325 
   326         nf = xfile(newfid, Clean);
   327         if(waserror()){
   328                 xfile(newfid, Clunk);
   329                 nexterror();
   330         }
   331         next = nf->next;
   332         *nf = *of;
   333         nf->next = next;
   334         nf->fid = newfid;
   335         refxfs(nf->xf, 1);
   336         if(nf->len){
   337                 nf->ptr = ealloc(nf->len);
   338                 memmove(nf->ptr, of->ptr, nf->len);
   339         }else
   340                 nf->ptr = of->ptr;
   341         (*of->xf->s->clone)(of, nf);
   342         poperror();
   343         return nf;
   344 }
   345 
   346 void
   347 rwalk(void)
   348 {
   349         Xfile *f, *nf;
   350         Isofile *oldptr;
   351         int oldlen;
   352         Qid oldqid;
   353 
   354         rep->nwqid = 0;
   355         nf = nil;
   356         f = xfile(req->fid, Asis);
   357         if(req->fid != req->newfid)
   358                 f = nf = doclone(f, req->newfid);
   359 
   360         /* save old state in case of error */
   361         oldqid = f->qid;
   362         oldlen = f->len;
   363         oldptr = f->ptr;
   364         if(oldlen){
   365                 oldptr = ealloc(oldlen);
   366                 memmove(oldptr, f->ptr, oldlen);
   367         }
   368 
   369         if(waserror()){
   370                 if(nf != nil)
   371                         xfile(req->newfid, Clunk);
   372                 if(rep->nwqid == req->nwname){
   373                         if(oldlen)
   374                                 free(oldptr);
   375                 }else{
   376                         /* restore previous state */
   377                         f->qid = oldqid;
   378                         if(f->len)
   379                                 free(f->ptr);
   380                         f->ptr = oldptr;
   381                         f->len = oldlen;
   382                 }
   383                 if(rep->nwqid==req->nwname || rep->nwqid > 0){
   384                         err_msg[0] = '\0';
   385                         return;
   386                 }
   387                 nexterror();
   388         }
   389 
   390         for(rep->nwqid=0; rep->nwqid < req->nwname && rep->nwqid < MAXWELEM; rep->nwqid++){
   391                 chat("\twalking %s\n", req->wname[rep->nwqid]);
   392                 if(!(f->qid.type & QTDIR)){
   393                         chat("\tnot dir: type=%#x\n", f->qid.type);
   394                         error("walk in non-directory");
   395                 }
   396 
   397                 if(strcmp(req->wname[rep->nwqid], "..")==0){
   398                         if(f->qid.path != f->xf->rootqid.path)
   399                                 (*f->xf->s->walkup)(f);
   400                 }else
   401                         (*f->xf->s->walk)(f, req->wname[rep->nwqid]);
   402                 rep->wqid[rep->nwqid] = f->qid;
   403         }
   404         poperror();
   405         if(oldlen)
   406                 free(oldptr);
   407 }
   408 
   409 void
   410 ropen(void)
   411 {
   412         Xfile *f;
   413 
   414         f = xfile(req->fid, Asis);
   415         if(f->flags&Omodes)
   416                 error("open on open file");
   417         if(req->mode&ORCLOSE)
   418                 error("no removes");
   419         (*f->xf->s->open)(f, req->mode);
   420         f->flags = openflags(req->mode);
   421         rep->qid = f->qid;
   422         rep->iounit = 0;
   423 }
   424 
   425 void
   426 rcreate(void)
   427 {
   428         error("no creates");
   429 /*
   430         Xfile *f;
   431 
   432         if(strcmp(req->name, ".") == 0 || strcmp(req->name, "..") == 0)
   433                 error("create . or ..");
   434         f = xfile(req->fid, Asis);
   435         if(f->flags&Omodes)
   436                 error("create on open file");
   437         if(!(f->qid.path&CHDIR))
   438                 error("create in non-directory");
   439         (*f->xf->s->create)(f, req->name, req->perm, req->mode);
   440         chat("f->qid=0x%8.8lux...", f->qid.path);
   441         f->flags = openflags(req->mode);
   442         rep->qid = f->qid;
   443 */
   444 }
   445 
   446 void
   447 rread(void)
   448 {
   449         Xfile *f;
   450 
   451         f=xfile(req->fid, Asis);
   452         if (!(f->flags&Oread))
   453                 error("file not opened for reading");
   454         if(f->qid.type & QTDIR)
   455                 rep->count = (*f->xf->s->readdir)(f, (uchar*)fdata, req->offset, req->count);
   456         else
   457                 rep->count = (*f->xf->s->read)(f, fdata, req->offset, req->count);
   458         rep->data = fdata;
   459 }
   460 
   461 void
   462 rwrite(void)
   463 {
   464         Xfile *f;
   465 
   466         f=xfile(req->fid, Asis);
   467         if(!(f->flags&Owrite))
   468                 error("file not opened for writing");
   469         rep->count = (*f->xf->s->write)(f, req->data, req->offset, req->count);
   470 }
   471 
   472 void
   473 rclunk(void)
   474 {
   475         Xfile *f;
   476 
   477         if(!waserror()){
   478                 f = xfile(req->fid, Asis);
   479                 (*f->xf->s->clunk)(f);
   480                 poperror();
   481         }
   482         xfile(req->fid, Clunk);
   483 }
   484 
   485 void
   486 rremove(void)
   487 {
   488         error("no removes");
   489 }
   490 
   491 void
   492 rstat(void)
   493 {
   494         Xfile *f;
   495         Dir dir;
   496 
   497         chat("stat(fid=%d)...", req->fid);
   498         f=xfile(req->fid, Asis);
   499         setnames(&dir, fdata);
   500         (*f->xf->s->stat)(f, &dir);
   501         if(chatty)
   502                 showdir(2, &dir);
   503         rep->nstat = convD2M(&dir, statbuf, sizeof statbuf);
   504         rep->stat = statbuf;
   505 }
   506 
   507 void
   508 rwstat(void)
   509 {
   510         error("no wstat");
   511 }
   512 
   513 static int
   514 openflags(int mode)
   515 {
   516         int flags = 0;
   517 
   518         switch(mode & ~(OTRUNC|OCEXEC|ORCLOSE)){
   519         case OREAD:
   520         case OEXEC:
   521                 flags = Oread; break;
   522         case OWRITE:
   523                 flags = Owrite; break;
   524         case ORDWR:
   525                 flags = Oread|Owrite; break;
   526         }
   527         if(mode & ORCLOSE)
   528                 flags |= Orclose;
   529         return flags;
   530 }
   531 
   532 void
   533 showdir(int fd, Dir *s)
   534 {
   535         char a_time[32], m_time[32];
   536         char *p;
   537 
   538         strcpy(a_time, ctime(s->atime));
   539         if(p=strchr(a_time, '\n'))        /* assign = */
   540                 *p = 0;
   541         strcpy(m_time, ctime(s->mtime));
   542         if(p=strchr(m_time, '\n'))        /* assign = */
   543                 *p = 0;
   544         fprint(fd, "name=\"%s\" qid=(0x%llux,%lud) type=%d dev=%d \
   545 mode=0x%8.8lux=0%luo atime=%s mtime=%s length=%lld uid=\"%s\" gid=\"%s\"...",
   546                 s->name, s->qid.path, s->qid.vers, s->type, s->dev,
   547                 s->mode, s->mode,
   548                 a_time, m_time, s->length, s->uid, s->gid);
   549 }
   550 
   551 #define        SIZE        1024
   552 
   553 void
   554 chat(char *fmt, ...)
   555 {
   556         va_list arg;
   557 
   558         if(chatty){
   559                 va_start(arg, fmt);
   560                 vfprint(2, fmt, arg);
   561                 va_end(arg);
   562         }
   563 }
   564 
   565 void
   566 panic(int rflag, char *fmt, ...)
   567 {
   568         va_list arg;
   569         char buf[SIZE]; int n;
   570 
   571         n = sprint(buf, "%s %d: ", argv0, getpid());
   572         va_start(arg, fmt);
   573         vseprint(buf+n, buf+SIZE, fmt, arg);
   574         va_end(arg);
   575         fprint(2, (rflag ? "%s: %r\n" : "%s\n"), buf);
   576         if(chatty){
   577                 fprint(2, "abort\n");
   578                 abort();
   579         }
   580         exits("panic");
   581 }