date and time created 83/08/05 13:34:56 by sam
[unix-history] / usr / src / old / cu / cu.c
index 6c3e9a1..dbe01bd 100644 (file)
@@ -1,12 +1,30 @@
-static char *sccsid = "@(#)cu.c        4.1 (Berkeley) %G%";
+static char *sccsid = "@(#)cu.c        4.7 (Berkeley) 82/10/21";
+
 #include <stdio.h>
 #include <signal.h>
 #include <sgtty.h>
 #include <stdio.h>
 #include <signal.h>
 #include <sgtty.h>
+
+/*
+ * defs that come from uucp.h
+ */
+#define NAMESIZE 15
+#define FAIL -1
+#define SAME 0
+#define SLCKTIME 5400  /* system/device timeout (LCK.. files) in seconds */
+#define ASSERT(e, f, v) if (!(e)) {\
+       fprintf(stderr, "AERROR - (%s) ", "e");\
+       fprintf(stderr, f, v);\
+       cleanup(FAIL);\
+}
+
 /*
 /*
- *     cu telno [-t] [-s speed] [-l line] [-a acu]
+ *     cu telno [-t] [-s speed] [-l line] [-a acu] [-p]
  *
  *     -t is for dial-out to terminal.
  *
  *     -t is for dial-out to terminal.
- *     speeds are: 110, 134, 150, 300, 1200. 300 is default.
+ *     speeds are: 110, 134, 150, 300, 1200, 2400. 300 is default.
+ *
+ *     -p says strip parity of characters transmitted.  (to compensate
+ *     for c100's)
  *
  *     Escape with `~' at beginning of line.
  *     Ordinary diversions are ~<, ~> and ~>>.
  *
  *     Escape with `~' at beginning of line.
  *     Ordinary diversions are ~<, ~> and ~>>.
@@ -40,7 +58,8 @@ char  *connmsg[] = {
        "acu access",
        "tty access",
        "tty hung",
        "acu access",
        "tty access",
        "tty hung",
-       "usage: cu telno [-t] [-s speed] [-l line] [-a acu]"
+       "usage: cu telno [-t] [-s speed] [-l line] [-a acu]",
+       "lock failed: line busy"
 };
 
 rdc(ds) {
 };
 
 rdc(ds) {
@@ -83,6 +102,9 @@ sig14()
 int    dout;
 int    nhup;
 int    dbflag;
 int    dout;
 int    nhup;
 int    dbflag;
+int    pflag;          /* strip parity on chars sent to remote */
+int    nullbrk;        /* turn breaks (nulls) into dels */
+int    pipes[2] = { -1, -1 };
 
 /*
  *     main: get connection, set speed for line.
 
 /*
  *     main: get connection, set speed for line.
@@ -96,8 +118,12 @@ char *av[];
        int speed;
        char *telno;
        struct sgttyb stbuf;
        int speed;
        char *telno;
        struct sgttyb stbuf;
+       int cleanup();
 
        signal(SIGALRM, sig14);
 
        signal(SIGALRM, sig14);
+       signal(SIGINT, cleanup);
+       signal(SIGHUP, cleanup);
+       signal(SIGQUIT, cleanup);
        if (ac < 2) {
                prf(connmsg[8]);
                exit(8);
        if (ac < 2) {
                prf(connmsg[8]);
                exit(8);
@@ -110,9 +136,15 @@ char *av[];
                        dout = 1;
                        --ac;
                        continue;
                        dout = 1;
                        --ac;
                        continue;
+               case 'b':
+                       nullbrk++;
+                       continue;
                case 'd':
                        dbflag++;
                        continue;
                case 'd':
                        dbflag++;
                        continue;
+               case 'p':
+                       pflag++;
+                       continue;
                case 's':
                        lspeed = av[2]; ++av; --ac;
                        break;
                case 's':
                        lspeed = av[2]; ++av; --ac;
                        break;
@@ -137,7 +169,7 @@ char *av[];
        ln = conn(devcul, devcua, telno);
        if (ln < 0) {
                prf("Connect failed: %s",connmsg[-ln]);
        ln = conn(devcul, devcua, telno);
        if (ln < 0) {
                prf("Connect failed: %s",connmsg[-ln]);
-               exit(-ln);
+               cleanup(-ln);
        }
        switch(atoi(lspeed)) {
        case 110:
        }
        switch(atoi(lspeed)) {
        case 110:
@@ -149,6 +181,8 @@ char *av[];
                speed = B300;break;
        case 1200:
                speed = B1200;break;
                speed = B300;break;
        case 1200:
                speed = B1200;break;
+       case 2400:
+               speed = B2400;break;
        }
        stbuf.sg_ispeed = speed;
        stbuf.sg_ospeed = speed;
        }
        stbuf.sg_ispeed = speed;
        stbuf.sg_ospeed = speed;
@@ -161,6 +195,7 @@ char *av[];
        ioctl(ln, TIOCEXCL, (struct sgttyb *)NULL);
        ioctl(ln, TIOCHPCL, (struct sgttyb *)NULL);
        prf("Connected");
        ioctl(ln, TIOCEXCL, (struct sgttyb *)NULL);
        ioctl(ln, TIOCHPCL, (struct sgttyb *)NULL);
        prf("Connected");
+       pipe(pipes);
        if (dout)
                fk = -1;
        else
        if (dout)
                fk = -1;
        else
@@ -170,19 +205,19 @@ char *av[];
                chwrsig();
                rd();
                prf("\007Lost carrier");
                chwrsig();
                rd();
                prf("\007Lost carrier");
-               exit(3);
+               cleanup(3);
        }
        mode(1);
        efk = fk;
        wr();
        mode(0);
        }
        mode(1);
        efk = fk;
        wr();
        mode(0);
-       kill(fk, SIGKILL);
+       if (fk != -1) kill(fk, SIGKILL);
        wait((int *)NULL);
        stbuf.sg_ispeed = 0;
        stbuf.sg_ospeed = 0;
        ioctl(ln, TIOCSETP, &stbuf);
        prf("Disconnected");
        wait((int *)NULL);
        stbuf.sg_ispeed = 0;
        stbuf.sg_ospeed = 0;
        ioctl(ln, TIOCSETP, &stbuf);
        prf("Disconnected");
-       exit(0);
+       cleanup(0);
 }
 
 /*
 }
 
 /*
@@ -200,9 +235,22 @@ char *dev, *acu, *telno;
        struct sgttyb stbuf;
        extern errno;
        char *p, *q, b[30];
        struct sgttyb stbuf;
        extern errno;
        char *p, *q, b[30];
+       char *ltail, *atail;
+       char *rindex();
        int er, fk, dn, dh, t;
        er=0; 
        fk=(-1);
        int er, fk, dn, dh, t;
        er=0; 
        fk=(-1);
+       atail = rindex(acu, '/')+1;
+       if (mlock(atail) == FAIL) {
+               er = 9;
+               goto X;
+       }
+       ltail = rindex(dev, '/')+1;
+       if (mlock(ltail) == FAIL) {
+               er = 9;
+               delock(atail);
+               goto X;
+       }
        if ((dn=open(acu,1))<0) {
                er=(errno == 6? 1:5); 
                goto X;
        if ((dn=open(acu,1))<0) {
                er=(errno == 6? 1:5); 
                goto X;
@@ -244,7 +292,7 @@ char *dev, *acu, *telno;
                er=(errno == 4? 3:6); 
                goto X;
        }
                er=(errno == 4? 3:6); 
                goto X;
        }
-       ioctl(ln, TIOCGETP, &stbuf);
+       ioctl(dh, TIOCGETP, &stbuf);
        stbuf.sg_flags &= ~ECHO;
        xalarm(10);
        ioctl(dh, TIOCSETP, &stbuf);
        stbuf.sg_flags &= ~ECHO;
        xalarm(10);
        ioctl(dh, TIOCSETP, &stbuf);
@@ -252,6 +300,7 @@ char *dev, *acu, *telno;
        xalarm(0);
 X: 
        if (er) close(dn);
        xalarm(0);
 X: 
        if (er) close(dn);
+       delock(atail);
        if (fk!=(-1)) {
                kill(fk, SIGKILL);
                xalarm(10);
        if (fk!=(-1)) {
                kill(fk, SIGKILL);
                xalarm(10);
@@ -270,6 +319,7 @@ X:
  *     ~$proc  execute proc locally, send output to line
  *     ~%cmd   execute builtin cmd (put and take)
  *     ~#      send 1-sec break
  *     ~$proc  execute proc locally, send output to line
  *     ~%cmd   execute builtin cmd (put and take)
  *     ~#      send 1-sec break
+ *     ~^Z     suspend cu process.
  */
 
 wr()
  */
 
 wr()
