home *** CD-ROM | disk | FTP | other *** search
/ minnie.tuhs.org / unixen.tar / unixen / PDP-11 / Distributions / ucb / spencer_2bsd.tar.gz / 2bsd.tar / src / net / sub.c < prev   
C/C++ Source or Header  |  1980-02-17  |  15KB  |  667 lines

  1. /* Copyright (c) 1979 Regents of the University of California */
  2. # include "defs.h"
  3. # include "config.h"
  4.  
  5. char netcmd[] =        NETCMD;
  6. char resfile[]=     RESFILE;
  7. char senddir[] =    SENDDIR;
  8. char logfile[]=     LOGFILE;
  9. char Bsh[]=         BINSH;
  10. char mailcmd[]=     MMAILCMD;
  11. char writecmd[]=      MWRITECMD;
  12.  
  13.  
  14. int debugflg = DBV;        /* debug flag */
  15. int datasize = SIZE;        /* best if mult of 512 */
  16. char tokval[BFS];
  17. FILE *cfile;
  18. char vaxtovax = 0;
  19. /*
  20.     speeds baud setting
  21.     300    7
  22.     1200    9
  23.     9600    13
  24.     */
  25. int linkspeed = LINKS;
  26. char local = LOCAL;
  27.  
  28.  
  29. struct tokstruct toktab[]= {
  30.     "machine",    MACHINE,
  31.     "login",    LOGIN,
  32.     "password",    PASSWORD,
  33.     "notify",    NOTIFY,
  34.     "command",    COMMAND,
  35.     "yes",        YES,
  36.     "y",        YES,
  37.     "no",        NO,
  38.     "n",        NO,
  39.     "default",    DEFAULT,
  40.     "write",    WRITE,
  41.     "force",    FORCE,
  42.     "local",    LOCALTOK,
  43.     "speed",    SPEED,
  44.     "link",        LINK,
  45.     "vaxtovax",    VAXTOVAX,
  46.     "length",    LENGTH,
  47.     "debug",    DEBUGTOK,
  48.     "time",        ALTIME,
  49.     "count",    ALCOUNT,
  50.     0,        0
  51.     };
  52. passwdent(){
  53.     register char *u;
  54.     register struct passwd *pwd;
  55.     pwd = getpwuid(getuid());
  56.     if(pwd == NULL){
  57.         err("Bad uid\n");
  58.         return;
  59.         }
  60.     strcpy(status.localname,pwd->pw_name);
  61.     status.muid = guid(pwd->pw_uid,pwd->pw_gid);
  62.     status.mgid = pwd->pw_gid;
  63.     if(isdigit(pwd->pw_gecos[0]))status.jobno = atoi(pwd->pw_gecos);
  64.     else status.jobno = 32767;
  65.     strcpy(status.dir,pwd->pw_dir);
  66.     u = pwd->pw_shell;
  67.     if(u[0] == 0 || strcmp("sh",u+strlen(u)-2) != 0)u= Bsh;
  68.     strcpy(status.loginshell,u);
  69.     }
  70. promptlogin(){
  71.     register char *p;
  72.     char buf[BFS];
  73.     FILE *wf;
  74.     int c;
  75.     struct sgttyb stt;
  76.     int oflag;
  77.     if(status.mpasswd[0] == 0 || status.login[0] == 0 || status.force){
  78.         wf = fopen("/dev/tty","r");
  79.         if(wf != NULL){
  80.             if(status.login[0]==0 || status.force){
  81.                 printf("Name (%s): ",status.localname);
  82.                 if(fgets(buf, BFS, wf) != buf){
  83.                     perror("fgets");
  84.                     exit(1);
  85.                     }
  86.                 c = strlen(buf);
  87.                 buf[c > 0 ? c-1 : 0] = 0;
  88.                 if(c > 10){
  89.                     err("Login name too long.\n");
  90.                     exit(1);
  91.                     }
  92.                 if(member(buf,' ')){
  93.                     err("Login names don't have blanks in them.\n");
  94.                     exit(1);
  95.                     }
  96.                 if(buf[0] == 0)strcpy(buf,status.localname);
  97.                 strcpy(status.login,buf);
  98.                 }
  99.             if(strcmp(status.login,"network") != 0
  100.                 && (status.mpasswd[0]== 0 || status.force)){
  101.                 sprintf(buf,"Password (%s):",status.login);
  102.                 strcpy(status.mpasswd,getpass(buf));
  103.                 }
  104.             fclose(wf);
  105.             }
  106.         }
  107.     if(status.login[0] == 0) strcpy(status.login,status.localname);
  108.     if(status.mpasswd[0] == 0)strcpy(status.mpasswd,"\"\"");
  109.     status.force = 0;
  110.     }
  111.     
  112. /*
  113.     called in netdaemon and debugging software,
  114.     handles parameter lists to setup
  115.     remote machine and pipes
  116. */
  117. setupdaemon(argc,argv)
  118.   char **argv; {
  119.     remote = argc > 1 ? lookup(argv[1]) : getremote(local);
  120.     if(argc == 4){    /* simulate using pipes */
  121.         readfd = atoi(argv[2]);
  122.         writefd = atoi(argv[3]);
  123.         pipesim++;
  124.         }
  125.     initdaemon();
  126.     }
  127. setup(str)
  128.   char *str; {
  129.     struct sgttyb stt;
  130.     static char readbuf[BUFSIZ],writebuf[BUFSIZ];
  131.     if(str == 0 || str[0] == 0){
  132.         err("invalid net device\n");
  133.         exit(1);
  134.         }
  135.     masterseqno = 1;
  136.     readtty = pipesim ? fdopen(readfd,"r") : fopen(str,"r");
  137.     if(readtty == NULL){
  138.         perror(str);
  139.         exit(1);
  140.         }
  141.     writetty = pipesim ? fdopen(writefd,"w") : fopen(str,"w");
  142.     if(writetty == NULL){
  143.         perror(str);
  144.         exit(1);
  145.         }
  146.     if(!pipesim){
  147.         /* set exclusive use for line */
  148.         if(ioctl(fileno(readtty),TIOCEXCL,&stt) != 0 ||
  149.             gtty(fileno(readtty),&stt) < 0){
  150.             perror(str);
  151.             exit(1);
  152.             }
  153.         stt.sg_ispeed = stt.sg_ospeed = linkspeed;  /* user-set baud */
  154.         stt.sg_erase = stt.sg_kill = 0;        /* erase and kill off */
  155.         stt.sg_flags = ANYP;    /* even and odd parity, off everything else */
  156.         if(stty(fileno(readtty),&stt) < 0){
  157.             perror(str);
  158.             exit(1);
  159.             }
  160.         }
  161.     setbuf(readtty,readbuf);
  162.     setbuf(writetty,writebuf);
  163.     }
  164. /* passwords work as follows:
  165.    passwd = "\n" means no password
  166.    */
  167. /* table of netrc options
  168.     option            default
  169.     ------            -------
  170.     default            default machine
  171.     login string        current login
  172.     password string        -
  173.     notify yes/no        yes
  174.     write yes/no        yes
  175.     command string        -
  176.     force yes/no        no
  177. */
  178.  
  179. /*
  180.     Fabry has suggested that machine names be more general:
  181.     that you be able to say:
  182.     cory:    fabry on Cory
  183.     caf:    caf on Cory
  184.     c:    fabry on C
  185.  
  186.     so the formulation would look like:
  187.  
  188.     default key
  189.     key: machine login passwd ...
  190.     key: ....
  191.  
  192.     and so on
  193.  
  194.     Gould has suggested the format be:
  195.  
  196.     pseudo cory     real Cory     login fabry
  197.     pseudo caf     real Cory     login caf
  198.     pseudo c     real C         login fabry
  199. */
  200.  
  201. /* init file format local C remote A
  202.     default A
  203.     machine A    local C link /dev/net-A    speed 9
  204.     machine Cory local C link /dev/net-Cory speed 9
  205.     
  206.     if remote == 0, default is A
  207.     also options:
  208.         vaxtovax, length, debug
  209.     */
  210. initdaemon(){
  211.     long timev;
  212.     int timei;
  213.     cfile = fopen(INITFILE,"r");
  214.     getfile();
  215.     err("remote %c local %c link %s speed %d vtov %d length %d\n",
  216.     remote,local,device,linkspeed,vaxtovax,datasize);
  217.     err("debug %d time %d count %d\n",debugflg,atime,maxbread);
  218.     setup(device);
  219.     timev = gettime();
  220.     timei = timev >> 16;
  221.     srand(timei);
  222. # ifdef VAX
  223.     if(machtype[local - 'a'] != M_VAX)
  224. # endif
  225. # ifdef CORY
  226.     if(machtype[local - 'a'] != M_CORY)
  227. # endif
  228. # ifdef CC
  229.     if(machtype[local -'a'] != M_CC && machtype[local - 'a'] != M_SRC)
  230. # endif
  231.         err("Machine type disagrees with local machine\n");
  232.     }
  233. commandfile(){
  234.     char *hdir, buf[BFS*2];
  235.     hdir = getenv("HOME");
  236.     if(hdir == 0)hdir = ".";
  237.     if(strcmp(hdir,"/") == 0)return;
  238.     sprintf(buf,"%s/.netrc",hdir);
  239. /*
  240.     debug("file %s",buf);
  241. */
  242.     cfile = fopen(buf,"r");
  243.     getfile();
  244.     }
  245. getfile(){
  246.     int t;
  247.     if(cfile == NULL)return;
  248.     if(fstat(fileno(cfile),&statbuf) < 0 || (statbuf.st_mode & 0444) == 0)
  249.         return;
  250.     while((t = token())){
  251.         switch(t){
  252.         case DEFAULT:
  253.             if(token() == ID && remote == 0)remote = lookup(tokval);
  254.             /*
  255.             debug("rem %c\n",remote);
  256.             */
  257.             break;
  258.         case MACHINE:
  259.             if(remote == 0)remote = getremote(local);
  260.             if(token() != ID)continue;
  261.             if(remote != lookup(tokval))continue;
  262.             /* this is the entry for the remote mach we want */
  263.             getnetline();
  264.             goto out;
  265.             break;
  266.         }
  267.         }
  268. out:
  269.     fclose(cfile);
  270.     return;
  271.     }
  272. getnetline(){
  273.     int t;
  274.     while((t = token())){
  275.         switch(t){
  276.         case MACHINE: return;
  277.         case LOGIN:
  278.             if(token() && status.login[0] == 0)
  279.                 strcpy(status.login,tokval);
  280.             break;
  281.         case PASSWORD:
  282.             if(fstat(fileno(cfile),&statbuf) >= 0
  283.             && (statbuf.st_mode & 077) != 0){
  284.                 err("Error - .netrc file not correct mode.\n");
  285.                 err("Remove password or correct mode.\n");
  286.                 exit(1);
  287.                 }
  288.             if(token() && status.mpasswd[0] == 0)
  289.                 strcpy(status.mpasswd,tokval);
  290.             /*
  291.             debug("mp:%s:%s\n",status.mpasswd,tokval);
  292.             */
  293.             break;
  294.         case NOTIFY:
  295.             status.nonotify = token() == NO;
  296.             break;
  297.         case WRITE:
  298.             status.nowrite = token() == NO;
  299.             break;
  300.         case COMMAND:
  301.             if(status.defcmd[0] == 0 && token())
  302.                 strcpy(status.defcmd,tokval);
  303.             break;
  304.         case FORCE:
  305.             status.force = token() == YES;
  306.             break;
  307.         case LOCALTOK:
  308.             if(token())local = lookup(tokval);
  309.             break;
  310.         case LINK:
  311.             if(token())strcpy(device,tokval);
  312.             break;
  313.         case SPEED:
  314.             if(token())linkspeed = atoi(tokval);
  315.             break;
  316.         case VAXTOVAX:
  317.             vaxtovax++;
  318.             break;
  319.         case LENGTH:
  320.             if(token())datasize = atoi(tokval);
  321.             break;
  322.         case DEBUGTOK:
  323.             debugflg++;
  324.             break;
  325.         case ALTIME:
  326.             if(token())atime = atoi(tokval);
  327.             break;
  328.         case ALCOUNT:
  329.             if(token())maxbread = atoi(tokval);
  330.             break;
  331.         default:
  332.             err("Unknown .netrc option %s\n",tokval);    
  333.             break;
  334.         }
  335.         }
  336.     }
  337. token(){    /* returns next token in cfile, 0 on EOF */
  338.     char *p;
  339.     int c;
  340.     if(feof(cfile))return(0);
  341.     while((c = getc(cfile)) != EOF && (c == '\n' || c == '\t'
  342.         || c == ' ' || c == ','));
  343.     /* next char begins token */
  344.     if(c == EOF)return(0);
  345.     p = tokval;
  346.     if(c == '"'){    /* process quoted string */
  347.         while((c = getc(cfile)) != EOF && c != '"'){
  348.             if(c == '\\')c = getc(cfile);
  349.             *p++ = c;
  350.             }
  351.         }
  352.     else {
  353.         *p++ = c;
  354.         while((c = getc(cfile)) != EOF && c != '\n' && c != '\t' 
  355.             && c != ' ' && c != ','){
  356.             if(c == '\\')c = getc(cfile);
  357.             *p++ = c;
  358.             }
  359.         }
  360.     *p = 0;
  361.     if(tokval[0] == 0)return(0);
  362. /*
  363.     debug("tok %s",tokval);
  364. */
  365.     return(tlookup(tokval));
  366.     }
  367. tlookup(str)
  368.   char *str; {
  369.     struct tokstruct *p;
  370.     for(p = toktab; p->tokstr; p++)
  371.         if(streql(p->tokstr,str) == 0){
  372.             return(p->tval);
  373.             }
  374.     return(ID);
  375.     }
  376. /* just like strcmp except upper- and lower-case are ignored */
  377. streql(s1,s2)
  378.   char *s1, *s2; {
  379.     char a,b;
  380.     while(*s1 && *s2){
  381.         a = isupper(*s1) ? tolower(*s1) : *s1;
  382.         b = isupper(*s2) ? tolower(*s2) : *s2;
  383.         if(a < b)return(-1);
  384.         if(a > b)return(1);
  385.         s1++, s2++;
  386.         }
  387.     if(*s2)return(-1);
  388.     if(*s1)return(1);
  389.     return(0);
  390.     }
  391. /* determine through machine */
  392. gothru(from,to){
  393.     register int i;
  394.     switch(from){
  395.     case 'a':    i = configA[to-'a']; break;
  396.     case 'b':    i = configB[to-'a']; break;
  397.     case 'c':    i = configC[to-'a']; break;
  398.     case 'd':    i = configD[to-'a']; break;
  399.     case 'e':    i = configE[to-'a']; break;
  400.     case 'i':    i = configI[to-'a']; break;
  401.     case 'q':    i = configQ[to-'a']; break;
  402.     case 's':    i = configS[to-'a']; break;
  403.     case 'v':    i = configV[to-'a']; break;
  404.     case 'y':    i = configY[to-'a']; break;
  405.     default:    i = 0; break;
  406.     }
  407.     return(i);
  408.     }
  409. /* note the pointers to returned values */
  410. harg(ans,pargc,pargv)
  411.   char *ans,*pargc,***pargv;{
  412.     if((*pargv)[0][2])        /* no space */
  413.         strcpy(ans,(*pargv)[0] + 2);
  414.     else {                /* space, get next arg */
  415.         strcpy(ans,(*pargv)[1]);
  416.         (*pargc)--;
  417.         (*pargv)++;
  418.         }
  419.     }
  420.  
  421. static struct stat x;
  422. static struct direct y;
  423. static FILE *file;
  424. static int off = -1;
  425.  
  426.  
  427. /* these three routines gwd, cat, ckroot and 
  428.    data structures x, y, off, do a pwd to string name */
  429. gwd(name)
  430.   register char *name; {
  431.     *name = 0;
  432.     for(;;){
  433.         stat(".",&x);
  434.         if((file = fopen("..","r")) == NULL)break;
  435.         do {
  436.             if(fread(&y,1,sizeof y,file) != sizeof y)break;
  437.             } while(y.d_ino != x.st_ino);
  438.         fclose(file);
  439.         if(y.d_ino == ROOTINO){
  440.             ckroot(name);
  441.             break;
  442.             }
  443.         if(cat(name))break;
  444.         chdir("..");
  445.         }
  446.     chdir(name);
  447.     }
  448.  
  449. cat(name)
  450.   register char *name; {        /* return 1 to exit */
  451.     register int i,j;
  452.     i = -1;
  453.     while(y.d_name[++i] != 0);
  454.     if((off+i+2) > 511)return(1);
  455.     for(j = off +1; j >= 0; --j)name[j+i+1] = name[j];
  456.     off = i + off + 1;
  457.     name[i] = '/';
  458.     for(--i; i>= 0; --i)name[i] = y.d_name[i];
  459.     return(0);
  460.     }
  461.  
  462. ckroot(name)
  463.   char *name; {
  464.     register int i;
  465.     if(stat(y.d_name,&x) < 0)return;
  466.     i = x.st_dev;
  467.     if(chdir("/") < 0)return;
  468.     if((file = fopen("/","r")) == NULL)return;
  469.     do {
  470.         if(fread(&y,1,sizeof y,file) != sizeof y)return;
  471.         if(y.d_ino == 0)continue;
  472.         if(stat(y.d_name,&x) < 0)return;
  473.         } while(x.st_dev!=i || (x.st_mode&S_IFMT)!=S_IFDIR);
  474.     if(strcmp(y.d_name,".") != 0 && strcmp(y.d_name,"..") != 0)
  475.         if(cat(name))return;
  476.     i = strlen(name);
  477.     name[i+1] = 0;
  478.     while(--i >= 0)name[i + 1] = name[i];
  479.     name[0] = '/';
  480.     return;
  481.     }
  482.  
  483.  
  484. /* prints out commands before executing them */
  485. /*VARARGS0*/
  486. mexecl(s)
  487.   char *s;{
  488.     int *p = (int *)&s;
  489.     register int i;
  490.     if(debugflg){
  491.         for(i=0; p[i]; i++)err("%s ",p[i]);
  492.         putc('\n',stderr);
  493.         }
  494.     execl(p[0],p[1],p[2],p[3],p[4],p[5],p[6],p[7],p[8],p[9],p[10],p[11],
  495.     p[12],p[13],p[14],p[15],0);
  496.     perror(p[0]);
  497.     }
  498. /* prints out commands before executing them */
  499. mexecv(s,p)
  500.   register char *s, **p;{
  501.     register int i;
  502.     if(debugflg){
  503.         err("%s ",s);
  504.         for(i=0; p[i]; i++)err("%s ",p[i]);
  505.         putc('\n',stderr);
  506.         }
  507.     execv(s,p);
  508.     perror("execv");
  509.     }
  510.  
  511. /*VARARGS0*/
  512. /* fills in -l - -p from commands like rcp */
  513. /* must be called with at least two arguments */
  514. kexecl(s)
  515.   char *s;    {
  516.     char *a[20], i = 2, j = 2;
  517.     char **p = (char **)&s;
  518.     a[0] = p[0];
  519.     a[1] = p[1];
  520.     if(status.login[0]){
  521.         a[i++] = "-l";
  522.         a[i++] = status.login;
  523.         }
  524.     if(status.mpasswd[0]){
  525.         a[i++] = "-p";
  526.         a[i++] = status.mpasswd;
  527.         }
  528.     if(status.nonotify)a[i++] = "-n";
  529.     if(status.force)a[i++] = "-f";
  530.     while(p[j])a[i++] = p[j++];
  531.     a[i] = 0;
  532.     mexecl(a[0],a[1],a[2],a[3],a[4],a[5],a[6],a[7],a[8],a[9],a[10],a[11],
  533.     a[12],a[13],a[14],a[15],0);
  534.     }
  535.  
  536. analyze(S,f)
  537.   char *S;
  538.   register struct fd *f; {
  539.     register char *file;
  540.     char work[FNS], *s, c0,c1,c2,c3;
  541.     s = work;
  542.     strcpy(s,S);
  543.     f->mach = local;
  544.     file = s;
  545.     if(member(s,':')){    /* name specified */
  546.         while(*s && *s != ':')s++;
  547.         *s = 0;
  548.         f->mach = lookup(file);
  549.         if(f->mach == 0){
  550.             err("Unknown machine %s",file);
  551.             exit(1);
  552.             }
  553.         while(*++s && *s == ':');
  554.         file = s;
  555.         }
  556.     else {
  557.         c0 = *s++;
  558.         c1 = *s++;
  559.         c2 = *s++;
  560.         c3 = *s++;
  561.         if(c0 == '/' && c1 != '/' && islower(c1))
  562.             if(c2 == '/')f->mach = 'y';        /* Cory name */
  563.             else if(c3 == '/')f->mach = c1;        /* CC name */
  564.         }
  565.     f->fn = calloc(strlen(file)+1,1);
  566.     strcpy(f->fn,file);
  567.     }
  568.  
  569. /* returns a single character for machine S */
  570. lookup(s)
  571.   register char *s; {
  572.     register struct tt *t;
  573.     if(strlen(s) == 1)return(isupper(*s) ? tolower(*s) : *s);
  574.     for(t = table; t->bigname; t++)
  575.         if(streql(s,t->bigname) == 0)return(t->lname);
  576.     return(0);
  577.     }
  578.  
  579. /* returns a long name (string) for single character machine c */
  580. char *longname(c)
  581.   register char c;
  582.     {
  583.     register struct tt *t;
  584.     if(c == 0)return("UNKNOWN");
  585.     for(t = table; t->bigname; t++)
  586.         if(c == t->lname)return(t->bigname);
  587.     return("UNKNOWN");
  588.     }
  589. /*VARARGS0*/
  590. error(s,a,b,c,d,e,f,g,h)
  591. char *s; {
  592.     char buf[10];
  593.     if(remote != 0) sprintf(buf,"%s",longname(remote));
  594.     else buf[0] = 0;
  595.     fflush(stdout);
  596.     if(debugflg){
  597.         fprintf(stderr,s,a,b,c,d,e,f,g,h);
  598.         putc('\n',stderr);
  599.         }
  600.     addtolog(remote,"Err %s: ",buf);
  601.     addtolog(remote,s,a,b,c,d,e,f,g,h);
  602.     addtolog(remote,"\n");
  603.     }
  604. /*VARARGS0*/
  605. debug(s,a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,t)
  606. char *s; {
  607.     if(debugflg){
  608.         printf(s,a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,t);
  609.         putchar('\n');
  610.         }
  611.     }
  612.  
  613. member(s,c)
  614. register char *s, c; {
  615.     while(*s)if(*s++ == c)return(1);
  616.     return(0);
  617.     }
  618. /* this is really not right - we should use the rcslog format */
  619. /* also, the user must be able to write on the
  620.    public logfile to get error messages such as
  621.    directory not found after he has
  622.    setuid'd from root
  623. */
  624. /*VARARGS0*/
  625. addtolog(mach,s,a,b,c,d,e,f,g,h,i,j,k,l,m,n)
  626. char *s;
  627. {
  628.     static FILE *log = NULL;
  629.     logfile[strlen(logfile)-1] = mach;
  630.     if(log == NULL){
  631.         if(stat(logfile,&statbuf) < 0)return;
  632.         log = fopen(logfile,"a");
  633.         }
  634.     if(log == NULL)return;
  635.     fseek(log,0L,2);
  636.     fprintf(log,s,a,b,c,d,e,f,g,h,i,j,k,l,m,n);
  637.     fflush(log);
  638.     }
  639. /* return a static string with the form "X hrs X mins X secs" */
  640. /* t is # of secs */
  641. char *comptime(t)
  642.   long t; {
  643.     static char str[30];
  644.     char buf[20];
  645.     long w;
  646.     str[0] = 0;
  647.     w = t/3600L;
  648.     if(w > 0L){
  649.         sprintf(buf,"%ld hr ",w);
  650.         strcat(str,buf);
  651.         }
  652.     t = t % 3600L;
  653.     w = t/60L;
  654.     if(w > 0L){
  655.         sprintf(buf,"%ld min ",w);
  656.         strcat(str,buf);
  657.         }
  658.     t = t % 60L;
  659.     sprintf(buf,"%ld sec",t);
  660.     strcat(str,buf);
  661.     return(str);
  662.     }
  663. /* VARARGS0 */
  664. static err(s,a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r) {
  665.     fprintf(stderr,s,a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r);
  666.     }
  667.