home *** CD-ROM | disk | FTP | other *** search
- /*
- * prelog.c Version 1.0 Glenn A. Emelko 10/10/87
- *
- * First of all, I do hereby declare this code as a completely original
- * program, inspired by many but written by one (me). I hereby grant
- * anyone permission to use this code as public domain, for the sole
- * purpose of understanding, learning, or simply implementation of any
- * or all of the concepts herein. I hereby restrict the usage of this
- * code to NON-PROFIT purposes; no portions of this code should be used
- * by anyone in any way, shape, or form, in order to promote gain to
- * either self or others (except me, but I'll never do that). This
- * restriction also stipulates that any of the above words, as well
- * these, shall be proliferated with this code until doomsday (or after).
- *
- * Thank you.
- *
- * This program was written and developed on a Charles River Data Systems
- * Universe 68/35 running UNOS 5.1. The purpose was to provide a login
- * preprocessor similar to getty, which would automatically detect baud
- * rate, set the entry in the /etc/ttys file for the proper baud setting,
- * and then execute the original login processor to log in a user. No
- * attempt has been made at this point to test this code with signals,
- * but it is my belief that it should work properly.
- *
- *
- * The file /etc/ttys must be maintained properly for the original UNOS
- * login procedure to set the baud rate during the login procedeure. I
- * have added a field in /etc/ttys which will determine which baud table
- * is used for rotary baud selection. Baud selection is accomplished by
- * sensing for two carriage returns, and if they are not found adjacent
- * to each other, waiting for no data, and then rotoring to the next baud
- * selection, and repeating. During this time, either nothing, or a
- * message (see rotormsg) may be sent to the terminal as each rate is
- * rotored through.
- *
- * Support in the code exists to start up and drive a "ATxx" compatable
- * modem, and it may be desirable to take advantage of the carrier
- * message to determine baud selection directly, rather than rotoring.
- *
- * The /etc/ttys file has single line items for each tty device, with
- * the information fields delimited by colons. I did not put in the
- * necessary support for continuation lines; it can be safely left as
- * an exercise to the guru [smile]. The format of the /etc/ttys file
- * is as follows:
- *
- * state:lineno:devpath:devid:terminal:ttymodes:comments:extra
- *
- * where [in brackets is the maximum field with allowed by prelog]:
- *
- * state [12] -- either "on" or something else; on indicating an
- * active login port, and anything else indicating an
- * i/o port for other usage.
- *
- * lineno [4] -- logical tty number, on the CRDS, it corresponds
- * to last number in the device path, whichhas a range
- * from 0 to 11.
- *
- * dpath [12] -- the full path of the tty device. Something like
- * "/dev/tty4" is valid.
- *
- * devnum [6] -- The system major and minor device number. On
- * the CRDS, this is 1/nn, where nn is the tty number.
- *
- * ttyid [12] -- this is the terminal id assumed to be connected
- * to the line; it is looked up in the termcap entries
- * to set terminal parameters. Something like "vt100"
- * is valid.
- *
- * tbaud [20] -- this is the entry read to set terminal modes on
- * the tty device. This entry is passed by the original
- * login program to an internal UNOS specific system call
- * called _ttymodes. The standard /etc/ttys file only
- * sets the baud rate by this field, and this is where
- * prelog puts its speed setting after it has detected
- * the speed. A standard UNOS entry in this field is
- * something like "speed=9600".
- * NOTE: THIS FIELD IS MODIFIED BY prelog.
- *
- * tsetb [30] -- this field was the comment field associated with
- * the tty device. I commandeered this field, and have
- * given it new meaning; the FIRST character of this
- * field shall be a '0' thru '9', identifying which table
- * prelog shall use to select its baud rates by, as well
- * as control a modem by. The DEFAULT setting is 0 or
- * a non-numeric character, which are treated the same.
- * In this default mode, the baud rate will NOT be auto
- * selected, instead, the ttymodes field will be used
- * as is, without changing it. See the tables for the
- * other possible values. The REST of this field may
- * still be used for comments of any sort.
- * NOTE: THIS FIELD IS CHECKED BY prelog.
- *
- * extra [30] -- Well, your guess is as good as mine. This
- * field may or may not even exist on some of the
- * entries; in fact there are some extra colons at the
- * end of some lines in my own ttys file. Anything
- * after the comments field is captured verbatim, so it
- * will be put back exactly the same way it came out.
- *
- * One last thing, before we get on with the program....
- *
- * INSTALLATION
- *
- * To install this program on a CRDS under UNOS 5.1, compile it with cc,
- * move /sys/login to /sys/post_login, and move the compiled code to
- * /sys/login. This is all that is needed, it will take over once you
- * log off. For other versions of UNOS or other UNIX machines, I will
- * say that YOU ARE AT YOUR OWN RISK -- playing with /sys/login is a
- * very dangerous thing to do, and I do not recomment it for those who
- * are weak at heart. I crashed my CRDS completely several times; even
- * though I had multiple ttys logged in to try to have recoverable
- * system problems, occasionally the WHOLE SYSTEM came to it's knees --
- * I get the feeling it really didn't like what I was doing. Please
- * note that this was an experimental time, and NOW it works fine, I
- * have been running my new login procedure for several weeks. You may
- * also wish to run "strip" on the new /sys/login file, to cut down its
- * storage requirements on the disk (strip removes symbolic information).
- */
-
- #include <fcntl.h> /* For file i/o */
- #include <sgtty.h> /* For tty modes */
- #include <signal.h> /* for sigquit/sighup */
- #include <stdio.h> /* for fprintf */
- #include <sys/utsname.h> /* for uname call */
- #include <termio.h> /* for terminal setting */
-
- int at_init();
-
- int no_init(){};
-
- struct ttyentry {
- char state[12]; /* state "on" or other */
- char lineno[4]; /* lineno (range 0-11) */
- char dpath[12]; /* device path /dev/tty */
- char devnum[6]; /* major/minor, 1/nn */
- char ttyid[12]; /* tty type, i.e. vt100 */
- char tbaud[20]; /* baud, speed=9600 */
- char tsetb[30]; /* table (0-9), remark */
- char extra[30]; /* anything else ? */
- } ttys[20]; /* NOTE max 20 entries */
-
- int ttys_count; /* count of entries */
- int myttyentry; /* which entry am I? */
-
- FILE *ttysfile; /* fildes for /etc/ttys */
-
- int tty_lun; /* login terminal unit */
- FILE *indev; /* stdin/stdout */
- FILE *outdev;
-
- struct sgttyb tty_mode; /* tty settings struct */
-
- char post_login[] = "/sys/post_login"; /* orig. login program */
-
- char s110[] = "speed=110"; /* Text for ttymodes */
- char s300[] = "speed=300";
- char s1200[] = "speed=1200";
- char s9600[] = "speed=9600";
- char s38400[] = "speed=38400";
-
- char ttymatch[] = "/dev/tty?? "; /* reserve space */
-
- char rotormsg[] = "\007";
-
- struct tset {
- char tableid; /* table name ('0'-'9') */
- int (*Line_init)(); /* anything to do first */
- char rotori; /* rotor name ('A'-'Z') */
- } tsets[] = {
-
- '0',no_init,\0, /* tset 0, no init, use /etc/ttys */
-
- '1',no_init,'A', /* tset 1, no init, use rotor A */
-
- '2',at_init,'B', /* tset 2, "ATxx" init, use rotor B */
-
- \0,no_init,\0 /* End of table, no init, use /etc/ttys */
- };
-
- #define NUMTSETS sizeof tsets/sizeof tsets[0]
-
- struct rotor {
- char rotorid; /* rotor name ('A'-'Z') */
- int flags; /* Sense setup flags */
- int speed; /* Baud flags */
- char *tbaudset; /* ttys tbaud setting */
- } rotors[] = {
-
- 'A',CR1+NL1+CRMOD+RAW,B9600,s9600, /*A, flags, ibaud, text */
- 'A',CR1+NL1+CRMOD+RAW,B38400,s38400, /*A, flags, ibaud, text */
- 'A',CR1+NL1+CRMOD+RAW,B1200,s1200, /*A, flags, ibaud, text */
- 'A',CR1+NL1+CRMOD+RAW,B1200,s1200, /*A, flags, ibaud, text */
-
- 'B',CR1+NL1+CRMOD+RAW,B300,s300, /*A, flags, ibaud, text */
- 'B',CR1+NL1+CRMOD+RAW,B1200,s1200, /*A, flags, ibaud, text */
-
- \0,0,0,(char *)\0 /* End of table */
- };
-
- main(argc,argv)
- int argc;
- char **argv;
- {
- struct utsname sysname; /* utsname definition */
- char tsetgo; /* default use table 0 */
- char rotorgo; /* search character */
- int i,j; /* general purpose */
- int tsetnum, rotornum; /* pointer counts */
- char chr; /* general purpuse */
-
- uname(&sysname); /* Get system name */
-
- if (argc==1) {
- tty_lun = fdown(outdev=stdout); /* get tty logical unit */
- indev = stdin; /* get i/o devices */
- } else {
- tty_lun = fdown(outdev=fileopen(argv[1],"w"));
- /* get tty logical unit */
- indev = fileopen(argv[1],"r"); /* and get i/o devices */
- }
-
- setbuf(indev,NULL); /* no i/o buffering */
- setbuf(outdev,NULL);
-
- strcpy(ttymatch,ttyname(tty_lun)); /* save device path */
- setctlterm(tty_lun); /* set controlling term */
- tty_lun=open(ttymatch,O_RDWR); /* reopen device for us */
-
- ttys_count = 0;
- ttysfile = fopen("/etc/ttys","r"); /* get /etc/ttys info */
- while (fread(&chr,1,1,ttysfile)>0) /* if chr, get entry */
- getentry(chr);
- fclose(ttysfile); /* have ttys information*/
-
- for(i=0;i<ttys_count;i++) { /* scan ttys entries */
- if (0==strcmp(ttymatch,ttys[i].dpath)) {/* if it matches... */
- tsetgo = *ttys[i].tsetb; /* get character */
- if ((tsetgo<'0') || (tsetgo>'9')) /* resort to default? */
- tsetgo='0';
- }
- }
-
- for(tsetnum=0;tsetnum<(NUMTSETS);tsetnum++) /* find tsetgo in tsets*/
- if (tsets[tsetnum].tableid==tsetgo) break;
-
- (*tsets[tsetnum].Line_init)(); /* Initialize the line */
-
- rotorgo = tsets[tsetnum].rotori; /* get the rotor ident */
-
- while (rotorgo!=\0) { /* do until cr detect */
- /* unless rotorgo is 0 */
- rotornum=0; /* start at first rotor */
- while (rotors[rotornum].rotorid!=rotorgo) {/* scan list for match*/
- rotornum++; /* go to next if not */
- if (rotors[rotornum].rotorid==\0) /* did we not find it? */
- rotorgo = \0; /* Not found, GET OUT! */
- }
- if (rotorgo!=\0) { /* now scan good ones */
- while (rotors[rotornum].rotorid==rotorgo) {
- /* for each valid entry */
- tty_mode.sg_erase = CERASE; /* prepare parameters */
- tty_mode.sg_kill = CKILL;
- tty_mode.sg_flags = rotors[rotornum].flags;
- tty_mode.sg_ispeed = rotors[rotornum].speed;
- tty_mode.sg_ospeed = rotors[rotornum].speed;
- stty(tty_lun,&tty_mode); /* set tty parameters */
- delay(1);
- j=0; /* count of cr's */
- while ((j<2) && (read(tty_lun,&chr,1)>0)) {
- /* go until 2 cr's, eof, or we get a bad chr */
- if ((chr=='\n') || (chr=='\r')) {
- fprintf(outdev,rotormsg);
- j++; /* count them */
- }
- else
- break;
- }
-
- if (j==2) { /* we got 2 cr's, GO! */
-
- ttys_count = 0;
- ttysfile = fopen("/etc/ttys","r"); /* do it again */
- while (fread(&chr,1,1,ttysfile)>0) /* get entry */
- getentry(chr);
- fclose(ttysfile); /* have ttys information*/
-
- ttysfile = fopen("/etc/ttys","w"); /* now update */
- for(i=0;i<ttys_count;i++) {
- if (0==strcmp(ttymatch,ttys[i].dpath))
- strcpy(ttys[i].tbaud,rotors[rotornum].tbaudset);
- /* match entry & change */
- fprintf(ttysfile,"%s:%s:%s:%s:%s:%s:%s:%s\n",
- ttys[i].state,
- ttys[i].lineno,
- ttys[i].dpath,
- ttys[i].devnum,
- ttys[i].ttyid,
- ttys[i].tbaud,
- ttys[i].tsetb,
- ttys[i].extra
- ); /* put back in file */
- };
- fclose(ttysfile);
- rotorgo = \0; /* done, exit */
- } else {
- rotornum++; /* otherwise next entry */
- }
- } /* end while matching rotorgo */
- } /* end if (rotorgo) */
- } /* end while (rotorgo) */
-
- fprintf(outdev,"\n\nCharles River Data Systems 68/35");
- if (*sysname.nodename) /* if nodename, print it*/
- fprintf(outdev," (%s)",sysname.nodename);
- fprintf(outdev,"\n\015");
-
- fexecl(post_login, indev, outdev, outdev, "login", ttymatch, 0);
- exit(1); /* Never get here??? */
- }
-
- getentry(a) /* parse entry from /etc/ttys file, increment ttys_count */
- char a;
- {
- char *ptr; /* field pointer in record */
- char *tbl[8]; /* ttys record field pointers */
- int i; /* field number, general purpose*/
-
- tbl[0]=ttys[ttys_count].state; /* point to fields */
- tbl[1]=ttys[ttys_count].lineno;
- tbl[2]=ttys[ttys_count].dpath;
- tbl[3]=ttys[ttys_count].devnum;
- tbl[4]=ttys[ttys_count].ttyid;
- tbl[5]=ttys[ttys_count].tbaud;
- tbl[6]=ttys[ttys_count].tsetb;
- tbl[7]=ttys[ttys_count].extra;
-
- for(i=0;i<8;i++) *tbl[i]=0; /* init fields to null */
-
- i = 0; /* start at first field */
- while (a!=10) { /* watch for EOL */
- ptr=tbl[i]; /* point at field */
- while ((a!=10) && ((i==7) || (a!=58))) {
- *ptr++=a; /* save chr if valid */
- if (fread(&a,1,1,ttysfile)==0) a=10;/* EOF, terminate */
- }
- if (a!=10)
- if (fread(&a,1,1,ttysfile)==0) a=10;/* is there next field? */
- *ptr=0; /* mark end of string */
- if (i<7) i++; /* next field ptr */
- }
- ttys_count++; /* count line-item */
- }
-
- at_init()
- {
- int awake = 0;
- char junk;
-
- tty_mode.sg_erase = CERASE; /* prepare parameters */
- tty_mode.sg_kill = CKILL;
- tty_mode.sg_flags = CR1+NL1+CRMOD+RAW;
- tty_mode.sg_ispeed = B1200;
- tty_mode.sg_ospeed = B1200;
- stty(tty_lun,&tty_mode); /* set tty parameters */
-
- sleep(4);
- fprintf(outdev,"+++"); /* get modems attention */
- sleep(4);
- fprintf(outdev,"\r");
- sleep(1);
- fprintf(outdev,"ATZ\r"); /* reset modem */
- sleep(1);
- fprintf(outdev,"ATS0=1\r"); /* auto answer */
- sleep(1);
- junk=' ';
- while(junk!='1') read(tty_lun,&junk,1); /* flush input buffer */
- while(junk!='\r') read(tty_lun,&junk,1);
- }
-