|
|
1.1 root 1: char *ckxv = "Unix tty I/O, 4C(037), 31 Jul 85";
2:
3: /* C K U T I O */
4:
5: /* C-Kermit interrupt, terminal control & i/o functions for Unix systems */
6:
7: /*
8: Author: Frank da Cruz (SY.FDC@CU20B),
9: Columbia University Center for Computing Activities, January 1985.
10: Copyright (C) 1985, Trustees of Columbia University in the City of New York.
11: Permission is granted to any individual or institution to use, copy, or
12: redistribute this software so long as it is not sold for profit, provided this
13: copyright notice is retained.
14: */
15: /* Includes for all Unixes (conditional includes come later) */
16:
17: #include <sys/types.h> /* Types */
18: #include <sys/dir.h> /* Directory */
19: #include <ctype.h> /* Character types */
20: #include <stdio.h> /* Unix Standard i/o */
21: #include <signal.h> /* Interrupts */
22: #include <setjmp.h> /* Longjumps */
23: #include "ckcdeb.h" /* Typedefs, formats for debug() */
24:
25: /* Maximum length for the name of a tty device */
26:
27: #ifndef DEVNAMLEN
28: #define DEVNAMLEN 25
29: #endif
30:
31: /* 4.1 BSD support added by Charles E. Brooks, EDN-VAX */
32: /* Fortune 16:32 For:Pro 1.7 support mostly like 4.1, added by J-P Dumas */
33:
34: #ifdef BSD4
35: #define ANYBSD
36: #undef DIRSIZ
37: #define DIRSIZ (sizeof(struct direct))
38: #ifdef MAXNAMLEN
39: #define BSD42
40: char *ckxsys = " 4.2 BSD";
41: #else
42: #ifdef FT17
43: #define BSD41
44: char *ckxsys = " For:Pro Fortune 1.7";
45: #else
46: #define BSD41
47: #ifndef C70
48: char *ckxsys = " 4.1 BSD";
49: #endif
50: #endif
51: #endif
52: #endif
53:
54: /* 2.9bsd support contributed by Bradley Smith, UCLA */
55: #ifdef BSD29
56: #define ANYBSD
57: char *ckxsys = " 2.9 BSD";
58: #endif
59:
60: /*
61: Version 7 UNIX support contributed by Gregg Wonderly,
62: Oklahoma State University: [email protected]
63: */
64: #ifdef V7
65: char *ckxsys = " Version 7 UNIX (tm)";
66: #endif V7
67:
68: /* BBN C70 support from Frank Wancho, WANCHO@SIMTEL20 */
69: #ifdef C70
70: char *ckxsys = " BBN C/70";
71: #endif
72:
73: /* Amdahl UTS 2.4 (v7 derivative) for IBM 370 series compatible mainframes */
74: /* Contributed by Garard Gaye, Jean-Pierre Dumas, DUMAS@SUMEX-AIM. */
75: #ifdef UTS24
76: char *ckxsys = " Amdahl UTS 2.4";
77: #endif
78:
79: /* Pro/Venix Version 1.x support from Columbia U. */
80: #ifdef PROVX1
81: char *ckxsys = " Pro-3xx Venix v1";
82: #endif
83:
84: /* Tower support contributed by John Bray, Auburn, Alabama */
85: #ifdef TOWER1
86: char *ckxsys = " NCR Tower 1632, OS 1.02";
87: #endif
88:
89: /* Sys III/V, Xenix, PC/IX support by Herm Fischer, Encino, CA */
90: #ifdef UXIII
91: #ifdef XENIX
92: char *ckxsys = " Xenix/286";
93: #else
94: #ifdef PCIX
95: char *ckxsys = " PC/IX";
96: #else
97: #ifdef ISIII
98: char *ckxsys = " Interactive Systems Corp System III";
99: #else
100: char *ckxsys = " AT&T System III/System V";
101: #endif
102: #endif
103: #endif
104: #endif
105:
106: /* Features... */
107:
108: /* Do own buffering, using unbuffered read() calls... */
109: #ifdef UXIII
110: #define MYREAD
111: #endif
112:
113: #ifdef BSD42
114: #define MYREAD
115: #endif
116:
117: /*
118: Note - KERLD is the Berkeley Unix Berknet line driver, modified to pass
119: through all 8 bits, and to allow an arbitrary break character to be set.
120: Don't define this symbol unless you have made this modification to your
121: 4.2BSD kernel!
122: */
123: #ifdef BSD4
124: /* #define KERLD */ /* <-- note, commented out */
125: #endif
126:
127: /*
128: Variables available to outside world:
129:
130: dftty -- Pointer to default tty name string, like "/dev/tty".
131: dfloc -- 0 if dftty is console, 1 if external line.
132: dfprty -- Default parity
133: dfflow -- Default flow control
134: ckxech -- Flag for who echoes console typein:
135: 1 - The program (system echo is turned off)
136: 0 - The system (or front end, or terminal).
137: functions that want to do their own echoing should check this flag
138: before doing so.
139:
140: flfnam -- Name of lock file, including its path, e.g.,
141: "/usr/spool/uucp/LCK..cul0" or "/etc/locks/tty77"
142: hasLock -- Flag set if this kermit established a uucp lock.
143: inbufc -- number of tty line rawmode unread characters
144: (system III/V unixes)
145: backgrd -- Flag indicating program executing in background ( & on
146: end of shell command). Used to ignore INT and QUIT signals.
147:
148: Functions for assigned communication line (either external or console tty):
149:
150: sysinit() -- System dependent program initialization
151: ttopen(ttname,local,mdmtyp) -- Open the named tty for exclusive access.
152: ttclos() -- Close & reset the tty, releasing any access lock.
153: ttpkt(speed,flow) -- Put the tty in packet mode and set the speed.
154: ttvt(speed,flow) -- Put the tty in virtual terminal mode.
155: or in DIALING or CONNECTED modem control state.
156: ttinl(dest,max,timo) -- Timed read line from the tty.
157: ttinc(timo) -- Timed read character from tty.
158: myread() -- System 3 raw mode bulk buffer read, gives
159: -- subsequent chars one at a time and simulates
160: -- FIONREAD!
161: myunrd(c) -- Places c back in buffer to be read (one only)
162: ttchk() -- See how many characters in tty input buffer.
163: ttxin(n,buf) -- Read n characters from tty (untimed).
164: ttol(string,length) -- Write a string to the tty.
165: ttoc(c) -- Write a character to the tty.
166: ttflui() -- Flush tty input buffer.
167:
168: ttlock(ttname) -- Lock against uucp collisions (Sys III)
169: ttunlck() -- Unlock " " "
170: look4lk(ttname) -- Check if a lock file exists
171: */
172:
173: /*
174: Functions for console terminal:
175:
176: congm() -- Get console terminal modes.
177: concb(esc) -- Put the console in single-character wakeup mode with no echo.
178: conbin(esc) -- Put the console in binary (raw) mode.
179: conres() -- Restore the console to mode obtained by congm().
180: conoc(c) -- Unbuffered output, one character to console.
181: conol(s) -- Unbuffered output, null-terminated string to the console.
182: conola(s) -- Unbuffered output, array of strings to the console.
183: conxo(n,s) -- Unbuffered output, n characters to the console.
184: conchk() -- Check if characters available at console (bsd 4.2).
185: Check if escape char (^\) typed at console (System III/V).
186: coninc(timo) -- Timed get a character from the console.
187: conint() -- Enable terminal interrupts on the console if not background.
188: connoi() -- Disable terminal interrupts on the console if not background.
189:
190: Time functions
191:
192: msleep(m) -- Millisecond sleep
193: ztime(&s) -- Return pointer to date/time string
194: rtimer() -- Reset timer
195: gtimer() -- Get elapsed time since last call to rtimer()
196: */
197:
198: /* Conditional Includes */
199:
200: #ifdef FT17
201: #include <sys/file.h> /* File information */
202: #endif
203:
204: #ifndef PROVX1
205: #include <sys/file.h> /* File information */
206: #endif
207:
208: /* System III, System V */
209:
210: #ifdef UXIII
211: #include <termio.h>
212: #include <sys/ioctl.h>
213: #include <fcntl.h> /* directory reading for locking */
214: #include <errno.h> /* error numbers for system returns */
215: #endif
216:
217: /* Not Sys III/V */
218:
219: #ifndef UXIII
220: #include <sgtty.h> /* Set/Get tty modes */
221: #ifndef PROVX1
222: #ifndef V7
223: #ifndef BSD41
224: #include <sys/time.h> /* Clock info (for break generation) */
225: #endif
226: #endif
227: #endif
228: #endif
229:
230: #ifdef BSD41
231: #include <sys/timeb.h> /* BSD 4.1 ... ceb */
232: #endif
233:
234: #ifdef TOWER1
235: #include <sys/timeb.h> /* Clock info for NCR Tower */
236: #endif
237:
238: /* Declarations */
239:
240: long time(); /* All Unixes should have this... */
241: extern int errno; /* System call error return */
242:
243: /* Special stuff for V7 input buffer peeking */
244:
245: #ifdef V7
246: int kmem[2] = { -1, -1};
247: char *initrawq(), *qaddr[2]={0,0};
248: #define CON 0
249: #define TTY 1
250: #endif
251:
252: /* dftty is the device name of the default device for file transfer */
253: /* dfloc is 0 if dftty is the user's console terminal, 1 if an external line */
254:
255: #ifdef PROVX1
256: char *dftty = "/dev/com1.dout"; /* Only example so far of a system */
257: int dfloc = 1; /* that goes in local mode by default */
258: #else
259: char *dftty = CTTNAM; /* Remote by default, use normal */
260: int dfloc = 0; /* controlling terminal name. */
261: #endif
262:
263: int dfprty = 0; /* Parity (0 = none) */
264: int dfflow = 1; /* Xon/Xoff flow control */
265: int backgrd = 0; /* Assume in foreground (no '&' ) */
266:
267: int ckxech = 0; /* 0 if system normally echoes console characters, else 1 */
268:
269: /* Declarations of variables global within this module */
270:
271: static long tcount; /* Elapsed time counter */
272:
273: static char *brnuls = "\0\0\0\0\0\0\0"; /* A string of nulls */
274:
275: static jmp_buf sjbuf, jjbuf; /* Longjump buffer */
276: static int lkf = 0, /* Line lock flag */
277: conif = 0, /* Console interrupts on/off flag */
278: cgmf = 0, /* Flag that console modes saved */
279: xlocal = 0, /* Flag for tty local or remote */
280: ttyfd = -1; /* TTY file descriptor */
281: static char escchr; /* Escape or attn character */
282:
283: /* Special line discipline, 4.2bsd only, and only with kernel mods... */
284: #ifdef KERLD
285: static int kerld = 1; /* Special Kermit line discipline... */
286: struct tchars oldc, newc; /* Special characters */
287: int ld = NETLDISC; /* Really a hack to "Berknet" l.d. */
288: int oldld; /* Old discipline */
289: #else
290: static int kerld = 0; /* Not selected, no special l.d. */
291: #endif
292:
293: #ifdef BSD42
294: static struct timeval tv; /* For getting time, from sys/time.h */
295: static struct timezone tz;
296: #endif
297:
298: #ifdef BSD29
299: static struct timeval tv; /* For getting time, from sys/time.h */
300: static struct timezone tz; /* Same as 4.2 */
301: #endif
302:
303: #ifdef BSD41
304: static long clock; /* For getting time from sys/time.h */
305: static struct timeb ftp; /* And from sys/timeb.h */
306: #endif
307:
308: #ifdef TOWER1
309: static long clock; /* For getting time from sys/time.h */
310: static struct timeb ftp; /* And from sys/timeb.h */
311: #endif
312:
313: #ifdef V7
314: static long clock;
315: #endif
316:
317: #ifdef UXIII
318: static struct termio /* sgtty info... */
319: ttold, ttraw, tttvt, /* for communication line */
320: ccold, ccraw, cccbrk; /* and for console */
321: #else
322: static struct sgttyb /* sgtty info... */
323: ttold, ttraw, tttvt, ttbuf, /* for communication line */
324: ccold, ccraw, cccbrk; /* and for console */
325: #endif
326:
327: static char flfnam[80]; /* uucp lock file path name */
328: static int hasLock = 0; /* =1 if this kermit locked uucp */
329: static int inbufc = 0; /* stuff for efficient SIII raw line */
330: static int ungotn = -1; /* pushback to unread character */
331: static int conesc = 0; /* set to 1 if esc char (^\) typed */
332:
333: static int ttlock(); /* definition of ttlock subprocedure */
334: static int ttunlck(); /* and unlock subprocedure */
335: static char ttnmsv[DEVNAMLEN]; /* copy of open path for tthang */
336:
337: /* S Y S I N I T -- System-dependent program initialization. */
338:
339: sysinit() {
340:
341: /* for now, nothing... */
342:
343: }
344:
345: /* T T O P E N -- Open a tty for exclusive access. */
346:
347: /* Returns 0 on success, -1 on failure. */
348: /*
349: If called with lcl < 0, sets value of lcl as follows:
350: 0: the terminal named by ttname is the job's controlling terminal.
351: 1: the terminal named by ttname is not the job's controlling terminal.
352: But watch out: if a line is already open, or if requested line can't
353: be opened, then lcl remains (and is returned as) -1.
354: */
355: ttopen(ttname,lcl,modem) char *ttname; int *lcl, modem; {
356:
357: #ifdef UXIII
358: char *ctermid(); /* Wish they all had this! */
359: #endif
360: char *x; extern char* ttyname();
361: char cname[DEVNAMLEN];
362:
363: if (ttyfd > -1) return(0); /* If already open, ignore this call */
364: xlocal = *lcl; /* Make this available to other fns */
365:
366: #ifndef UXIII
367: ttyfd = open(ttname,2); /* Try to open for read/write */
368: #else
369: /* if modem connection, don't wait for carrier */
370: ttyfd = open(ttname,O_RDWR | (modem ? O_NDELAY : 0) );
371: #endif
372:
373: if (ttyfd < 0) { /* If couldn't open, fail. */
374: return(-1);
375: }
376: strncpy(ttnmsv,ttname,DEVNAMLEN); /* Open, keep copy of name locally. */
377:
378: /* Caller wants us to figure out if line is controlling tty */
379:
380: debug(F111,"ttopen",ttname,*lcl);
381: if (*lcl == -1) {
382: if (strcmp(ttname,CTTNAM) == 0) { /* "/dev/tty" always remote */
383: debug(F110," Same as CTTNAM",ttname,0);
384: xlocal = 0;
385: } else if (isatty(0)) { /* Else, if stdin not redirected */
386: x = ttyname(0); /* then compare its device name */
387: strncpy(cname,x,DEVNAMLEN); /* (copy from internal static buf) */
388: debug(F110," ttyname(0)",x,0);
389: x = ttyname(ttyfd); /* ...with real name of ttname. */
390: xlocal = (strncmp(x,cname,DEVNAMLEN) == 0) ? 0 : 1;
391: debug(F111," ttyname",x,xlocal);
392: } else { /* Else, if stdin redirected... */
393: #ifdef UXIII
394: /* Sys III/V provides nice ctermid() function to get name of controlling tty */
395: ctermid(cname); /* Get name of controlling terminal */
396: debug(F110," ctermid",cname,0);
397: x = ttyname(ttyfd); /* Compare with name of comm line. */
398: xlocal = (strncmp(x,cname,DEVNAMLEN) == 0) ? 0 : 1;
399: debug(F111," ttyname",x,xlocal);
400: #else
401: /* Just assume local, so "set speed" and similar commands will work */
402: /* If not really local, how could it work anyway?... */
403: xlocal = 1;
404: debug(F101," redirected stdin","",xlocal);
405: #endif
406: }
407: }
408:
409: /* Now check if line is locked -- if so fail, else lock for ourselves */
410:
411: lkf = 0; /* Check lock */
412: if (xlocal > 0) {
413: if (ttlock(ttname) < 0) {
414: fprintf(stderr,"Exclusive access to %s denied\n",ttname);
415: close(ttyfd); ttyfd = -1;
416: debug(F110," Access denied by lock",ttname,0);
417: return(-1); /* Not if already locked */
418: } else lkf = 1;
419: }
420:
421: /* Got the line, now set the desired value for local. */
422:
423: if (*lcl < 0) *lcl = xlocal;
424:
425: /* Some special stuff for v7... */
426:
427: #ifdef V7
428: if (kmem[TTY] < 0) { /* If open, then skip this. */
429: qaddr[TTY] = initrawq(ttyfd); /* Init the queue. */
430: if ((kmem[TTY] = open("/dev/kmem", 0)) < 0) {
431: fprintf(stderr, "Can't read /dev/kmem in ttopen.\n");
432: perror("/dev/kmem");
433: exit(1);
434: }
435: }
436: #endif V7
437:
438: /* Request exclusive access on systems that allow it. */
439:
440: #ifndef XENIX
441: /* Xenix exclusive access prevents open(close(...)) from working... */
442: #ifdef TIOCEXCL
443: if (ioctl(ttyfd,TIOCEXCL, NULL) < 0)
444: fprintf(stderr,"Warning, problem getting exclusive access\n");
445: #endif
446: #endif
447:
448: /* Get tty device settings */
449:
450: #ifndef UXIII
451: gtty(ttyfd,&ttold); /* Get sgtty info */
452: gtty(ttyfd,&ttraw); /* And a copy of it for packets*/
453: gtty(ttyfd,&tttvt); /* And one for virtual tty service */
454: #else
455: ioctl(ttyfd,TCGETA,&ttold); /* Same deal for Sys III, Sys V */
456: ioctl(ttyfd,TCGETA,&ttraw);
457: ioctl(ttyfd,TCGETA,&tttvt);
458: #endif
459: debug(F101,"ttopen, ttyfd","",ttyfd);
460: debug(F101," lcl","",*lcl);
461: debug(F111," lock file",flfnam,lkf);
462: return(0);
463: }
464:
465: /* T T C L O S -- Close the TTY, releasing any lock. */
466:
467: ttclos() {
468: if (ttyfd < 0) return(0); /* Wasn't open. */
469: if (xlocal) {
470: if (tthang()) /* Hang up phone line */
471: fprintf(stderr,"Warning, problem hanging up the phone\n");
472: if (ttunlck()) /* Release uucp-style lock */
473: fprintf(stderr,"Warning, problem releasing lock\n");
474: }
475: ttres(); /* Reset modes. */
476: /* Relinquish exclusive access if we might have had it... */
477: #ifndef XENIX
478: #ifdef TIOCEXCL
479: #ifdef TIOCNXCL
480: if (ioctl(ttyfd, TIOCNXCL, NULL) < 0)
481: fprintf(stderr,"Warning, problem relinquishing exclusive access\n");
482: #endif
483: #endif
484: #endif
485: close(ttyfd); /* Close it. */
486: ttyfd = -1; /* Mark it as closed. */
487: return(0);
488: }
489:
490: /* T T H A N G -- Hangup phone line */
491:
492: tthang() {
493: #ifdef UXIII
494: unsigned short ttc_save;
495: #endif
496:
497: if (ttyfd < 0) return(0); /* Not open. */
498: #ifdef ANYBSD
499: ioctl(ttyfd,TIOCCDTR,0); /* Clear DTR */
500: msleep(500); /* Let things settle */
501: ioctl(ttyfd,TIOCSDTR,0); /* Restore DTR */
502: #endif
503: #ifdef UXIII
504: ttc_save = ttraw.c_cflag;
505: ttraw.c_cflag &= ~CBAUD; /* swa: set baud rate to 0 to hangup */
506: if (ioctl(ttyfd,TCSETAF,&ttraw) < 0) return(-1); /* do it */
507: msleep(100); /* let things settle */
508: ttraw.c_cflag = ttc_save;
509: #ifndef XENIX /* xenix cannot do close/open when carrier drops */
510: /* following corrects a PC/IX defficiency */
511: ttc_save = fcntl(ttyfd,F_GETFL,0);
512: close(ttyfd); /* close/reopen file descriptor */
513: if ((ttyfd = open(ttnmsv, ttc_save)) < 0) return(-1);
514: #endif
515: if (ioctl(ttyfd,TCSETAF,&ttraw) < 0) return(-1); /* un-do it */
516: #endif
517: return (0);
518: }
519:
520:
521: /* T T R E S -- Restore terminal to "normal" mode. */
522:
523: ttres() { /* Restore the tty to normal. */
524: if (ttyfd < 0) return(-1); /* Not open. */
525: #ifndef UXIII /* except for sIII, */
526: sleep(1); /* Wait for pending i/o to finish. */
527: #endif /* (sIII does wait in ioctls) */
528: #ifdef KERLD
529: if (kerld) ioctl(ttyfd,TIOCSETD,&oldld); /* Restore old line discipline. */
530: #endif
531: #ifdef UXIII
532: if (ioctl(ttyfd,TCSETAW,&ttold) < 0) return(-1); /* restore termio stuff */
533: #else
534: if (stty(ttyfd,&ttold) < 0) return(-1); /* Restore sgtty stuff */
535: #endif
536: #ifdef KERLD
537: if (kerld) ioctl(ttyfd,TIOCSETC,&oldc); /* Restore old special chars. */
538: #endif
539:
540: return(0);
541: }
542:
543: /* Exclusive uucp file locking control */
544: /*
545: by H. Fischer, creative non-Bell coding !
546: copyright rights for lock modules assigned to Columbia University
547: */
548: static char *
549: xxlast(s,c) char *s; char c; { /* Equivalent to strrchr() */
550: int i;
551: for (i = strlen(s); i > 0; i--)
552: if ( s[i-1] == c ) return( s + (i - 1) );
553: return(NULL);
554: }
555: static
556: look4lk(ttname) char *ttname; {
557: extern char *strcat(), *strcpy();
558: char *device, *devname;
559: char lockfil[DIRSIZ+1];
560:
561: #ifdef ISIII
562: char *lockdir = "/etc/locks";
563: #else
564: #ifdef ATT3BX
565: char *lockdir = "/usr/spool/locks";
566: #else
567: char *lockdir = "/usr/spool/uucp";
568: #endif
569: #endif
570:
571: device = ( (devname=xxlast(ttname,'/')) != NULL ? devname+1 : ttname);
572:
573: #ifdef ISIII
574: (void) strcpy( lockfil, device );
575: #else
576: strcat( strcpy( lockfil, "LCK.." ), device );
577: #endif
578:
579: if (access( lockdir, 04 ) < 0) { /* read access denied on lock dir */
580: fprintf(stderr,"Warning, read access to lock directory denied\n");
581: return( 1 ); /* cannot check or set lock file */
582: }
583:
584: strcat(strcat(strcpy(flfnam,lockdir),"/"), lockfil);
585: debug(F110,"look4lk",flfnam,0);
586:
587: if ( ! access( flfnam, 00 ) ) { /* print out lock file entry */
588: char lckcmd[40] ;
589: strcat( strcpy(lckcmd, "ls -l ") , flfnam);
590: system(lckcmd);
591: if (access(flfnam,02) == 0)
592: printf("(You may type \"! rm %s\" to remove this file)\n",flfnam);
593: return( -1 );
594: }
595: if ( access( lockdir, 02 ) < 0 ) { /* lock file cannot be written */
596: fprintf(stderr,"Warning, write access to lock directory denied\n");
597: return( 1 );
598: }
599: return( 0 ); /* okay to go ahead and lock */
600: }
601:
602: /* T T L O C K */
603:
604:
605: static
606: ttlock(ttyfd) char *ttyfd; { /* lock uucp if possible */
607: #ifdef ATT3BX
608: FILE *lck_fild;
609: #endif
610: int lck_fil, l4l;
611: int pid_buf = getpid(); /* pid to save in lock file */
612:
613: hasLock = 0; /* not locked yet */
614: l4l = look4lk(ttyfd);
615: if (l4l < 0) return (-1); /* already locked */
616: if (l4l == 1) return (0); /* can't read/write lock directory */
617: lck_fil = creat(flfnam, 0444); /* create lock file ... */
618: if (lck_fil < 0) return (-1); /* create of lockfile failed */
619: /* creat leaves file handle open for writing -- hf */
620: #ifdef ATT3BX
621: fprintf((lck_fild = fdopen(lck_fil, "w")), "%10d\n", pid_buf);
622: fflush(lck_fild);
623: #else
624: write (lck_fil, &pid_buf, sizeof(pid_buf) ); /* uucp expects int in file */
625: #endif
626: close (lck_fil);
627: hasLock = 1; /* now is locked */
628: return(0);
629: }
630:
631: /* T T U N L O C K */
632:
633: static
634: ttunlck() { /* kill uucp lock if possible */
635: if (hasLock) return( unlink( flfnam ) );
636: }
637:
638: /* T T P K T -- Condition the communication line for packets. */
639: /* or for modem dialing */
640:
641: #define DIALING 4 /* flags (via flow) for modem handling */
642: #define CONNECT 5
643:
644: /* If called with speed > -1, also set the speed. */
645:
646: /* Returns 0 on success, -1 on failure. */
647:
648: ttpkt(speed,flow) int speed, flow; {
649: int s;
650: if (ttyfd < 0) return(-1); /* Not open. */
651:
652: #ifdef KERLD
653: /* Note, KERLD ignores the TANDEM, ECHO, and CRMOD bits */
654: if (kerld) {
655: ioctl(ttyfd,TIOCGETD,&oldld); /* Get line discipline */
656: ioctl(ttyfd,TIOCGETC,&oldc); /* Get special chars */
657: newc = oldc; /* Copy special chars */
658: newc.t_brkc = '\r'; /* Set CR to be break character */
659: if(ioctl(ttyfd,TIOCSETC,&newc) < 0) return(-1);
660: }
661: #endif
662:
663: s = ttsspd(speed); /* Check the speed */
664:
665: #ifndef UXIII
666: if (flow == 1) ttraw.sg_flags |= TANDEM; /* Use XON/XOFF if selected */
667: if (flow == 0) ttraw.sg_flags &= ~TANDEM;
668: ttraw.sg_flags |= RAW; /* Go into raw mode */
669: ttraw.sg_flags &= ~(ECHO|CRMOD); /* Use CR for break character */
670: #ifdef TOWER1
671: ttraw.sg_flags &= ~ANYP; /* Must tell Tower no parityr */
672: #endif
673: if (s > -1) ttraw.sg_ispeed = ttraw.sg_ospeed = s; /* Do the speed */
674: if (stty(ttyfd,&ttraw) < 0) return(-1); /* Set the new modes. */
675:
676: #ifdef MYREAD
677: #ifdef BSD4
678: /* Try to make reads nonblocking */
679: if (kerld == 0) {
680: if (fcntl(ttyfd,F_SETFL,fcntl(ttyfd,F_GETFL,0) & FNDELAY) == -1)
681: return(-1);
682: else return(0);
683: }
684: #endif
685: #endif
686: #endif
687:
688: #ifdef UXIII
689: if (flow == 1) ttraw.c_iflag |= (IXON|IXOFF);
690: if (flow == 0) ttraw.c_iflag &= ~(IXON|IXOFF);
691:
692: if (flow == DIALING) ttraw.c_cflag |= CLOCAL|HUPCL;
693: if (flow == CONNECT) ttraw.c_cflag &= ~CLOCAL;
694:
695: ttraw.c_lflag &= ~(ICANON|ECHO);
696: ttraw.c_lflag |= ISIG; /* do check for interrupt */
697: ttraw.c_iflag |= (BRKINT|IGNPAR);
698: ttraw.c_iflag &= ~(IGNBRK|INLCR|IGNCR|ICRNL|IUCLC|INPCK|ISTRIP|IXANY);
699: ttraw.c_oflag &= ~OPOST;
700: ttraw.c_cflag &= ~(CSIZE|PARENB);
701: ttraw.c_cflag |= (CS8|CREAD);
702: ttraw.c_cc[4] = 1;
703: ttraw.c_cc[5] = 0;
704:
705: if (s > -1) ttraw.c_cflag &= ~CBAUD, ttraw.c_cflag |= s; /* set speed */
706:
707: if (ioctl(ttyfd,TCSETAW,&ttraw) < 0) return(-1); /* set new modes . */
708: if (flow == DIALING) {
709: if (fcntl(ttyfd,F_SETFL, fcntl(ttyfd, F_GETFL, 0) & ~O_NDELAY) < 0 )
710: return(-1);
711: close( open(ttnmsv,2) ); /* magic to force mode change!!! */
712: }
713: #endif
714:
715: #ifdef KERLD
716: if (kerld) {
717: if (ioctl(ttyfd,TIOCSETD,&ld) < 0)
718: return(-1); /* Set line discpline. */
719: }
720: #endif
721:
722: ttflui(); /* Flush any pending input */
723: return(0);
724: }
725:
726: /* T T V T -- Condition communication line for use as virtual terminal */
727:
728: ttvt(speed,flow) int speed, flow; {
729: int s;
730: if (ttyfd < 0) return(-1); /* Not open. */
731:
732: s = ttsspd(speed); /* Check the speed */
733:
734: #ifndef UXIII
735: if (flow == 1) tttvt.sg_flags |= TANDEM; /* XON/XOFF if selected */
736: if (flow == 0) tttvt.sg_flags &= ~TANDEM;
737: tttvt.sg_flags |= RAW; /* Raw mode */
738: #ifdef TOWER1
739: tttvt.sg_flags &= ~(ECHO|ANYP); /* No echo or system III ??? parity */
740: #else
741: tttvt.sg_flags &= ~ECHO; /* No echo */
742: #endif
743: if (s > -1) tttvt.sg_ispeed = tttvt.sg_ospeed = s; /* Do the speed */
744: if (stty(ttyfd,&tttvt) < 0) return(-1);
745: #ifdef MYREAD
746: #ifdef BSD4
747: /* Make reads nonblocking */
748: if (kerld == 0) {
749: if (fcntl(ttyfd,F_SETFL,fcntl(ttyfd,F_GETFL,0) & FNDELAY) == -1)
750: return(-1);
751: else return(0);
752: }
753: #endif
754: #endif
755:
756: #else
757: if (flow == 1) tttvt.c_iflag |= (IXON|IXOFF);
758: if (flow == 0) tttvt.c_iflag &= ~(IXON|IXOFF);
759:
760: if (flow == DIALING) tttvt.c_cflag |= CLOCAL|HUPCL;
761: if (flow == CONNECT) tttvt.c_cflag &= ~CLOCAL;
762:
763: tttvt.c_lflag &= ~(ISIG|ICANON|ECHO);
764: tttvt.c_iflag |= (IGNBRK|IGNPAR);
765: tttvt.c_iflag &= ~(INLCR|IGNCR|ICRNL|IUCLC|BRKINT|INPCK|ISTRIP|IXANY);
766: tttvt.c_oflag &= ~OPOST;
767: tttvt.c_cflag &= ~(CSIZE|PARENB);
768: tttvt.c_cflag |= (CS8|CREAD);
769: tttvt.c_cc[4] = 1;
770: tttvt.c_cc[5] = 0;
771:
772: if (s > -1) tttvt.c_cflag &= ~CBAUD, tttvt.c_cflag |= s; /* set speed */
773:
774: if (ioctl(ttyfd,TCSETAW,&tttvt) < 0) return(-1); /* set new modes . */
775: if (flow == DIALING) {
776: if (fcntl(ttyfd,F_SETFL, fcntl(ttyfd, F_GETFL, 0) & ~O_NDELAY) < 0 )
777: return(-1);
778: close( open(ttnmsv,2) ); /* magic to force mode change!!! */
779: }
780: return(0);
781: #endif
782: }
783:
784: /* T T S S P D -- Return the internal baud rate code for 'speed'. */
785:
786: ttsspd(speed) {
787: int s, spdok;
788:
789: if (speed < 0) return(-1);
790: spdok = 1; /* Assume arg ok */
791: switch (speed) {
792: case 0: s = B0; break; /* Just the common ones. */
793: case 110: s = B110; break; /* The others from ttydev.h */
794: case 150: s = B150; break; /* could also be included if */
795: case 300: s = B300; break; /* necessary... */
796: case 600: s = B600; break;
797: case 1200: s = B1200; break;
798: case 1800: s = B1800; break;
799: case 2400: s = B2400; break;
800: case 4800: s = B4800; break;
801: case 9600: s = B9600; break;
802: #ifdef PLEXUS
803: case 19200: s = EXTA; break;
804: #endif
805: default:
806: spdok = 0;
807: fprintf(stderr,"Unsupported line speed - %d\n",speed);
808: fprintf(stderr,"Current speed not changed\n");
809: break;
810: }
811: if (spdok) return(s); else return(-1);
812: }
813:
814:
815:
816: /* T T F L U I -- Flush tty input buffer */
817:
818: ttflui() {
819:
820: #ifndef UXIII
821: long n;
822: #endif
823: if (ttyfd < 0) return(-1); /* Not open. */
824:
825: ungotn = -1; /* Initialize myread() stuff */
826: inbufc = 0;
827:
828: #ifdef UXIII
829: if (ioctl(ttyfd,TCFLSH,0) < 0) perror("flush failed");
830: #else
831: #ifdef TIOCFLUSH
832: #ifdef ANYBSD
833: n = FREAD; /* Specify read queue */
834: if (ioctl(ttyfd,TIOCFLUSH,&n) < 0) perror("flush failed");
835: #else
836: if (ioctl(ttyfd,TIOCFLUSH,0) < 0) perror("flush failed");
837: #endif
838: #endif
839: #endif
840: return(0);
841: }
842:
843: /* Interrupt Functions */
844:
845:
846: /* Timeout handler for communication line input functions */
847:
848: timerh() {
849: longjmp(sjbuf,1);
850: }
851:
852:
853: /* Set up terminal interrupts on console terminal */
854:
855: #ifdef UXIII
856: esctrp() { /* trap console escapes (^\) */
857: conesc = 1;
858: signal(SIGQUIT,SIG_IGN); /* ignore until trapped */
859: }
860: #endif
861:
862: #ifdef V7
863: esctrp() { /* trap console escapes (^\) */
864: conesc = 1;
865: signal(SIGQUIT,SIG_IGN); /* ignore until trapped */
866: }
867: #endif
868:
869: #ifdef C70
870: esctrp() { /* trap console escapes (^\) */
871: conesc = 1;
872: signal(SIGQUIT,SIG_IGN); /* ignore until trapped */
873: }
874: #endif
875:
876: /* C O N I N T -- Console Interrupt setter */
877:
878: conint(f) int (*f)(); { /* Set an interrupt trap. */
879:
880: if (backgrd) return; /* must ignore signals in bkgrd */
881:
882: /*
883: Except for special cases below, ignore keyboard quit signal.
884: ^\ too easily confused with connect escape, and besides, we don't want
885: to leave lock files around. (Frank Prindle)
886: */
887: signal(SIGQUIT,SIG_IGN);
888:
889: #ifdef UXIII
890: signal(SIGQUIT,esctrp); /* console escape in pkt modes */
891: if (conesc) { /* clear out pending escapes */
892: conesc = 0;
893: }
894: #endif
895:
896: #ifdef V7
897: signal(SIGQUIT,esctrp); /* console escape in pkt modes */
898: if (conesc) { /* clear out pending escapes */
899: conesc = 0;
900: }
901: #endif
902:
903: if (conif) return; /* Nothing to do if already on. */
904:
905: /* check if invoked in background -- if so signals set to be ignored */
906:
907: if (signal(SIGINT,SIG_IGN) == SIG_IGN) {
908: backgrd = 1; /* means running in background */
909: #ifdef UXIII
910: signal(SIGQUIT,SIG_IGN); /* must leave signals ignored */
911: #endif
912: #ifdef V7
913: signal(SIGQUIT,SIG_IGN); /* must leave signals ignored */
914: #endif
915: return;
916: }
917: signal(SIGINT,f); /* Function to trap to on interrupt. */
918: signal(SIGHUP,f); /* Or hangup, so lock file cleared. */
919: conif = 1; /* Flag console interrupts on. */
920: }
921:
922:
923: /* C O N N O I -- Reset console terminal interrupts */
924:
925: connoi() { /* Console-no-interrupts */
926:
927: if (backgrd) return; /* Ignore signals in background */
928:
929: signal(SIGINT,SIG_DFL);
930: signal(SIGHUP,SIG_DFL);
931: signal(SIGQUIT,SIG_DFL);
932: conif = 0; /* Flag interrupt trapping off */
933: }
934:
935: /* myread() -- For use by systems that can do nonblocking read() calls */
936: /*
937: Returns:
938: -1 if no characters available,
939: -2 upon error (such as disconnect),
940: otherwise value of character (0 or greater)
941: */
942: myread() {
943: static int inbuf_item;
944: static CHAR inbuf[257];
945: CHAR readit;
946:
947: if (ungotn >= 0) {
948: readit = ungotn;
949: } else {
950: if (inbufc > 0) {
951: readit = inbuf[++inbuf_item];
952: } else {
953: if ((inbufc = read(ttyfd,inbuf,256)) == 0) { /* end of file */
954: /* means carrier dropped on modem connection */
955: errno = 9999; /* magic number for no carrier */
956: return(-2); /* end of file has no errno */
957: }
958: if (inbufc < 0) return(-2);
959: readit = inbuf[inbuf_item = 0];
960: }
961: inbufc--;
962: }
963: ungotn = -1;
964: return(readit);
965: }
966:
967: myunrd(ch) CHAR ch; { /* push back up to one character */
968: ungotn = ch;
969: }
970:
971: /* I N I T R A W Q -- Set up to read /DEV/KMEM for character count. */
972:
973: #ifdef V7
974: /*
975: Used in Version 7 to simulate Berkeley's FIONREAD ioctl call. This
976: eliminates blocking on a read, because we can read /dev/kmem to get the
977: number of characters available for raw input. If your system can't
978: or you won't let it read /dev/kmem (the world that is) then you must
979: figure out a different way to do the counting of characters available,
980: or else replace this by a dummy function that always returns 0.
981: */
982: /*
983: * Call this routine as: initrawq(tty)
984: * where tty is the file descriptor of a terminal. It will return
985: * (as a char *) the kernel-mode memory address of the rawq character
986: * count, which may then be read. It has the side-effect of flushing
987: * input on the terminal.
988: */
989: /*
990: * John Mackin, Physiology Dept., University of Sydney (Australia)
991: * ...!decvax!mulga!physiol.su.oz!john
992: *
993: * Permission is hereby granted to do anything with this code, as
994: * long as this comment is retained unmodified and no commercial
995: * advantage is gained.
996: */
997: #include <a.out.h>
998: #include <sys/proc.h>
999:
1000: char *initrawq(tty) int tty; {
1001: #ifdef UTS24
1002: return(0);
1003: #else
1004: #ifdef BSD29
1005: return(0);
1006: #else
1007: long lseek();
1008: static struct nlist nl[] = {
1009: {PROCNAME},
1010: {NPROCNAME},
1011: {""}
1012: };
1013: static struct proc *pp;
1014: char *malloc(), *qaddr, *p, c;
1015: int m, pid, me;
1016: NPTYPE xproc; /* Its type is defined in makefile. */
1017: int catch();
1018:
1019: me = getpid();
1020: if ((m = open("/dev/kmem", 0)) < 0) err("kmem");
1021: nlist(BOOTNAME, nl);
1022: if (nl[0].n_type == 0) err("proc array");
1023:
1024: if (nl[1].n_type == 0) err("nproc");
1025:
1026: lseek(m, (long)(nl[1].n_value), 0);
1027: read (m, &xproc, sizeof(xproc));
1028: signal(SIGALRM, catch);
1029: if ((pid = fork()) == 0) {
1030: while(1)
1031: read(tty, &c, 1);
1032: }
1033: alarm(2);
1034:
1035: if(setjmp(jjbuf) == 0) {
1036: while(1)
1037: read(tty, &c, 1);
1038: }
1039: signal(SIGALRM, SIG_DFL);
1040:
1041: #ifdef DIRECT
1042: pp = (struct proc *) nl[0].n_value;
1043: #else
1044: if (lseek(m, (long)(nl[0].n_value), 0) < 0L) err("seek");
1045: if (read(m, &pp, sizeof(pp)) != sizeof(pp)) err("no read of proc ptr");
1046: #endif
1047: lseek(m, (long)(nl[1].n_value), 0);
1048: read(m, &xproc, sizeof(xproc));
1049:
1050: if (lseek(m, (long)pp, 0) < 0L) err("Can't seek to proc");
1051: if ((p = malloc(xproc * sizeof(struct proc))) == NULL) err("malloc");
1052: if (read(m,p,xproc * sizeof(struct proc)) != xproc*sizeof(struct proc))
1053: err("read proc table");
1054: for (pp = (struct proc *)p; xproc > 0; --xproc, ++pp) {
1055: if (pp -> p_pid == (short) pid) goto iout;
1056: }
1057: err("no such proc");
1058:
1059: iout:
1060: close(m);
1061: qaddr = (char *)(pp -> p_wchan);
1062: free (p);
1063: kill(pid, SIGKILL);
1064: wait((int *)0); /* Destroy the ZOMBIEs! */
1065: return (qaddr);
1066: #endif
1067: #endif
1068: }
1069:
1070: /* More V7-support functions... */
1071:
1072: static
1073: err(s) char *s; {
1074: char buf[200];
1075:
1076: sprintf(buf, "fatal error in initrawq: %s", s);
1077: perror(buf);
1078: doexit(1);
1079: }
1080:
1081: static
1082: catch() {
1083: longjmp(jjbuf, -1);
1084: }
1085:
1086:
1087: /* G E N B R K -- Simulate a modem break. */
1088:
1089: #define BSPEED B150
1090:
1091: genbrk(fn) int fn; {
1092: struct sgttyb ttbuf;
1093: int ret, sospeed;
1094:
1095: ret = ioctl(fn, TIOCGETP, &ttbuf);
1096: sospeed = ttbuf.sg_ospeed;
1097: ttbuf.sg_ospeed = BSPEED;
1098: ret = ioctl(fn, TIOCSETP, &ttbuf);
1099: ret = write(fn, "\0\0\0\0\0\0\0\0\0\0\0\0", 8);
1100: ttbuf.sg_ospeed = sospeed;
1101: ret = ioctl(fn, TIOCSETP, &ttbuf);
1102: ret = write(fn, "@", 1);
1103: return;
1104: }
1105: #endif V7
1106:
1107: /* T T C H K -- Tell how many characters are waiting in tty input buffer */
1108:
1109: ttchk() {
1110: int x; long n;
1111: #ifdef FIONREAD
1112: x = ioctl(ttyfd, FIONREAD, &n); /* Berkeley and maybe some others */
1113: debug(F101,"ttchk","",n);
1114: return((x < 0) ? 0 : n);
1115: #else
1116: #ifdef V7
1117: lseek(kmem[TTY], (long) qaddr[TTY], 0);
1118: x = read(kmem[TTY], &n, sizeof(int));
1119: return((x == sizeof(int))? n: 0);
1120: #else V7
1121: #ifdef UXIII
1122: return(inbufc + (ungotn >= 0) );
1123: #else
1124: #ifdef C70
1125: return(inbufc + (ungotn >= 0) );
1126: #else
1127: #ifdef PROVX1
1128: x = ioctl(ttyfd, TIOCQCNT, &ttbuf);
1129: n = ttbuf.sg_ispeed & 0377;
1130: return((x < 0) ? 0 : n);
1131: #else
1132: return(0);
1133: #endif
1134: #endif
1135: #endif
1136: #endif
1137: #endif
1138: }
1139:
1140:
1141: /* T T X I N -- Get n characters from tty input buffer */
1142:
1143: /* Returns number of characters actually gotten, or -1 on failure */
1144:
1145: /* Intended for use only when it is known that n characters are actually */
1146: /* Available in the input buffer. */
1147:
1148: ttxin(n,buf) int n; char *buf; {
1149: int x;
1150: CHAR c;
1151:
1152: #ifdef MYREAD
1153: for( x = 0; (x > -1) && (x < n); buf[x++] = myread() );
1154: #else
1155: debug(F101,"ttxin: n","",n);
1156: x = read(ttyfd,buf,n);
1157: debug(F101," x","",x);
1158: #endif
1159: if (x > 0) buf[x] = '\0';
1160: if (x < 0) x = -1;
1161: return(x);
1162: }
1163:
1164: /* T T O L -- Similar to "ttinl", but for writing. */
1165:
1166: ttol(s,n) int n; char *s; {
1167: int x;
1168: if (ttyfd < 0) return(-1); /* Not open. */
1169: x = write(ttyfd,s,n);
1170: debug(F111,"ttol",s,n);
1171: if (x < 0) debug(F101,"ttol failed","",x);
1172: return(x);
1173: }
1174:
1175:
1176: /* T T O C -- Output a character to the communication line */
1177:
1178: ttoc(c) char c; {
1179: if (ttyfd < 0) return(-1); /* Not open. */
1180: return(write(ttyfd,&c,1));
1181: }
1182:
1183: /* T T I N L -- Read a record (up to break character) from comm line. */
1184: /*
1185: If no break character encountered within "max", return "max" characters,
1186: with disposition of any remaining characters undefined. Otherwise, return
1187: the characters that were read, including the break character, in "dest" and
1188: the number of characters read as the value of function, or 0 upon end of
1189: file, or -1 if an error occurred. Times out & returns error if not completed
1190: within "timo" seconds.
1191: */
1192:
1193: ttinl(dest,max,timo,eol) int max,timo; char *dest; char eol; {
1194: int x, y;
1195: CHAR c;
1196:
1197: if (ttyfd < 0) return(-1); /* Not open. */
1198: if (timo <= 0) { /* Untimed read... */
1199:
1200: #ifdef MYREAD
1201: for (x = y = 0; (x < max) && (c != eol); x++) {
1202: while ((y = myread()) == -1) ;
1203: if (y == -2) return(-1);
1204: dest[x] = y & 0377;
1205: }
1206: #else
1207: x = read(ttyfd,dest,max); /* Try to read. */
1208: #endif
1209: return(x); /* Return the count. */
1210: }
1211:
1212: /* Timed read... */
1213:
1214: signal(SIGALRM,timerh); /* Set up timeout action. */
1215: alarm(timo); /* Set the timer. */
1216: if (setjmp(sjbuf)) /* Do this if timer went off. */
1217: x = -1;
1218: else if (kerld) { /* Efficient Kermit line discipline */
1219: x = read(ttyfd,dest,max); /* for 4.2bsd only... */
1220: } else { /* Normal case... */
1221: for (x = c = y = 0; (x < max) && (c != eol); x++) {
1222: #ifdef MYREAD
1223: while ((y = myread()) == -1) /* Use own buffering if we can */
1224: ;
1225: if (y == -2) y++;
1226: c = y & 0377;
1227: #else
1228: while ((y = read(ttyfd,&c,1)) == 0) /* Else call system */
1229: ; /* ...for each character. */
1230: #endif
1231: if (y < 0) {
1232: alarm(0); /* Error, turn off timer, */
1233: signal(SIGALRM,SIG_DFL); /* and associated interrupt. */
1234: return(y); /* Return the error indication. */
1235: }
1236: dest[x] = c;
1237: }
1238: x++;
1239: }
1240: alarm(0); /* Success, turn off timer, */
1241: signal(SIGALRM,SIG_DFL); /* and associated interrupt. */
1242: return(x); /* Return the count. */
1243: }
1244:
1245: /* T T I N C -- Read a character from the communication line */
1246:
1247: ttinc(timo) int timo; {
1248: int n = 0;
1249: CHAR ch = 0;
1250:
1251: if (ttyfd < 0) return(-1); /* Not open. */
1252: if (timo <= 0) { /* Untimed. */
1253: #ifdef MYREAD
1254: /* comm line failure returns -1 thru myread, so no &= 0377 */
1255: while ((n = myread()) == -1) ; /* Wait for a character... */
1256: if (n == -2) n++;
1257: return( n );
1258: #else
1259: while ((n = read(ttyfd,&ch,1)) == 0) ; /* Wait for a character. */
1260: return( (n > 0) ? (ch & 0377) : n );
1261: #endif
1262: }
1263:
1264: signal(SIGALRM,timerh); /* Timed, set up timer. */
1265: alarm(timo);
1266: if (setjmp(sjbuf)) {
1267: n = -1;
1268: } else {
1269: #ifdef MYREAD
1270: while ((n = myread()) == -1) ; /* If managing own buffer... */
1271: if (n == -2) {
1272: n++;
1273: } else {
1274: ch = n;
1275: n = 1;
1276: }
1277: #else
1278: n = read(ttyfd,&ch,1); /* Otherwise call the system. */
1279: #endif
1280: }
1281: alarm(0); /* Turn off timer, */
1282: signal(SIGALRM,SIG_DFL); /* and interrupt. */
1283: return( (n > 0) ? (ch & 0377) : n ); /* Return char or -1. */
1284: }
1285:
1286: /* T T S N D B -- Send a BREAK signal */
1287:
1288: ttsndb() {
1289: int x; long n; char spd;
1290:
1291: if (ttyfd < 0) return(-1); /* Not open. */
1292:
1293: #ifdef PROVX1
1294: gtty(ttyfd,&ttbuf); /* Get current tty flags */
1295: spd = ttbuf.sg_ospeed; /* Save speed */
1296: ttbuf.sg_ospeed = B50; /* Change to 50 baud */
1297: stty(ttyfd,&ttbuf); /* ... */
1298: write(ttyfd,brnuls,3); /* Send 3 nulls */
1299: ttbuf.sg_ospeed = spd; /* Restore speed */
1300: stty(ttyfd,&ttbuf); /* ... */
1301: return(0);
1302: #else
1303: #ifdef UXIII
1304: if (ioctl(ttyfd,TCSBRK,(char *)0) < 0) { /* Send a BREAK */
1305: perror("Can't send BREAK");
1306: return(-1);
1307: }
1308: return(0);
1309: #else
1310: #ifdef ANYBSD
1311: n = FWRITE; /* Flush output queue. */
1312: ioctl(ttyfd,TIOCFLUSH,&n); /* Ignore any errors.. */
1313: if (ioctl(ttyfd,TIOCSBRK,(char *)0) < 0) { /* Turn on BREAK */
1314: perror("Can't send BREAK");
1315: return(-1);
1316: }
1317: x = msleep(275); /* Sleep for so many milliseconds */
1318: if (ioctl(ttyfd,TIOCCBRK,(char *)0) < 0) { /* Turn off BREAK */
1319: perror("BREAK stuck!!!");
1320: doexit(1); /* Get out, closing the line. */
1321: /* with exit status = 1 */
1322: }
1323: return(x);
1324: #else
1325: #ifdef V7
1326: genbrk(ttyfd); /* Simulate a BREAK */
1327: return(x);
1328: #endif
1329: #endif
1330: #endif
1331: #endif
1332: }
1333:
1334: /* M S L E E P -- Millisecond version of sleep(). */
1335:
1336: /*
1337: Intended only for small intervals. For big ones, just use sleep().
1338: */
1339:
1340: msleep(m) int m; {
1341:
1342: #ifdef PROVX1
1343: sleep(-((m * 60 + 500) / 1000));
1344: return(0);
1345: #endif
1346:
1347: #ifdef ANYBSD
1348: int t1, t3, t4;
1349: #ifdef BSD41
1350: if (ftime(&ftp) < 0) return(-1); /* Get current time. */
1351: t1 = ((ftp.time & 0xff) * 1000) + ftp.millitm;
1352: while (1) {
1353: ftime(&ftp); /* new time */
1354: t3 = (((ftp.time & 0xff) * 1000) + ftp.millitm) - t1;
1355: if (t3 > m) return (t3);
1356: }
1357: #else
1358: /* 2.9 and 4.1 BSD do it this way */
1359: if (gettimeofday(&tv, &tz) < 0) return(-1); /* Get current time. */
1360: t1 = tv.tv_sec; /* Seconds */
1361:
1362: tv.tv_sec = 0; /* Use select() */
1363: tv.tv_usec = m * 1000;
1364: return(select( 0, (int *)0, (int *)0, (int *)0, &tv) );
1365: #endif
1366: #endif
1367:
1368: #ifdef UXIII
1369: #ifdef XENIX
1370: #define CLOCK_TICK 50 /* millisecs per clock tick */
1371: #else
1372: #define CLOCK_TICK 17 /* 1/60 sec */
1373: #endif
1374: extern long times();
1375: long t1, t2, tarray[4];
1376: int t3;
1377:
1378: if ((t1 = times(tarray)) < 0) return(-1);
1379: while (1) {
1380: if ((t2 = times(tarray)) < 0) return(-1);
1381: t3 = ((int)(t2 - t1)) * CLOCK_TICK;
1382: if (t3 > m) return(t3);
1383: }
1384: #endif
1385:
1386: #ifdef TOWER1
1387: int t1, t3;
1388: if (ftime(&ftp) < 0) return(-1); /* Get current time. */
1389: t1 = ((ftp.time & 0xff) * 1000) + ftp.millitm;
1390: while (1) {
1391: ftime(&ftp); /* new time */
1392: t3 = (((ftp.time & 0xff) * 1000) + ftp.millitm) - t1;
1393: if (t3 > m) return (t3);
1394: }
1395: #endif
1396: }
1397:
1398: /* R T I M E R -- Reset elapsed time counter */
1399:
1400: rtimer() {
1401: tcount = time( (long *) 0 );
1402: }
1403:
1404:
1405: /* G T I M E R -- Get current value of elapsed time counter in seconds */
1406:
1407: gtimer() {
1408: int x;
1409: x = (int) (time( (long *) 0 ) - tcount);
1410: rtimer();
1411: return( (x < 0) ? 0 : x );
1412: }
1413:
1414:
1415: /* Z T I M E -- Return date/time string */
1416:
1417: ztime(s) char **s; {
1418:
1419: #ifdef UXIII
1420: extern long time(); /* Sys III/V way to do it */
1421: char *ctime();
1422: long clock_storage;
1423:
1424: clock_storage = time( (long *) 0 );
1425: *s = ctime( &clock_storage );
1426: #endif
1427:
1428: #ifdef PROVX1
1429: int utime[2]; /* Venix way */
1430: time(utime);
1431: *s = ctime(utime);
1432: #endif
1433:
1434: #ifdef ANYBSD
1435: char *asctime(); /* Berkeley way */
1436: struct tm *localtime();
1437: struct tm *tp;
1438: #ifndef BSD41
1439: gettimeofday(&tv, &tz); /* BSD 2.9, 4.2 ... */
1440: time(&tv.tv_sec);
1441: tp = localtime(&tv.tv_sec);
1442: #else
1443: time(&clock); /* BSD 4.1 ... ceb */
1444: tp = localtime(&clock);
1445: #endif
1446: *s = asctime(tp);
1447: #endif
1448:
1449: #ifdef TOWER1
1450: char *asctime(); /* Tower way */
1451: struct tm *localtime();
1452: struct tm *tp;
1453:
1454: time(&clock);
1455: tp = localtime(&clock);
1456: *s = asctime(tp);
1457: #endif
1458: #ifdef V7
1459: char *asctime(); /* V7 way */
1460: struct tm *localtime();
1461: struct tm *tp;
1462:
1463: time(&clock);
1464: tp = localtime(&clock);
1465: *s = asctime(tp);
1466: #endif
1467: }
1468:
1469: /* C O N G M -- Get console terminal modes. */
1470:
1471: /*
1472: Saves current console mode, and establishes variables for switching between
1473: current (presumably normal) mode and other modes.
1474: */
1475:
1476: congm() {
1477: #ifndef UXIII
1478: gtty(0,&ccold); /* Structure for restoring */
1479: gtty(0,&cccbrk); /* For setting CBREAK mode */
1480: gtty(0,&ccraw); /* For setting RAW mode */
1481: #else
1482: ioctl(0,TCGETA,&ccold);
1483: ioctl(0,TCGETA,&cccbrk);
1484: ioctl(0,TCGETA,&ccraw);
1485: #endif
1486: cgmf = 1; /* Flag that we got them. */
1487: }
1488:
1489:
1490: /* C O N C B -- Put console in cbreak mode. */
1491:
1492: /* Returns 0 if ok, -1 if not */
1493:
1494: concb(esc) char esc; {
1495: int x;
1496: if (cgmf == 0) congm(); /* Get modes if necessary. */
1497: escchr = esc; /* Make this available to other fns */
1498: ckxech = 1; /* Program can echo characters */
1499: #ifndef UXIII
1500: cccbrk.sg_flags |= CBREAK; /* Set to character wakeup, */
1501: cccbrk.sg_flags &= ~ECHO; /* no echo. */
1502: x = stty(0,&cccbrk);
1503: #else
1504: cccbrk.c_lflag &= ~(ICANON|ECHO);
1505: cccbrk.c_cc[0] = 003; /* interrupt char is control-c */
1506: cccbrk.c_cc[1] = escchr; /* escape during packet modes */
1507: cccbrk.c_cc[4] = 1;
1508: cccbrk.c_cc[5] = 1;
1509: x = ioctl(0,TCSETAW,&cccbrk); /* set new modes . */
1510: #endif
1511: if (x > -1) setbuf(stdout,NULL); /* Make console unbuffered. */
1512: #ifdef V7
1513: if (kmem[CON] < 0) {
1514: qaddr[CON] = initrawq(0);
1515: if((kmem[CON] = open("/dev/kmem", 0)) < 0) {
1516: fprintf(stderr, "Can't read /dev/kmem in concb.\n");
1517: perror("/dev/kmem");
1518: exit(1);
1519: }
1520: }
1521: #endif V7
1522: return(x);
1523: }
1524:
1525: /* C O N B I N -- Put console in binary mode */
1526:
1527: /* Returns 0 if ok, -1 if not */
1528:
1529: conbin(esc) char esc; {
1530: if (cgmf == 0) congm(); /* Get modes if necessary. */
1531: escchr = esc; /* Make this available to other fns */
1532: ckxech = 1; /* Program can echo characters */
1533: #ifndef UXIII
1534: ccraw.sg_flags |= (RAW|TANDEM); /* Set rawmode, XON/XOFF */
1535: ccraw.sg_flags &= ~(ECHO|CRMOD); /* Set char wakeup, no echo */
1536: return(stty(0,&ccraw));
1537: #else
1538: ccraw.c_lflag &= ~(ISIG|ICANON|ECHO);
1539: ccraw.c_iflag |= (BRKINT|IGNPAR);
1540: ccraw.c_iflag &= ~(IGNBRK|INLCR|IGNCR|ICRNL|IUCLC|IXON|IXANY|IXOFF
1541: |INPCK|ISTRIP);
1542: ccraw.c_oflag &= ~OPOST;
1543:
1544: /*** Kermit used to put the console in 8-bit raw mode, but some users have
1545: *** pointed out that this should not be done, since some sites actually
1546: *** use terminals with parity settings on their Unix systems, and if we
1547: *** override the current settings and stop doing parity, then their terminals
1548: *** will display blotches for characters whose parity is wrong. Therefore,
1549: *** the following two lines are commented out (Larry Afrin, Clemson U):
1550: ***
1551: *** ccraw.c_cflag &= ~(PARENB|CSIZE);
1552: *** ccraw.c_cflag |= (CS8|CREAD);
1553: ***
1554: *** Sys III/V sites that have trouble with this can restore these lines.
1555: ***/
1556: ccraw.c_cc[4] = 1;
1557: ccraw.c_cc[5] = 1;
1558: return(ioctl(0,TCSETAW,&ccraw) ); /* set new modes . */
1559: #endif
1560: }
1561:
1562:
1563: /* C O N R E S -- Restore the console terminal */
1564:
1565: conres() {
1566: if (cgmf == 0) return(0); /* Don't do anything if modes */
1567: #ifndef UXIII /* except for sIII, */
1568: sleep(1); /* not known! */
1569: #endif /* (sIII does wait in ioctls) */
1570: ckxech = 0; /* System should echo chars */
1571: #ifndef UXIII
1572: return(stty(0,&ccold)); /* Restore controlling tty */
1573: #else
1574: return(ioctl(0,TCSETAW,&ccold));
1575: #endif
1576: }
1577:
1578: /* C O N O C -- Output a character to the console terminal */
1579:
1580: conoc(c) char c; {
1581: write(1,&c,1);
1582: }
1583:
1584: /* C O N X O -- Write x characters to the console terminal */
1585:
1586: conxo(x,s) char *s; int x; {
1587: write(1,s,x);
1588: }
1589:
1590: /* C O N O L -- Write a line to the console terminal */
1591:
1592: conol(s) char *s; {
1593: int len;
1594: len = strlen(s);
1595: write(1,s,len);
1596: }
1597:
1598: /* C O N O L A -- Write an array of lines to the console terminal */
1599:
1600: conola(s) char *s[]; {
1601: int i;
1602: for (i=0 ; *s[i] ; i++) conol(s[i]);
1603: }
1604:
1605: /* C O N O L L -- Output a string followed by CRLF */
1606:
1607: conoll(s) char *s; {
1608: conol(s);
1609: write(1,"\r\n",2);
1610: }
1611:
1612: /* C O N C H K -- Return how many characters available at console */
1613:
1614: conchk() {
1615: int x; long n;
1616:
1617: #ifdef PROVX1
1618: x = ioctl(0, TIOCQCNT, &ttbuf);
1619: n = ttbuf.sg_ispeed & 0377;
1620: return((x < 0) ? 0 : n);
1621: #else
1622: #ifdef V7
1623: lseek(kmem[CON], (long) qaddr[CON], 0);
1624: x = read(kmem[CON], &n, sizeof(int));
1625: return((x == sizeof(int))? n: 0);
1626: #else
1627: #ifdef UXIII
1628: if (conesc) { /* Escape typed */
1629: conesc = 0;
1630: signal(SIGQUIT,esctrp); /* Restore escape */
1631: return(1);
1632: }
1633: return(0);
1634: #else
1635: #ifdef C70
1636: if (conesc) { /* Escape typed */
1637: conesc = 0;
1638: signal(SIGQUIT,esctrp); /* Restore escape */
1639: return(1);
1640: }
1641: return(0);
1642: #else
1643: #ifdef FIONREAD
1644: x = ioctl(0, FIONREAD, &n); /* BSD and maybe some others */
1645: return((x < 0) ? 0 : n);
1646: #else
1647: return(0); /* Others can't do. */
1648: #endif
1649: #endif
1650: #endif
1651: #endif
1652: #endif
1653: }
1654:
1655: /* C O N I N C -- Get a character from the console */
1656:
1657: coninc(timo) int timo; {
1658: int n = 0; char ch;
1659: if (timo <= 0 ) { /* untimed */
1660: n = read(0, &ch, 1); /* Read a character. */
1661: ch &= 0377;
1662: if (n > 0) return(ch); /* Return the char if read */
1663: else
1664: #ifdef UXIII
1665: if (n < 0 && errno == EINTR) /* if read was interrupted by QUIT */
1666: return(escchr); /* user entered escape character */
1667: else /* couldnt be ^c, sigint never returns */
1668: #endif
1669: return(-1); /* Return the char, or -1. */
1670: }
1671: signal(SIGALRM,timerh); /* Timed read, so set up timer */
1672: alarm(timo);
1673: if (setjmp(sjbuf)) n = -2;
1674: else {
1675: n = read(0, &ch, 1);
1676: ch &= 0377;
1677: }
1678: alarm(0); /* Stop timing, we got our character */
1679: signal(SIGALRM,SIG_DFL);
1680: if (n > 0) return(ch);
1681: else
1682: #ifdef UXIII
1683: if (n == -1 && errno == EINTR) /* If read interrupted by QUIT, */
1684: return(escchr); /* user entered escape character, */
1685: else /* can't be ^c, sigint never returns */
1686: #endif
1687: return(-1);
1688: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.