@@ -281,9 +331,9 @@ wr()
                while (rdc(0) == 1) {
                        if (p == b) lcl=(c == '~');
                        if (p == b+1 && b[0] == '~') lcl=(c!='~');
                while (rdc(0) == 1) {
                        if (p == b) lcl=(c == '~');
                        if (p == b+1 && b[0] == '~') lcl=(c!='~');
-                       /* if (c == 0) oc=c=0177; fake break kludge */
+                       if (nullbrk && c == 0) oc=c=0177; /* fake break kludge */
                        if (!lcl) {
                        if (!lcl) {
-                               c = oc;
+                               if(!pflag)c = oc;
                                if (wrc(ln) == 0) {
                                        prf("line gone"); return;
                                }
                                if (wrc(ln) == 0) {
                                        prf("line gone"); return;
                                }
@@ -365,16 +415,17 @@ A:
                case '>':
                case ':':
                        {
                case '>':
                case ':':
                        {
-                       FILE *fp; char tbuff[128]; register char *q;
-                       sprintf(tbuff,"/tmp/cu%d",efk);
-                       if(NULL==(fp = fopen(tbuff,"w"))) {
+                       register char *q;
+
+                       if(pipes[1]==-1) {
                                prf("Can't tell other demon to divert");
                                break;
                        }
                                prf("Can't tell other demon to divert");
                                break;
                        }
-                       fprintf(fp,"%s\n",(b[1]=='>'?&b[2]: &b[1] ));
-                       if(dbflag) prf("name to be written in temporary:"),prf(&b[2]);
-                       fclose(fp);
-                       kill(efk,SIGEMT);
+                       q = b+1;
+                       if(*q=='>') q++;
+                       write(pipes[1],q,strlen(q)+1);
+                       if(dbflag) prf("msg to be delivered:"),prf(q);
+                       if (efk != -1) kill(efk,SIGEMT);
                        }
                        break;
 #ifdef SIGTSTP
                        }
                        break;
 #ifdef SIGTSTP
@@ -420,9 +471,13 @@ register char *line;
                }
                if (narg < 3)
                        args[2] = args[1];
                }
                if (narg < 3)
                        args[2] = args[1];
-               wrln("echo '~>:'");
+               write(pipes[1], ">:/dev/null",sizeof(">:/dev/null"));
+               if(dbflag) prf("sending take message");
+               if (efk != -1) kill(efk,SIGEMT);
+               xsleep(5);
+               wrln("echo '~>");
                wrln(args[2]);
                wrln(args[2]);
-               wrln(";tee /dev/null <");
+               wrln("'; tee /dev/null <");
                wrln(args[1]);
                wrln(";echo '~>'\n");
                return;
                wrln(args[1]);
                wrln(";echo '~>'\n");
                return;
@@ -493,33 +548,33 @@ register char *s;
  */
 int whoami;
 chwrsig(){
  */
 int whoami;
 chwrsig(){
-       int dodiver(); 
+       int readmsg(); 
        whoami = getpid();
        whoami = getpid();
-       signal(SIGEMT,dodiver);
+       signal(SIGEMT,readmsg);
 }
 }
-int ds,slnt;
+int ds,slnt,taking;
 int justrung;
 int justrung;
-dodiver(){
-       static char dobuff[128], morejunk[256]; register char *cp; 
-       FILE *fp;
+readmsg(){
+       static char dobuff[128], morejunk[256];
+       int n;
        justrung = 1;
        justrung = 1;
-       signal(SIGEMT,dodiver);
-       sprintf(dobuff,"/tmp/cu%d",whoami);
-       fp = fopen(dobuff,"r");
-       if(fp==NULL) prf("Couldn't open temporary");
-       unlink(dobuff);
+       signal(SIGEMT,readmsg);
        if(dbflag) {
        if(dbflag) {
-               prf("Name of temporary:");
-               prf(dobuff);
+               prf("About to read from pipe");
        }
        }
-       fgets(dobuff,128,fp); fclose(fp);
+       n = read(pipes[0],morejunk,256);
        if(dbflag) {
        if(dbflag) {
-               prf("Name of target file:");
-               prf(dobuff);
+               prf("diversion mesg recieved is");
+               prf(morejunk);
+               prf(CRLF);
        }
        }
-       for(cp = dobuff-1; *++cp; ) /* squash newline */
-               if(*cp=='\n') *cp=0;
-       cp = dobuff;
+       dodiver(morejunk);
+}
+dodiver(msg)
+char *msg;
+{
+       register char *cp = msg; 
+
        if (*cp=='>') cp++;
        if (*cp==':') {
                cp++;
        if (*cp=='>') cp++;
        if (*cp==':') {
                cp++;
@@ -536,7 +591,7 @@ dodiver(){
                ds = -1;
                return;
        }
                ds = -1;
                return;
        }
-       if (*dobuff!='>' || (ds=open(cp,1))<0) ds=creat(cp,0644);
+       if (*msg!='>' || (ds=open(cp,1))<0) ds=creat(cp,0644);
        lseek(ds, (long)0, 2);
        if(ds < 0) prf("Creat failed:"), prf(cp);
        if (ds<0) prf("Can't divert %s",cp+1);
        lseek(ds, (long)0, 2);
        if(ds < 0) prf("Creat failed:"), prf(cp);
        if (ds<0) prf("Can't divert %s",cp+1);
@@ -545,54 +600,76 @@ dodiver(){
 
 /*
  *     rd: read from remote: line -> 1
 
 /*
  *     rd: read from remote: line -> 1
- *     catch:
- *     ~>[>][:][file]
- *     stuff from file...
- *     ~>      (ends diversion)
+ *     catch: diversion caught by interrupt routine
  */
 
  */
 
+#define ORDIN 0
+#define SAWCR 1
+#define EOL   2
+#define SAWTL 3
+#define DIVER 4
+
 rd()
 {
        extern int ds,slnt;
 rd()
 {
        extern int ds,slnt;
-       char *p,*q,b[600];
-       p=b;
+       char rb[600], lb[600], *rlim, *llim, c;
+       register char *p,*q;
+       int cnt, state = 0, mustecho, oldslnt;
+
        ds=(-1);
        ds=(-1);
+       p = lb; llim = lb+600;
 agin:
 agin:
-       while (rdc(ln) == 1) {
-               if (!slnt) wrc(1);
-               *p++=c;
-               if (c!='\n') continue;
-               q=p; 
-               p=b;
-               if (b[0]!='~' || b[1]!='>') {
-                       if (*(q-2) == '\r') {
-                               q--; 
-                               *(q-1)=(*q);
+       while((cnt = read(ln,rb,600)) > 0) {
+               if(!slnt) write(1,rb,cnt);
+               if(ds < 0) continue;
+               oldslnt = slnt;
+               for( q=rb, rlim = rb + cnt - 1; q <= rlim; ) {
+                       c = *q++ & 0177;
+                       if(p < llim) *p++ = c;
+                       switch(state) {
+                       case ORDIN:
+                               if(c=='\r') state = SAWCR;
+                               break;
+                       case SAWCR:
+                               if(c=='\n') {
+                                       state = EOL;
+                                       p--;
+                                       p[-1] = '\n';
+                               } else state = ORDIN;
+                               break;
+                       case EOL:
+                               state = (c=='~' ? SAWTL : 
+                                        (c=='\r' ? SAWCR : ORDIN));
+                               break;
+                       case SAWTL:
+                               state = (c=='>' ? DIVER : 
+                                        (c=='\r' ? SAWCR : ORDIN));
+                               break;
+                       case DIVER:
+                               if(c=='\r') {
+                                       p--;
+                               } else if (c=='\n') {
+                                       state = ORDIN;
+                                       p[-1] = 0;
+                                       dodiver(lb+2);
+                                       c = 0; p = lb;
+                               }
+                       }
+                       if(slnt==0 && oldslnt) {
+                               if(c=='\n') {
+                                       write(ln,lb,p-lb-1);
+                                       write(ln,CRLF,sizeof(CRLF));
+                               } else if(q==rlim) {
+                                       write(ln,lb,p-lb);
+                                       c = '\n';  /*force flush to file*/
+                               }
+                       }
+                       if(c=='\n') {
+                               if(ds >= 0)
+                                       write(ds,lb,p-lb);
+                               p = lb;
                        }
                        }
-                       if (ds>=0) write(ds,b,q-b);
-                       continue;
-               }
-               if (ds>=0) close(ds);
-               if (slnt) {
-                       write(1, b, q - b);
-                       write(1, CRLF, sizeof(CRLF));
-               }
-               if (*(q-2) == '\r') q--;
-               *(q-1)=0;
-               slnt=0;
-               q=b+2;
-               if (*q == '>') q++;
-               if (*q == ':') {
-                       slnt=1; 
-                       q++;
-               }
-               if (*q == 0) {
-                       ds=(-1); 
-                       continue;
                }
                }
-               if (b[2]!='>' || (ds=open(q,1))<0) ds=creat(q,0644);
-               lseek(ds, (long)0, 2);
-               if (ds<0) prf("Can't divert %s",b+1);
        }
        if(justrung) {
                justrung = 0;
        }
        if(justrung) {
                justrung = 0;
@@ -648,3 +725,234 @@ char *devname;
        prf("%s does not exist", devname);
        return(0);
 }
        prf("%s does not exist", devname);
        return(0);
 }
+
+cleanup(code)
+{
+       rmlock(NULL);
+       exit(code);
+}
+
+/*
+ * This code is taken directly from uucp and follows the same
+ * conventions.  This is important since uucp and cu should
+ * respect each others locks.
+ */
+
+       /*  ulockf 3.2  10/26/79  11:40:29  */
+/* #include "uucp.h" */
+#include <sys/types.h>
+#include <sys/stat.h>
+
+
+
+/*******
+ *     ulockf(file, atime)
+ *     char *file;
+ *     time_t atime;
+ *
+ *     ulockf  -  this routine will create a lock file (file).
+ *     If one already exists, the create time is checked for
+ *     older than the age time (atime).
+ *     If it is older, an attempt will be made to unlink it
+ *     and create a new one.
+ *
+ *     return codes:  0  |  FAIL
+ */
+
+ulockf(file, atime)
+char *file;
+time_t atime;
+{
+       struct stat stbuf;
+       time_t ptime;
+       int ret;
+       static int pid = -1;
+       static char tempfile[NAMESIZE];
+
+       if (pid < 0) {
+               pid = getpid();
+               sprintf(tempfile, "/usr/spool/uucp/LTMP.%d", pid);
+       }
+       if (onelock(pid, tempfile, file) == -1) {
+               /* lock file exists */
+               /* get status to check age of the lock file */
+               ret = stat(file, &stbuf);
+               if (ret != -1) {
+                       time(&ptime);
+                       if ((ptime - stbuf.st_ctime) < atime) {
+                               /* file not old enough to delete */
+                               return(FAIL);
+                       }
+               }
+               ret = unlink(file);
+               ret = onelock(pid, tempfile, file);
+               if (ret != 0)
+                       return(FAIL);
+       }
+       stlock(file);
+       return(0);
+}
+
+
+#define MAXLOCKS 10    /* maximum number of lock files */
+char *Lockfile[MAXLOCKS];
+int Nlocks = 0;
+
+/***
+ *     stlock(name)    put name in list of lock files
+ *     char *name;
+ *
+ *     return codes:  none
+ */
+
+stlock(name)
+char *name;
+{
+       char *p;
+       extern char *calloc();
+       int i;
+
+       for (i = 0; i < Nlocks; i++) {
+               if (Lockfile[i] == NULL)
+                       break;
+       }
+       ASSERT(i < MAXLOCKS, "TOO MANY LOCKS %d", i);
+       if (i >= Nlocks)
+               i = Nlocks++;
+       p = calloc(strlen(name) + 1, sizeof (char));
+       ASSERT(p != NULL, "CAN NOT ALLOCATE FOR %s", name);
+       strcpy(p, name);
+       Lockfile[i] = p;
+       return;
+}
+
+
+/***
+ *     rmlock(name)    remove all lock files in list
+ *     char *name;     or name
+ *
+ *     return codes: none
+ */
+
+rmlock(name)
+char *name;
+{
+       int i;
+
+       for (i = 0; i < Nlocks; i++) {
+               if (Lockfile[i] == NULL)
+                       continue;
+               if (name == NULL
+               || strcmp(name, Lockfile[i]) == SAME) {
+                       unlink(Lockfile[i]);
+                       free(Lockfile[i]);
+                       Lockfile[i] = NULL;
+               }
+       }
+       return;
+}
+
+
+/*  this stuff from pjw  */
+/*  /usr/pjw/bin/recover - check pids to remove unnecessary locks */
+/*     isalock(name) returns 0 if the name is a lock */
+/*     unlock(name)  unlocks name if it is a lock*/
+/*     onelock(pid,tempfile,name) makes lock a name
+       on behalf of pid.  Tempfile must be in the same
+       file system as name. */
+/*     lock(pid,tempfile,names) either locks all the
+       names or none of them */
+isalock(name) char *name;
+{
+       struct stat xstat;
+       if(stat(name,&xstat)<0) return(0);
+       if(xstat.st_size!=sizeof(int)) return(0);
+       return(1);
+}
+unlock(name) char *name;
+{
+       if(isalock(name)) return(unlink(name));
+       else return(-1);
+}
+onelock(pid,tempfile,name) char *tempfile,*name;
+{      int fd;
+       fd=creat(tempfile,0444);
+       if(fd<0) return(-1);
+       write(fd,(char *) &pid,sizeof(int));
+       close(fd);
+       if(link(tempfile,name)<0)
+       {       unlink(tempfile);
+               return(-1);
+       }
+       unlink(tempfile);
+       return(0);
+}
+lock(pid,tempfile,names) char *tempfile,**names;
+{      int i,j;
+       for(i=0;names[i]!=0;i++)
+       {       if(onelock(pid,tempfile,names[i])==0) continue;
+               for(j=0;j<i;j++) unlink(names[j]);
+               return(-1);
+       }
+       return(0);
+}
+
+#define LOCKPRE "/usr/spool/uucp/LCK."
+
+/***
+ *     delock(s)       remove a lock file
+ *     char *s;
+ *
+ *     return codes:  0  |  FAIL
+ */
+
+delock(s)
+char *s;
+{
+       char ln[30];
+
+       sprintf(ln, "%s.%s", LOCKPRE, s);
+       rmlock(ln);
+}
+
+
+/***
+ *     mlock(sys)      create system lock
+ *     char *sys;
+ *
+ *     return codes:  0  |  FAIL
+ */
+
+mlock(sys)
+char *sys;
+{
+       char lname[30];
+       sprintf(lname, "%s.%s", LOCKPRE, sys);
+       return(ulockf(lname, (time_t) SLCKTIME ) < 0 ? FAIL : 0);
+}
+
+
+
+/***
+ *     ultouch()       update access and modify times for lock files
+ *
+ *     return code - none
+ */
+
+ultouch()
+{
+       time_t time();
+       int i;
+       struct ut {
+               time_t actime;
+               time_t modtime;
+       } ut;
+
+       ut.actime = time(&ut.modtime);
+       for (i = 0; i < Nlocks; i++) {
+               if (Lockfile[i] == NULL)
+                       continue;
+               utime(Lockfile[i], &ut);
+       }
+       return;
+}