date and time created 85/03/22 10:10:11 by ralph
authorRalph Campbell <ralph@ucbvax.Berkeley.EDU>
Sat, 23 Mar 1985 02:10:11 +0000 (18:10 -0800)
committerRalph Campbell <ralph@ucbvax.Berkeley.EDU>
Sat, 23 Mar 1985 02:10:11 +0000 (18:10 -0800)
SCCS-vsn: usr.bin/uucp/acucntrl/acucntrl.c 5.1

usr/src/usr.bin/uucp/acucntrl/acucntrl.c [new file with mode: 0644]

diff --git a/usr/src/usr.bin/uucp/acucntrl/acucntrl.c b/usr/src/usr.bin/uucp/acucntrl/acucntrl.c
new file mode 100644 (file)
index 0000000..be55b1e
--- /dev/null
@@ -0,0 +1,571 @@
+#ifndef lint
+static char sccsid[] = "@(#)acucntrl.c 5.1 (Berkeley) %G%";
+#endif
+
+/*  acucntrl - turn around tty line between dialin and dialout
+ * 
+ * Usage:      acucntrl {enable,disable} /dev/ttydX
+ *
+ * History:
+ *     First written by Allan Wilkes (fisher!allan)
+ *
+ *     Modified June 8,1983 by W.Sebok (astrovax!wls) to poke kernel rather
+ *     than use kernel hack to turn on/off modem control, using subroutine
+ *     stolen from program written by Tsutomu Shimomura
+ *     {astrovax,escher}!tsutomu
+ *
+ *     Worked over many times by W.Sebok (i.e. hacked to death)
+ *
+ * Operation:
+ *   disable (i.e. setup for dialing out)
+ *     (1) check input arguments
+ *     (2) look in /etc/utmp to check that the line is not in use by another
+ *     (3) disable modem control on terminal
+ *     (4) check for carrier on device
+ *     (5) change owner of device to real id
+ *     (6) edit /etc/ttys,  changing the first character of the appropriate
+ *         line to 0
+ *     (7) send a hangup to process 1 to poke init to disable getty
+ *     (8) post uid name in capitals in /etc/utmp to let world know device has
+ *         been grabbed
+ *     (9) make sure that DTR is on
+ *
+ *   enable (i.e.) restore for dialin
+ *     (1) check input arguments
+ *     (2) look in /etc/utmp to check that the line is not in use by another
+ *     (3) make sure modem control on terminal is disabled
+ *     (4) turn off DTR to make sure line is hung up
+ *     (5) condition line: clear exclusive use and set hangup on close modes
+ *     (6) turn on modem control
+ *     (7) edit /etc/ttys,  changing the first character of the appropriate
+ *         line to 1
+ *     (8) send a hangup to process 1 to poke init to enable getty
+ *     (9) clear uid name for /etc/utmp
+ */
+
+/* #define SENSECARRIER */
+
+#include "uucp.h"
+#include <sys/param.h>
+#include <sys/buf.h>
+#include <sys/conf.h>
+#ifdef BSD4_2
+#include "/sys/vaxuba/ubavar.h"
+#else !BSD4_2
+#include <sys/ubavar.h>
+#endif !BSD4_2
+#include <sys/stat.h>
+#include <nlist.h>
+#include <sgtty.h>
+#include <utmp.h>
+#include <pwd.h>
+#include <stdio.h>
+
+#define NDZLINE        8       /* lines/dz */
+#define NDHLINE        16      /* lines/dh */
+#define NDMFLINE 8     /* lines/dmf */
+
+#define DZ11   1
+#define DH11   2
+#define DMF    3
+
+#define NLVALUE(val)   (nl[val].n_value)
+
+struct nlist nl[] = {
+#define CDEVSW 0
+       { "_cdevsw" },
+
+#define DZOPEN 1
+       { "_dzopen" },
+#define DZINFO 2
+       { "_dzinfo" },
+#define NDZ11  3
+       { "_dz_cnt" },
+#define DZSCAR 4
+       { "_dzsoftCAR" },
+
+#define DHOPEN 5
+       { "_dhopen" },
+#define DHINFO 6
+       { "_dhinfo" },
+#define NDH11  7
+       { "_ndh11" },
+#define DHSCAR 8
+       { "_dhsoftCAR" },
+
+#define DMFOPEN        9
+       { "_dmfopen" },
+#define DMFINFO        10
+       { "_dmfinfo" },
+#define NDMF   11
+       { "_ndmf" },
+#define DMFSCAR        12
+       { "_dmfsoftCAR" },
+
+       { "\0" }
+};
+
+#define ENABLE 1
+#define DISABLE        0
+
+char Etcutmp[] = "/etc/utmp";
+char Etcttys[] = "/etc/ttys";
+char Devhome[] = "/dev";
+
+char usage[] = "Usage: acucntrl {dis|en}able ttydX\n";
+
+struct utmp utmp;
+char resettty, resetmodem;
+int etcutmp;
+int utmploc;
+int ttyslnbeg;
+
+#define NAMSIZ sizeof(utmp.ut_name)
+#define        LINSIZ  sizeof(utmp.ut_line)
+
+main(argc, argv)
+int argc; char *argv[];
+{
+       register char *p;
+       register int i;
+       char uname[NAMSIZ], Uname[NAMSIZ];
+       int enable ;
+       char *device;
+       int devfile;
+       int uid, gid;
+       long lseek();
+       struct passwd *getpwuid();
+       char *rindex();
+       extern int errno;
+       extern char *sys_errlist[];
+
+       /* check input arguments */
+       if (argc!=3) {
+               fprintf(stderr, usage);
+               exit(1);
+       }
+
+       /* interpret command type */
+       if (prefix(argv[1], "disable")  || strcmp(argv[1],"dialout")==0)
+               enable = 0;
+       else if (prefix(argv[1], "enable")  || strcmp(argv[1],"dialin")==0)
+               enable = 1;
+       else {
+               fprintf(stderr, usage);
+               exit(1);
+       }
+
+       device = rindex(argv[2],'/');
+       device = (device == NULL) ? argv[2]: device+1;
+
+       /* only recognize devices of the form ttydX */
+       if (strncmp(device,"ttyd",4)!=0) {
+               fprintf(stderr,"Bad Device Name %s",device);
+               exit(1);
+       }
+
+       opnttys(device);
+
+       /* Get nlist info */
+       nlist("/vmunix",nl);
+
+       /* Chdir to /dev */
+       if(chdir(Devhome) < 0) {
+               fprintf(stderr, "Cannot chdir to %s: %s\r\n",
+                       Devhome, sys_errlist[errno]);
+               exit(1);
+       }
+
+       /* Get uid information */
+       uid = getuid();
+       gid = getgid();
+
+       p = getpwuid(uid)->pw_name;
+       if (p==NULL) {
+               fprintf(stderr,"cannot get uid name\n");
+               exit(1);
+       }
+
+       /*  to upper case */
+       i = 0;
+       do {
+               uname[i] = *p;
+               Uname[i] = (*p>='a' && *p<='z') ? (*p - ('a'-'A')) : *p;
+               i++; p++;
+       } while (*p && i<NAMSIZ);
+
+
+       /* check to see if line is being used */
+       if( (etcutmp = open(Etcutmp, 2)) < 0) {
+               fprintf(stderr,"On open %s open: %s\n",
+                       Etcutmp,sys_errlist[errno]);
+               exit(1);
+       }
+
+       (void)lseek(etcutmp,utmploc, 0);
+
+       i = read(etcutmp,&utmp,sizeof(struct utmp));
+
+       if(
+               i == sizeof(struct utmp) &&
+               utmp.ut_line[0] != '\0'  &&
+               utmp.ut_name[0] != '\0'  &&
+               (
+                       !upcase(utmp.ut_name,NAMSIZ) ||
+                       (
+                               uid != 0 &&
+                               strncmp(utmp.ut_name,Uname,NAMSIZ) != 0
+                       )
+               )
+       ) {
+               fprintf(stderr, "%s in use by %s\n", device, utmp.ut_name);
+               exit(2);
+       }
+
+       /* Disable modem control */
+       if (setmodem(device,DISABLE)<0) {
+               fprintf(stderr,"Unable to disable modem control\n");
+               exit(1);
+       }
+
+       if (enable) {
+               if((devfile = open(device, 1)) < 0) {
+                       fprintf(stderr,"On open of %s: %s\n",
+                               device, sys_errlist[errno]);
+                       (void)setmodem(device,resetmodem);
+                       exit(1);
+               }
+               /* Try one last time to hang up */
+               if (ioctl(devfile,TIOCCDTR,0) < 0)
+                       fprintf(stderr,"On TIOCCDTR ioctl: %s\n",
+                               sys_errlist[errno]);
+
+               if (ioctl(devfile, TIOCNXCL,0) < 0)
+                       fprintf(stderr,
+                           "Cannot clear Exclusive Use on %s: %s\n",
+                               device, sys_errlist[errno]);
+
+               if (ioctl(devfile, TIOCHPCL,0) < 0)
+                       fprintf(stderr,
+                           "Cannot set hangup on close on %s: %s\n",
+                               device, sys_errlist[errno]);
+
+               i = resetmodem;
+
+               if (setmodem(device,ENABLE) < 0) {
+                       fprintf(stderr,"Cannot Enable modem control\n");
+                       (void)setmodem(device,i);
+                       exit(1);
+               }
+               resetmodem=i;
+
+               settys(ENABLE);
+
+               pokeinit(device,Uname,enable);
+               post(device,"");
+
+       } else {
+#if defined(TIOCMGET) && defined(SENSECARRIER)
+               if (uid!=0) {
+                       int linestat = 0;
+
+                       /* check for presence of carrier */
+                       sleep(2); /* need time after modem control turnoff */
+
+                       if((devfile = open(device, 1)) < 0) {
+                               fprintf(stderr,"On open of %s: %s\n",
+                                       device, sys_errlist[errno]);
+                               (void)setmodem(device,resetmodem);
+                               exit(1);
+                       }
+
+                       (void)ioctl(devfile,TIOCMGET,&linestat);
+
+                       if (linestat&TIOCM_CAR) {
+                               fprintf(stderr,"%s is in use (Carrier On)\n",
+                                       device);
+                               (void)setmodem(device,resetmodem);
+                               exit(2);
+                       }
+                       (void)close(devfile);
+               }
+#endif TIOCMGET
+               /* chown device */
+               if(chown(device, uid, gid) < 0)
+                       fprintf(stderr, "Cannot chown %s: %s\n",
+                               device, sys_errlist[errno]);
+
+
+               /* poke init */
+               settys(DISABLE);
+               pokeinit(device,Uname,enable);
+               post(device,Uname);
+               if((devfile = open(device, 1)) < 0) {
+                       fprintf(stderr, "On %s open: %s\n",
+                               device, sys_errlist[errno]);
+               } else {
+                       if(ioctl(devfile, TIOCSDTR, 0) < 0)
+                               fprintf(stderr,
+                                   "Cannot set DTR on %s: %s\n",
+                                       device, sys_errlist[errno]);
+               }
+       }
+
+       exit(0);
+}
+
+/* return true if no lower case */
+upcase(str,len)
+register char *str;
+register int len;
+{
+       for (; *str, --len >= 0 ; str++)
+               if (*str>='a' && *str<='z')
+                       return(0);
+       return(1);
+}
+
+/* Post name to public */
+post(device,name)
+char *device, *name;
+{
+       (void)time(&utmp.ut_time);
+       strcpyn(utmp.ut_line, device, LINSIZ);
+       strcpyn(utmp.ut_name, name,  NAMSIZ);
+       if (lseek(etcutmp, utmploc, 0)<0)
+               fprintf(stderr,"on lseek in /etc/utmp: %s",
+                       sys_errlist[errno]);
+       if (write(etcutmp, (char *)&utmp, sizeof(utmp))<0)
+               fprintf(stderr,"on write in /etc/utmp: %s",
+                       sys_errlist[errno]);
+}
+       
+/* poke process 1 and wait for it to do its thing */
+pokeinit(device,uname,enable)
+char *uname, *device; int enable;
+{
+       struct utmp utmp;
+
+       post(device, uname);
+
+       /* poke init */
+       if (kill(1, SIGHUP)) {
+               fprintf(stderr,
+                   "Cannot send hangup to init process: %s\n",
+                       sys_errlist[errno]);
+               settys(resettty);
+               (void)setmodem(device,resetmodem);
+               exit(1);
+       }
+
+       if (enable)
+               return;
+
+       /* wait till init has responded, clearing the utmp entry */
+       do {
+               sleep(1);
+               if (lseek(etcutmp,utmploc,0)<0)
+                       fprintf(stderr,"On lseek in /etc/utmp: %s",
+                               sys_errlist[errno]);
+               if (read(etcutmp,&utmp,sizeof utmp)<0)
+                       fprintf(stderr,"On read from /etc/utmp: %s",
+                               sys_errlist[errno]);
+       } while (utmp.ut_name[0] !='\0');
+}
+
+/* identify terminal line in ttys */
+opnttys(device)
+char *device;
+{
+       register FILE *ttysfile;
+       register int  ndevice, lnsiz; 
+       register char *p;
+       char *index();
+       char linebuf[100];
+
+       ttysfile = fopen(Etcttys, "r");
+       if(ttysfile == NULL) {
+               fprintf(stderr, "Cannot open %s: %s\n", Etcttys,
+                       sys_errlist[errno]);
+               exit(1);
+       }
+
+       ndevice = strlen(device);
+       ttyslnbeg = 0;
+       utmploc = 0;
+
+       while(fgets(linebuf, sizeof(linebuf) - 1, ttysfile) != NULL) {
+               utmploc += sizeof(utmp);
+               lnsiz = strlen(linebuf);
+               if ((p = index(linebuf,'\n')) != NULL)
+                       *p = '\0';
+               if(strncmp(device, &linebuf[2], ndevice) == 0) {
+                       (void)fclose(ttysfile);
+                       return;
+               }
+               ttyslnbeg += lnsiz;
+       }
+       fprintf(stderr, "%s not found in %s\n", device, Etcttys);
+       exit(1);
+}
+
+/* modify appropriate line in /etc/ttys to turn on/off the device */
+settys(enable)
+int enable;
+{
+       int ittysfil;
+       int  lnbeg, foundit, ndevice; 
+       char out,in;
+
+       ittysfil = open(Etcttys, 2);
+       if(ittysfil == NULL) {
+               fprintf(stderr, "Cannot open %s for output: %s\n",
+                       Etcttys, sys_errlist[errno]);
+               exit(1);
+       }
+       (void)lseek(ittysfil,(long)ttyslnbeg,0);
+       if(read(ittysfil,&in,1)<0) {
+               fprintf(stderr,"On %s write: %s\n",
+                       Etcttys, sys_errlist[errno]);
+               exit(1);
+       }
+       resettty = (in == '1');
+       out = enable ? '1' : '0';
+       (void)lseek(ittysfil,(long)ttyslnbeg,0);
+       if(write(ittysfil,&out,1)<0) {
+               fprintf(stderr,"On %s write: %s\n",
+                       Etcttys, sys_errlist[errno]);
+               exit(1);
+       }
+       (void)close(ittysfil);
+}
+
+/*
+ * Excerpted from (June 8,1983 W.Sebok)
+ * > ttymodem.c - enable/disable modem control for tty lines.
+ * >
+ * > Knows about DZ11s and DH11/DM11s.
+ * > 23.3.83 - TS
+ * > modified to know about DMF's  (hasn't been tested) Nov 8,1984 - WLS
+ */
+
+
+setmodem(ttyline,enable)
+char *ttyline; int enable;
+{
+       dev_t dev;
+       int kmem;
+       int unit,line,nlines,addr,tflags;
+       struct uba_device *ubinfo;
+       struct stat statb;
+       short flags,devtype=0;
+       struct cdevsw cdevsw;
+
+       if(nl[CDEVSW].n_type == 0) {
+               fprintf(stderr,"No namelist.\n");
+               return(-1);
+       }
+
+       if((kmem = open("/dev/kmem", 2)) < 0) {
+               fprintf(stderr,"/dev/kmem open: %s\n", sys_errlist[errno]);
+               return(-1);
+       }
+
+       if(stat(ttyline,&statb) < 0) {
+               fprintf(stderr,"%s stat: %s\n", ttyline, sys_errlist[errno]);
+               return(-1);
+       }
+
+       if(statb.st_mode&S_IFMT != S_IFCHR) {
+               fprintf(stderr,"%s is not a character device.\n",ttyline);
+               return(-1);
+       }
+
+       dev = statb.st_rdev;
+       (void)lseek(kmem,
+               (int) &(((struct cdevsw *)NLVALUE(CDEVSW))[major(dev)]),0);
+       (void)read(kmem,(char *) &cdevsw,sizeof cdevsw);
+
+       if((int)(cdevsw.d_open) == NLVALUE(DZOPEN)) {
+               devtype = DZ11;
+               unit = minor(dev) / NDZLINE;
+               line = minor(dev) % NDZLINE;
+               addr = (int) &(((int *)NLVALUE(DZINFO))[unit]);
+               (void)lseek(kmem,(int) NLVALUE(NDZ11),0);
+       } else if((int)(cdevsw.d_open) == NLVALUE(DHOPEN)) {
+               devtype = DH11;
+               unit = minor(dev) / NDHLINE;
+               line = minor(dev) % NDHLINE;
+               addr = (int) &(((int *)NLVALUE(DHINFO))[unit]);
+               (void)lseek(kmem,(int) NLVALUE(NDH11),0);
+       } else if((int)(cdevsw.d_open) == NLVALUE(DMFOPEN)) {
+               devtype = DMF;
+               unit = minor(dev) / NDMFLINE;
+               line = minor(dev) % NDMFLINE;
+               addr = (int) &(((int *)NLVALUE(DMFINFO))[unit]);
+               (void)lseek(kmem,(int) NLVALUE(NDMF),0);
+       } else {
+               fprintf(stderr,"Device %s (%d/%d) unknown.\n",ttyline,
+                   major(dev),minor(dev));
+               return(-1);
+       }
+
+       (void)read(kmem,(char *) &nlines,sizeof nlines);
+       if(minor(dev) >= nlines) {
+               fprintf(stderr,"Sub-device %d does not exist (only %d).\n",
+                   minor(dev),nlines);
+               return(-1);
+       }
+
+       (void)lseek(kmem,addr,0);
+       (void)read(kmem,(char *) &ubinfo,sizeof ubinfo);
+       (void)lseek(kmem,(int) &(ubinfo->ui_flags),0);
+       (void)read(kmem,(char *) &flags,sizeof flags);
+
+       tflags = 1<<line;
+       resetmodem = ((flags&tflags) == 0);
+       flags = enable ? (flags & ~tflags) : (flags | tflags);
+       (void)lseek(kmem,(int) &(ubinfo->ui_flags),0);
+       (void)write(kmem,(char *) &flags, sizeof flags);
+       switch(devtype) {
+               case DZ11:
+                       if((addr = NLVALUE(DZSCAR)) == 0) {
+                               fprintf(stderr,"No dzsoftCAR.\n");
+                               return(-1);
+                       }
+                       (void)lseek(kmem,(int) &(((char *)addr)[unit]),0);
+                       (void)write(kmem,(char *) &flags, sizeof flags);
+                       break;
+               case DH11:
+                       if((addr = NLVALUE(DHSCAR)) == 0) {
+                               fprintf(stderr,"No dhsoftCAR.\n");
+                               return(-1);
+                       }
+                       (void)lseek(kmem,(int) &(((short *)addr)[unit]),0);
+                       (void)write(kmem,(char *) &flags, sizeof flags);
+                       break;
+               case DMF:
+                       if((addr = NLVALUE(DMFSCAR)) == 0) {
+                               fprintf(stderr,"No dmfsoftCAR.\n");
+                               return(-1);
+                       }
+                       (void)lseek(kmem,(int) &(((short *)addr)[unit]),0);
+                       (void)write(kmem,(char *) &flags,2);
+                       break;
+               default:
+                       fprintf(stderr,"Unknown device type\n");
+                       return(-1);
+       }
+       return(0);
+}
+
+prefix(s1, s2)
+       register char *s1, *s2;
+{
+       register char c;
+
+       while ((c = *s1++) == *s2++)
+               if (c == '\0')
+                       return (1);
+       return (c == '\0');
+}