#include "fs.h" #include #define SPOOL "usr0:" #define USER "news" struct passwd *pw ; #define ERRLOG "FSDLOG" char *logfile = ERRLOG ; FILE *errlog = NULL ; int debug = 1; eprintf(fmt,a,b,c,d,e,f) char *fmt, *a, *b, *c, *d, *e, *f ; { if(!debug) return ; if(errlog == NULL) { close(2) ; if((errlog = fopen(ERRLOG,"a")) == NULL) return ; } fprintf(errlog,fmt,a,b,c,d,e,f) ; fflush(errlog) ; } main(argc,argv) int argc ; char **argv ; { struct servent *sp ; struct sockaddr_in from, sin ; int f, g ; struct passwd *pw ; if((argc > 1) && !strcmp(argv[1],"-d")) { debug++ ; if(argc > 2) logfile = argv[2] ; fprintf(stderr,"All error and tracing to %s\n",logfile) ; } if(debug) eprintf("fsd: started\n") ; if((pw = getpwnam(USER)) == NULL) { fprintf(stderr,"%s: no such user to set to?\n",USER) ; exit(1) ; } if(chdir(SPOOL) < 0) { perror("chdir") ; exit(1) ; } bzero(&sin,sizeof sin) ; if((sp = getservbyname(SVC,PROTO)) == NULL) { fprintf(stderr,"%s: %s/%s: unknown service\n", *argv,SVC,PROTO) ; exit(1) ; } sin.sin_family = AF_INET ; sin.sin_port = sp->s_port ; if((f = socket(AF_INET,SOCK_STREAM,0)) < 0) { perror("socket") ; exit(1) ; } if(bind(f,(caddr_t)&sin,sizeof sin,0) < 0) { perror("bind") ; exit(1) ; } listen(f,5) ; for(;;) { int i, szfrom ; szfrom = sizeof from ; if((g = accept(f,&from,&szfrom)) < 0) { if(errno != EINTR) perror("accept") ; continue ; } switch(fork()) { case -1 : close(g) ; break ; case 0 : /* close(f) ; */ doit(g) ; exit(1) ; default : /* close(g) ; */ break ; } while(wait3(&i,WNOHANG,0) > 0) ; } /* NOTREACHED */ } u_long gtulong(s) int s; { u_long l; char buf[4]; register char *bp; register int i; if(_read(s,buf,sizeof buf) == NULL) { close(s) ; exit(0) ; } l = (buf[3] & 0377) + ((buf[2] & 0377) << 8) + ((buf[1] & 0377) << 16) + ((buf[0] & 0377) << 24); return( l ); } /* gtulong */ u_short gtushort(s) int s; { u_short sh; char buf[2]; if(_read(s,buf,sizeof buf) == NULL) { close(s) ; exit(0) ; } sh = ((buf[0] & 0377) << 8) + (buf[1] & 0377); return( sh ); } /* gtushort */ doit(s) int s ; { static FILE *fps[_NFILE] ; FILE *fp ; if(debug) eprintf("fsd: DOIT\n") ; /* setuid(pw->pw_uid) ; setgid(pw->pw_gid) ; */ bzero((char *)fps,sizeof(fps)) ; if((fp = fdopen(s,"r+")) == NULL) { close(s) ; exit(1) ; } again: clearerr(fp) ; rewind(fp) ; /* if(fread(&req,sizeof req,1,fp) == NULL) /* { /* close(s) ; /* exit(0) ; /* } */ req.type = gtulong(s); req.flags = gtushort(s); req.fd = gtushort(s); req.offset = gtulong(s); req.count = gtulong(s); if(!debug) eprintf("fsd: req 0%o\n",req.type) ; switch(req.type) { case RFOPEN : openit(fp,fps,&req) ; break ; case RFREAD : readit(fp,fps,&req) ; break ; case RFCLOSE : closeit(fp,fps,&req) ; break ; case RFSEEK : seekit(fp,fps,&req) ; break ; case RFACCESS: acesit(fp,fps,&req) ; break ; default : if(debug) eprintf("fsd: bad request 0%o?\n",req.type) ; break ; } goto again ; } rerror(fp,val) FILE *fp ;int val ; { rewind(fp) ; fprintf(fp,"%c%d\n",ERR,val) ; fflush(fp) ; return ; } rok(fp,val) FILE *fp ; int val ; { rewind(fp) ; fprintf(fp,"%c%d\n",REPLY,val) ; fflush(fp) ; return ; } openit(fp,fps,rp) FILE *fp, *fps[] ; struct rreq *rp ; { int i ; char fbuf[BUFSIZ] ; char *fname ; fname = fbuf ; for(i=0 ; fps[i] != NULL ; i++) if((i+1) == _NFILE) { rerror(fp,EMFILE) ; return ; } if(fgets(fname,BUFSIZ,fp) == NULL) { rerror(fp,EINVAL) ; return ; } /** fname[strlen(fname)-1] = '\0' ; **/ { int i; i = strlen(fname) - 1; fname[i] = '\0'; } if(debug) eprintf("fsd: fname = %s\n",fname) ; /* if(strncmp(fname,SPOOL,strlen(SPOOL)) == 0) fname += strlen(SPOOL) ; */ if((fps[i] = fopen(fname,"r")) == NULL) { rerror(fp,errno) ; if(debug) eprintf("fsd: open err %d\n",errno) ; return ; } if(debug) eprintf("fsd: open ok %d\n",i) ; rok(fp,i) ; return ; } acesit(fp,fps,rp) FILE *fp, *fps[] ; struct rreq *rp ; { int i ; char fbuf[BUFSIZ] ; char *fname ; fname = fbuf ; if(fgets(fname,BUFSIZ,fp) == NULL) { rerror(fp,EINVAL) ; return ; } /** fname[strlen(fname)-1] = '\0' ; **/ { int i; i = strlen(fname) - 1; fname[i] = '\0'; } if(debug) eprintf("fsd: access: fname = %s\n",fname) ; if((i = access(fname,rp->offset)) < 0) { rerror(fp,errno) ; if(debug) eprintf("fsd: access(%s,%d): err %d\n", fname,rp->offset,errno); return ; } if(debug) eprintf("fsd: access: ok %d\n",i) ; rok(fp,i) ; return ; } readit(fp,fps,rp) FILE *fp, *fps[] ; struct rreq *rp ; { int n ; if(debug) eprintf("fsd:read fd %d count %d\n",rp->fd,rp->count) ; if((rp->fd < 0) || (rp->fd > _NFILE) || (fps[rp->fd] == NULL)) { rerror(fp,EINVAL) ; return ; } if((rp->count < 0) || (rp->count > BUFSIZ)) { rerror(fp,EINVAL) ; return ; } if(rp->count == 0) { rok(fp,0) ; return ; } if((n = fread(buf,sizeof(buf[0]),rp->count,fps[rp->fd])) < 0) { if(debug) eprintf("fsd: read err %d\n",errno) ; rerror(fp,errno) ; return ; } if(debug) eprintf("fsd: read ok %d\n",n) ; rok(fp,n) ; if(n > 0) write(fileno(fp),buf,n) ; return ; } closeit(fp,fps,rp) FILE *fp, *fps[] ; struct rreq *rp ; { int n ; if(debug) eprintf("fsd:close fd %d\n",rp->fd) ; if((rp->fd < 0) || (rp->fd > _NFILE) || (fps[rp->fd] == NULL)) { rerror(fp,EINVAL) ; return ; } if((n = fclose(fps[rp->fd])) == EOF) { if(debug) eprintf("fsd: close err %d\n",errno) ; rerror(fp,errno) ; return ; } if(debug) eprintf("fsd: close ok\n") ; fps[rp->fd] = NULL ; rok(fp,0) ; return ; } seekit(fp,fps,rp) FILE *fp, *fps[] ; struct rreq *rp ; { int n ; if(debug) eprintf("fsd:seek fd %d off %d ptr %d\n", rp->fd,rp->offset,rp->count) ; if((rp->fd < 0) || (rp->fd > _NFILE) || (fps[rp->fd] == NULL)) { rerror(fp,EINVAL) ; return ; } if(fseek(fps[rp->fd],rp->offset,rp->count) < 0) { if(debug) eprintf("fsd: seek err %d\n",errno) ; rerror(fp,errno) ; return ; } if(debug) eprintf("fsd: seek ok\n") ; rok(fp,0) ; return ; }