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