|
|
1.1 root 1: char *ckxv = "Unix tty I/O, 4E(047), 27 Jan 88";
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, 1988, Trustees of Columbia University in the City of New
11: York. 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:
19: #include <sys/dir.h> /* Directory */
20: #include <ctype.h> /* Character types */
21: #ifdef NULL
22: #undef NULL
23: #endif /* NULL */
24: #include <stdio.h> /* Unix Standard i/o */
25: #include <signal.h> /* Interrupts */
26:
27: #ifndef ZILOG
28: #include <setjmp.h> /* Longjumps */
29: #else
30: #include <setret.h>
31: #endif
32:
33: #include "ckcdeb.h" /* Typedefs, formats for debug() */
34:
35: /* Maximum length for the name of a tty device */
36:
37: #ifndef DEVNAMLEN
38: #define DEVNAMLEN 25
39: #endif
40:
41: /* 4.1 BSD support added by Charles E. Brooks, EDN-VAX */
42: /* Fortune 32:16 Pro:For 1.8 support mostly like 4.1, added by J-P Dumas */
43:
44: #ifdef BSD4
45: #define ANYBSD
46: #ifdef MAXNAMLEN
47: #define BSD42
48: #ifdef aegis
49: char *ckxsys = " Apollo DOMAIN/IX 4.2 BSD";
50: #else
51: char *ckxsys = " 4.2 BSD";
52: #endif /* aegis */
53: #else
54: #ifdef FT18
55: #define BSD41
56: char *ckxsys = " Fortune For:Pro 1.8";
57: #else
58: #define BSD41
59: #ifndef C70
60: char *ckxsys = " 4.1 BSD";
61: #endif /* not c70 */
62: #endif /* ft18 */
63: #endif /* maxnamlen */
64: #endif /* bsd4 */
65:
66: /* 2.9bsd support contributed by Bradley Smith, UCLA */
67: #ifdef BSD29
68: #define ANYBSD
69: char *ckxsys = " 2.9 BSD";
70: #endif /* bsd29 */
71:
72: /*
73: Version 7 UNIX support contributed by Gregg Wonderly,
74: Oklahoma State University: [email protected]
75: */
76: #ifdef V7
77: char *ckxsys = " Version 7 UNIX (tm)";
78: #endif /* v7 */
79:
80: /*
81: Version 9 UNIX support contributed by Paul Glick,
82: AT&T Bell Laboratories: [email protected]
83: */
84: #ifdef V9
85: char *ckxsys = " Version 9 UNIX (tm)";
86: #endif /* v9 */
87:
88: /* BBN C70 support from Frank Wancho, WANCHO@SIMTEL20 */
89: #ifdef C70
90: char *ckxsys = " BBN C/70";
91: #endif /* c70 */
92:
93: /* IBM 370 IX/370 support from Wayne Van Pelt, GE/CRD, Schenectedy, NY */
94: #ifdef IX370
95: char *ckxsys = " IBM IX/370";
96: #endif /* ix370 */
97:
98: /* Amdahl UTS 2.4 (v7 derivative) for IBM 370 series compatible mainframes */
99: /* Contributed by Garard Gaye, Jean-Pierre Dumas, DUMAS@SUMEX-AIM. */
100: #ifdef UTS24
101: char *ckxsys = " Amdahl UTS 2.4";
102: #endif /* uts24 */
103:
104: /* Pro/Venix Version 1.x support from Columbia U. */
105: #ifdef PROVX1
106: char *ckxsys = " Pro-3xx Venix v1";
107: #endif /* provx1 */
108:
109: /* Tower support contributed by John Bray, Auburn, Alabama */
110: #ifdef TOWER1
111: char *ckxsys = " NCR Tower 1632, OS 1.02";
112: #endif /* tower1 */
113:
114: /* Sys III/V, Xenix, PC/IX support by Herm Fischer, Encino, CA */
115: #ifdef UXIII
116: #ifdef XENIX
117: char *ckxsys = " Xenix/286";
118: #else
119: #ifdef PCIX
120: char *ckxsys = " PC/IX";
121: #else
122: #ifdef ISIII
123: char *ckxsys = " Interactive Systems Corp System III";
124: #else
125: #ifdef hpux
126: /* HP 9000 Series changes contributed by Bill Coalson */
127: char *ckxsys = " HP 9000 Series HP-UX";
128: #else
129: #ifdef aegis
130: /* Apollo Aegis support from SAS Institute, Cary, NC */
131: char *ckxsys = " Apollo DOMAIN/IX System V";
132: #else
133: #ifdef ZILOG
134: char *ckxsys = " Zilog S8000 Zeus 3.21+";
135: #else
136: #ifdef VXVE
137: /* Control Data Corp VX/VE 5.2.1 System V support by */
138: /* S.O. Lidie, Lehigh University, [email protected] */
139: char *ckxsys = " CDC VX/VE 5.2.1 System V";
140: #else
141: char *ckxsys = " AT&T System III/System V";
142: #endif /* vxve */
143: #endif /* zilog */
144: #endif /* aegis */
145: #endif /* hpux */
146: #endif /* isiii */
147: #endif /* pcix */
148: #endif /* xenix */
149: #endif /* uxiii */
150:
151: /* Features... */
152:
153: /* Do own buffering, using unbuffered read() calls... */
154: #ifdef UXIII
155: #define MYREAD
156: #endif /* uxiii */
157:
158: #ifdef BSD42
159: #undef MYREAD
160: #include <errno.h>
161: #endif /* bsd42 */
162:
163: /*
164: Variables available to outside world:
165:
166: dftty -- Pointer to default tty name string, like "/dev/tty".
167: dfloc -- 0 if dftty is console, 1 if external line.
168: dfprty -- Default parity
169: dfflow -- Default flow control
170: ckxech -- Flag for who echoes console typein:
171: 1 - The program (system echo is turned off)
172: 0 - The system (or front end, or terminal).
173: functions that want to do their own echoing should check this flag
174: before doing so.
175:
176: flfnam -- Name of lock file, including its path, e.g.,
177: "/usr/spool/uucp/LCK..cul0" or "/etc/locks/tty77"
178: hasLock -- Flag set if this kermit established a uucp lock.
179: inbufc -- number of tty line rawmode unread characters
180: (system III/V unixes)
181: backgrd -- Flag indicating program executing in background ( & on
182: end of shell command). Used to ignore INT and QUIT signals.
183:
184: Functions for assigned communication line (either external or console tty):
185:
186: sysinit() -- System dependent program initialization
187: syscleanup() -- System dependent program shutdown
188: ttopen(ttname,local,mdmtyp) -- Open the named tty for exclusive access.
189: ttclos() -- Close & reset the tty, releasing any access lock.
190: ttpkt(speed,flow) -- Put the tty in packet mode and set the speed.
191: ttvt(speed,flow) -- Put the tty in virtual terminal mode.
192: or in DIALING or CONNECTED modem control state.
193: ttinl(dest,max,timo) -- Timed read line from the tty.
194: ttinc(timo) -- Timed read character from tty.
195: myread() -- System 3 raw mode bulk buffer read, gives
196: -- subsequent chars one at a time and simulates
197: -- FIONREAD!
198: myunrd(c) -- Places c back in buffer to be read (one only)
199: ttchk() -- See how many characters in tty input buffer.
200: ttxin(n,buf) -- Read n characters from tty (untimed).
201: ttol(string,length) -- Write a string to the tty.
202: ttoc(c) -- Write a character to the tty.
203: ttflui() -- Flush tty input buffer.
204:
205: ttlock(ttname) -- Lock against uucp collisions (Sys III)
206: ttunlck() -- Unlock " " "
207: look4lk(ttname) -- Check if a lock file exists
208: */
209:
210: /*
211: Functions for console terminal:
212:
213: congm() -- Get console terminal modes.
214: concb(esc) -- Put the console in single-character wakeup mode with no echo.
215: conbin(esc) -- Put the console in binary (raw) mode.
216: conres() -- Restore the console to mode obtained by congm().
217: conoc(c) -- Unbuffered output, one character to console.
218: conol(s) -- Unbuffered output, null-terminated string to the console.
219: conola(s) -- Unbuffered output, array of strings to the console.
220: conxo(n,s) -- Unbuffered output, n characters to the console.
221: conchk() -- Check if characters available at console (bsd 4.2).
222: Check if escape char (^\) typed at console (System III/V).
223: coninc(timo) -- Timed get a character from the console.
224: conint() -- Enable terminal interrupts on the console if not background.
225: connoi() -- Disable terminal interrupts on the console if not background.
226:
227: Time functions
228:
229: msleep(m) -- Millisecond sleep
230: ztime(&s) -- Return pointer to date/time string
231: rtimer() -- Reset timer
232: gtimer() -- Get elapsed time since last call to rtimer()
233: */
234:
235: /* Conditional Includes */
236:
237: #ifdef FT18
238: #include <sys/file.h> /* File information */
239: #endif /* ft18 */
240:
241: /* Whether to #include <sys/file.h>... */
242: #ifndef PROVX1
243: #ifndef aegis
244: #ifndef XENIX
245: #include <sys/file.h> /* File information */
246: #endif /* xenix */
247: #endif /* aegis */
248: #endif /* provx1 */
249:
250: #ifdef aegis
251: #ifdef BSD4
252: #include <sys/file.h>
253: #include <fcntl.h>
254: #endif /* bsd4 */
255: #endif /* aegis */
256:
257: /* System III, System V */
258:
259: #ifdef UXIII
260: #include <termio.h>
261: #include <sys/ioctl.h>
262: #include <fcntl.h> /* directory reading for locking */
263: #include <errno.h> /* error numbers for system returns */
264: #endif /* uxiii */
265:
266: #ifdef HPUX
267: #include <sys/modem.h>
268: #endif
269:
270: /* Not Sys III/V */
271:
272: #ifdef V9
273: #include <sys/filio.h>
274: #include <sys/ttyio.h>
275:
276: extern int tty_ld;
277: #endif
278: #ifndef UXIII
279: #ifndef V9
280: #include <sgtty.h> /* Set/Get tty modes */
281: #ifndef PROVX1
282: #ifndef V7
283: #ifndef BSD41
284: #include <sys/time.h> /* Clock info (for break generation) */
285: #endif /* not bsd41 */
286: #endif /* not v7 */
287: #endif /* not provx1 */
288: #endif /* not v9 */
289: #endif /* not uxiii */
290:
291: #ifdef BSD41
292: #include <sys/timeb.h> /* BSD 4.1 ... ceb */
293: #endif /* bsd41 */
294:
295: #ifdef BSD29
296: #include <sys/timeb.h> /* BSD 2.9 (Vic Abell, Purdue) */
297: #endif /* bsd29 */
298:
299: #ifdef TOWER1
300: #include <sys/timeb.h> /* Clock info for NCR Tower */
301: #endif /* tower1 */
302:
303: #ifdef aegis
304: #include "/sys/ins/base.ins.c"
305: #include "/sys/ins/error.ins.c"
306: #include "/sys/ins/ios.ins.c"
307: #include "/sys/ins/sio.ins.c"
308: #include "/sys/ins/pad.ins.c"
309: #include "/sys/ins/time.ins.c"
310: #include "/sys/ins/pfm.ins.c"
311: #include "/sys/ins/pgm.ins.c"
312: #include "/sys/ins/ec2.ins.c"
313: #include "/sys/ins/type_uids.ins.c"
314: #include <default_acl.h>
315: #undef TIOCEXCL
316: #undef FIONREAD
317: #endif
318:
319: /* The following two conditional #defines are catch-alls for those systems */
320: /* that didn't have or couldn't find <file.h>... */
321:
322: #ifndef FREAD
323: #define FREAD 0x01
324: #endif
325:
326: #ifndef FWRITE
327: #define FWRITE 0x10
328: #endif
329:
330: /* Declarations */
331:
332: long time(); /* All Unixes should have this... */
333: extern int errno; /* System call error code. */
334:
335: /* Special stuff for V7 input buffer peeking */
336:
337: #ifdef V7
338: int kmem[2] = { -1, -1};
339: char *initrawq(), *qaddr[2]={0,0};
340: #define CON 0
341: #define TTY 1
342: #endif /* v7 */
343:
344: /* dftty is the device name of the default device for file transfer */
345: /* dfloc is 0 if dftty is the user's console terminal, 1 if an external line */
346:
347: #ifdef PROVX1
348: char *dftty = "/dev/com1.dout"; /* Only example so far of a system */
349: int dfloc = 1; /* that goes in local mode by default */
350: #else
351: char *dftty = CTTNAM; /* Remote by default, use normal */
352: int dfloc = 0; /* controlling terminal name. */
353: #endif /* provx1 */
354:
355: int dfprty = 0; /* Default parity (0 = none) */
356: int ttprty = 0; /* Parity in use. */
357: int ttmdm = 0; /* Modem in use. */
358: int dfflow = 1; /* Xon/Xoff flow control */
359: int backgrd = 0; /* Assume in foreground (no '&' ) */
360:
361: int ckxech = 0; /* 0 if system normally echoes console characters, else 1 */
362:
363: /* Declarations of variables global within this module */
364:
365: static long tcount; /* Elapsed time counter */
366:
367: static char *brnuls = "\0\0\0\0\0\0\0"; /* A string of nulls */
368:
369: static jmp_buf sjbuf, jjbuf; /* Longjump buffer */
370: static int lkf = 0, /* Line lock flag */
371: conif = 0, /* Console interrupts on/off flag */
372: cgmf = 0, /* Flag that console modes saved */
373: xlocal = 0, /* Flag for tty local or remote */
374: ttyfd = -1; /* TTY file descriptor */
375: static char escchr; /* Escape or attn character */
376:
377: #ifdef BSD42
378: static struct timeval tv; /* For getting time, from sys/time.h */
379: static struct timezone tz;
380: #endif /* bsd42 */
381:
382: #ifdef BSD29
383: static long clock; /* For getting time from sys/time.h */
384: static struct timeb ftp; /* And from sys/timeb.h */
385: #endif /* bsd29 */
386:
387: #ifdef BSD41
388: static long clock; /* For getting time from sys/time.h */
389: static struct timeb ftp; /* And from sys/timeb.h */
390: #endif /* bsd41 */
391:
392: #ifdef TOWER1
393: static long clock; /* For getting time from sys/time.h */
394: static struct timeb ftp; /* And from sys/timeb.h */
395: #endif /* tower1 */
396:
397: #ifdef V7
398: static long clock;
399: #endif /* v7 */
400:
401: #ifdef V9
402: static long clock;
403: #endif
404:
405: /* sgtty/termio information... */
406:
407: #ifdef UXIII
408: static struct termio ttold = {0}; /* Init'd for word alignment, */
409: static struct termio ttraw = {0}; /* which is important for some */
410: static struct termio tttvt = {0}; /* systems, like Zilog... */
411: static struct termio ccold = {0};
412: static struct termio ccraw = {0};
413: static struct termio cccbrk = {0};
414: #else
415: static struct sgttyb /* sgtty info... */
416: ttold, ttraw, tttvt, ttbuf, /* for communication line */
417: ccold, ccraw, cccbrk; /* and for console */
418: #endif /* uxiii */
419:
420: static char flfnam[80]; /* uucp lock file path name */
421: static int hasLock = 0; /* =1 if this kermit locked uucp */
422: static int inbufc = 0; /* stuff for efficient SIII raw line */
423: static int ungotn = -1; /* pushback to unread character */
424: static int conesc = 0; /* set to 1 if esc char (^\) typed */
425:
426: static int ttlock(); /* definition of ttlock subprocedure */
427: static int ttunlck(); /* and unlock subprocedure */
428: static char ttnmsv[DEVNAMLEN]; /* copy of open path for tthang */
429:
430: #ifdef aegis
431: static status_$t st; /* error status return value */
432: static short concrp = 0; /* true if console is CRP pad */
433: #define CONBUFSIZ 10
434: static char conbuf[CONBUFSIZ]; /* console readahead buffer */
435: static int conbufn = 0; /* # chars in readahead buffer */
436: static char *conbufp; /* next char in readahead buffer */
437: static uid_$t ttyuid; /* tty type uid */
438: static uid_$t conuid; /* stdout type uid */
439:
440: /* APOLLO Aegis main()
441: * establish acl usage and cleanup handling
442: * this makes sure that CRP pads
443: * get restored to a usable mode
444: */
445: main(argc,argv) int argc; char **argv; {
446: status_$t status;
447: pfm_$cleanup_rec dirty;
448:
449: int pid = getpid();
450:
451: /* acl usage according to invoking environment */
452: default_acl(USE_DEFENV);
453:
454: /* establish a cleanup continuation */
455: status = pfm_$cleanup(dirty);
456: if (status.all != pfm_$cleanup_set)
457: {
458: /* only handle faults for the original process */
459: if (pid == getpid() && status.all > pgm_$max_severity)
460: { /* blew up in main process */
461: status_$t quo;
462: pfm_$cleanup_rec clean;
463:
464: /* restore the console in any case */
465: conres();
466:
467: /* attempt a clean exit */
468: debug(F101, "cleanup fault status", "", status.all);
469:
470: /* doexit(), then send status to continuation */
471: quo = pfm_$cleanup(clean);
472: if (quo.all == pfm_$cleanup_set)
473: doexit(pgm_$program_faulted);
474: else if (quo.all > pgm_$max_severity)
475: pfm_$signal(quo); /* blew up in doexit() */
476: }
477: /* send to the original continuation */
478: pfm_$signal(status);
479: /*NOTREACHED*/
480: }
481: return(ckcmai(argc, argv));
482: }
483: #endif /* aegis */
484:
485: /* S Y S I N I T -- System-dependent program initialization. */
486:
487: sysinit() {
488:
489: /* for now, nothing... */
490: return(0);
491: }
492:
493: /* S Y S C L E A N U P -- System-dependent program cleanup. */
494:
495: syscleanup() {
496:
497: /* for now, nothing... */
498: return(0);
499: }
500:
501: /* T T O P E N -- Open a tty for exclusive access. */
502:
503: /* Returns 0 on success, -1 on failure. */
504: /*
505: If called with lcl < 0, sets value of lcl as follows:
506: 0: the terminal named by ttname is the job's controlling terminal.
507: 1: the terminal named by ttname is not the job's controlling terminal.
508: But watch out: if a line is already open, or if requested line can't
509: be opened, then lcl remains (and is returned as) -1.
510: */
511: ttopen(ttname,lcl,modem) char *ttname; int *lcl, modem; {
512:
513: #ifdef UXIII
514: #ifndef CIE
515: char *ctermid(); /* Wish they all had this! */
516: #endif /* not cie */
517: #endif /* uxiii */
518:
519: #ifdef CIE /* CIE Regulus doesn't... */
520: #define ctermid(x) strcpy(x,"")
521: #endif
522:
523: char *x; extern char* ttyname();
524: char cname[DEVNAMLEN+4];
525:
526: if (ttyfd > -1) return(0); /* If already open, ignore this call */
527: ttmdm = modem; /* Make this available to other fns */
528: xlocal = *lcl; /* Make this available to other fns */
529: #ifdef NEWUUCP
530: acucntrl("disable",ttname); /* Open getty on line (4.3BSD) */
531: #endif /* newuucp */
532: #ifdef UXIII
533: /* if modem connection, don't wait for carrier */
534: ttyfd = open(ttname,O_RDWR | (modem ? O_NDELAY : 0) );
535: #else
536: #ifdef V9
537: if (strncmp(ttname, "/cs", 3) == 0) {
538: if ((ttyfd = ipcopen(ttname, "")) >= 0)
539: if ( ioctl(ttyfd, FIOPUSHLD, &tty_ld) == -1 )
540: fprintf(stderr, "ioctl error - FIOPUSHLD\n");
541: } else
542: #endif /* V9 */
543: ttyfd = open(ttname,2); /* Try to open for read/write */
544: #endif /* uxiii */
545:
546: if (ttyfd < 0) { /* If couldn't open, fail. */
547: perror(ttname);
548: return(-1);
549: }
550: #ifdef aegis
551: /* Apollo C runtime claims that console pads are tty devices, which
552: * is reasonable, but they aren't any good for packet transfer. */
553: ios_$inq_type_uid((short)ttyfd, ttyuid, st);
554: if (st.all != status_$ok) {
555: fprintf(stderr, "problem getting tty object type: ");
556: error_$print(st);
557: } else if (ttyuid != sio_$uid) { /* reject non-SIO lines */
558: close(ttyfd); ttyfd = -1;
559: errno = ENOTTY; perror(ttname);
560: return(-1);
561: }
562: #endif /* aegis */
563: strncpy(ttnmsv,ttname,DEVNAMLEN); /* Open, keep copy of name locally. */
564:
565: /* Caller wants us to figure out if line is controlling tty */
566:
567: debug(F111,"ttopen ok",ttname,*lcl);
568: if (*lcl == -1) {
569: if (strcmp(ttname,CTTNAM) == 0) { /* "/dev/tty" always remote */
570: debug(F110," Same as CTTNAM",ttname,0);
571: xlocal = 0;
572: } else if (isatty(0)) { /* Else, if stdin not redirected */
573: x = ttyname(0); /* then compare its device name */
574: strncpy(cname,x,DEVNAMLEN); /* (copy from internal static buf) */
575: debug(F110," ttyname(0)",x,0);
576: x = ttyname(ttyfd); /* ...with real name of ttname. */
577: xlocal = (strncmp(x,cname,DEVNAMLEN) == 0) ? 0 : 1;
578: debug(F111," ttyname",x,xlocal);
579: } else { /* Else, if stdin redirected... */
580: #ifdef UXIII
581: /* Sys III/V provides nice ctermid() function to get name of controlling tty */
582: ctermid(cname); /* Get name of controlling terminal */
583: debug(F110," ctermid",cname,0);
584: x = ttyname(ttyfd); /* Compare with name of comm line. */
585: xlocal = (strncmp(x,cname,DEVNAMLEN) == 0) ? 0 : 1;
586: debug(F111," ttyname",x,xlocal);
587: #else
588: /* Just assume local, so "set speed" and similar commands will work */
589: /* If not really local, how could it work anyway?... */
590: xlocal = 1;
591: debug(F101," redirected stdin","",xlocal);
592: #endif /* uxiii */
593: }
594: }
595:
596: /* Now check if line is locked -- if so fail, else lock for ourselves */
597:
598: lkf = 0; /* Check lock */
599: if (xlocal > 0) {
600: if (ttlock(ttname) < 0) {
601: fprintf(stderr,"Exclusive access to %s denied\n",ttname);
602: close(ttyfd); ttyfd = -1;
603: debug(F110," Access denied by lock",ttname,0);
604: return(-1); /* Not if already locked */
605: } else lkf = 1;
606: }
607:
608: /* Got the line, now set the desired value for local. */
609:
610: if (*lcl < 0) *lcl = xlocal;
611:
612: /* Some special stuff for v7... */
613:
614: #ifdef V7
615: if (kmem[TTY] < 0) { /* If open, then skip this. */
616: qaddr[TTY] = initrawq(ttyfd); /* Init the queue. */
617: if ((kmem[TTY] = open("/dev/kmem", 0)) < 0) {
618: fprintf(stderr, "Can't read /dev/kmem in ttopen.\n");
619: perror("/dev/kmem");
620: exit(1);
621: }
622: }
623: #endif /* v7 */
624:
625: /* Request exclusive access on systems that allow it. */
626:
627: #ifndef XENIX
628: /* Xenix exclusive access prevents open(close(...)) from working... */
629: #ifdef TIOCEXCL
630: if (ioctl(ttyfd,TIOCEXCL, NULL) < 0)
631: fprintf(stderr,"Warning, problem getting exclusive access\n");
632: #endif /* tiocexcl */
633: #endif /* xenix */
634:
635: /* Get tty device settings */
636:
637: #ifndef UXIII
638: #ifdef V9
639: ioctl(ttyfd,TIOCGETP,&ttold); /* Same deal for Sys III, Sys V */
640: ioctl(ttyfd,TIOCGETP,&ttraw);
641: ioctl(ttyfd,TIOCGETP,&tttvt);
642: #else
643: gtty(ttyfd,&ttold); /* Get sgtty info */
644: #ifdef aegis
645: sio_$control((short)ttyfd, sio_$raw_nl, false, st);
646: if (xlocal) { /* ignore breaks from local line */
647: sio_$control((short)ttyfd, sio_$int_enable, false, st);
648: sio_$control((short)ttyfd, sio_$quit_enable, false, st);
649: }
650: #endif /* aegis */
651: gtty(ttyfd,&ttraw); /* And a copy of it for packets*/
652: gtty(ttyfd,&tttvt); /* And one for virtual tty service */
653: #endif /* v9 */
654: #else
655: ioctl(ttyfd,TCGETA,&ttold); /* Same deal for Sys III, Sys V */
656: #ifdef aegis
657: sio_$control((short)ttyfd, sio_$raw_nl, false, st);
658: if (xlocal) { /* ignore breaks from local line */
659: sio_$control((short)ttyfd, sio_$int_enable, false, st);
660: sio_$control((short)ttyfd, sio_$quit_enable, false, st);
661: }
662: #endif /* aegis */
663: ioctl(ttyfd,TCGETA,&ttraw);
664: ioctl(ttyfd,TCGETA,&tttvt);
665: #endif /* not uxiii */
666:
667: #ifdef VXVE
668: ttraw.c_line = 0; /* STTY line 0 for VX/VE */
669: ioctl(ttyfd,TCSETA,&ttraw);
670: tttvt.c_line = 0; /* STTY line 0 for VX/VE */
671: ioctl(ttyfd,TCSETA,&tttvt);
672: #endif /* vxve */
673:
674: debug(F101,"ttopen, ttyfd","",ttyfd);
675: debug(F101," lcl","",*lcl);
676: debug(F111," lock file",flfnam,lkf);
677: return(0);
678: }
679:
680: /* T T C L O S -- Close the TTY, releasing any lock. */
681:
682: ttclos() {
683: if (ttyfd < 0) return(0); /* Wasn't open. */
684: if (xlocal) {
685: if (tthang()) /* Hang up phone line */
686: fprintf(stderr,"Warning, problem hanging up the phone\n");
687: if (ttunlck()) /* Release uucp-style lock */
688: fprintf(stderr,"Warning, problem releasing lock\n");
689: }
690: ttres(); /* Reset modes. */
691: /* Relinquish exclusive access if we might have had it... */
692: #ifndef XENIX
693: #ifdef TIOCEXCL
694: #ifdef TIOCNXCL
695: if (ioctl(ttyfd, TIOCNXCL, NULL) < 0)
696: fprintf(stderr,"Warning, problem relinquishing exclusive access\n");
697: #endif /* tiocnxcl */
698: #endif /* tiocexcl */
699: #endif /* not xenix */
700: close(ttyfd); /* Close it. */
701: #ifdef NEWUUCP
702: acucntrl("enable",flfnam); /* Close getty on line. */
703: #endif /* newuucp */
704: ttyfd = -1; /* Mark it as closed. */
705: return(0);
706: }
707:
708: /* T T H A N G -- Hangup phone line */
709:
710: tthang() {
711: #ifdef UXIII
712: #ifdef HPUX
713: unsigned long dtr_down = 00000000000,
714: modem_rtn;
715: #else
716: unsigned short ttc_save;
717: #endif /* hpux */
718: #endif /* uxiii */
719:
720: if (ttyfd < 0) return(0); /* Not open. */
721: #ifdef aegis
722: sio_$control((short)ttyfd, sio_$dtr, false, st); /* DTR down */
723: msleep(500); /* pause */
724: sio_$control((short)ttyfd, sio_$dtr, true, st); /* DTR up */
725: #else
726: #ifdef ANYBSD
727: ioctl(ttyfd,TIOCCDTR,0); /* Clear DTR */
728: msleep(500); /* Let things settle */
729: ioctl(ttyfd,TIOCSDTR,0); /* Restore DTR */
730: #endif /* anybsd */
731: #ifdef UXIII
732: #ifdef HPUX /* Hewlett Packard way of modem control */
733: if (ioctl(ttyfd,MCSETAF,&dtr_down) < 0) return(-1); /* lower DTR */
734: msleep(500);
735: if (ioctl(ttyfd,MCGETA,&modem_rtn) < 0) return(-1); /* get line status */
736: if ((modem_rtn & MDCD) != 0) return(-1); /* check if DCD is low */
737: modem_rtn = MRTS | MDTR; /* bits for RTS & DTR */
738: if (ioctl(ttyfd,MCSETAF,&modem_rtn) < 0) return(-1); /* set lines */
739: #else
740: ttc_save = ttraw.c_cflag;
741: ttraw.c_cflag &= ~CBAUD; /* swa: set baud rate to 0 to hangup */
742: if (ioctl(ttyfd,TCSETAF,&ttraw) < 0) return(-1); /* do it */
743: msleep(100); /* let things settle */
744: ttraw.c_cflag = ttc_save;
745:
746: /* NOTE - The following #ifndef...#endif can be removed for SCO Xenix 2.1.3 */
747: /* or later, but must keep for earlier versions, which can't do close/open. */
748:
749: #ifndef XENIX /* xenix cannot do close/open when carrier drops */
750: /* following corrects a PC/IX defficiency */
751: ttc_save = fcntl(ttyfd,F_GETFL,0);
752: close(ttyfd); /* close/reopen file descriptor */
753: if ((ttyfd = open(ttnmsv, ttc_save)) < 0) return(-1);
754: #endif /* not xenix */
755: if (ioctl(ttyfd,TCSETAF,&ttraw) < 0) return(-1); /* un-do it */
756: #endif /* uxiii */
757: #endif /* hpux */
758: #endif /* aegis */
759: return (0);
760: }
761:
762:
763: /* T T R E S -- Restore terminal to "normal" mode. */
764:
765: ttres() { /* Restore the tty to normal. */
766: int x;
767:
768: if (ttyfd < 0) return(-1); /* Not open. */
769: #ifndef UXIII /* except for sIII, */
770: sleep(1); /* Wait for pending i/o to finish. */
771: #endif /* uxiii */ /* (sIII does wait in ioctls) */
772:
773: #ifdef UXIII
774: if (ioctl(ttyfd,TCSETAW,&ttold) < 0) return(-1); /* restore termio stuff */
775: if (fcntl(ttyfd,F_SETFL, fcntl(ttyfd, F_GETFL, 0) & ~O_NDELAY) < 0 )
776: return(-1);
777: #else /* not uxiii */
778: #ifdef V9
779: if (ioctl(ttyfd, TIOCSETP, &ttold) < 0) return(-1); /* Restore sgttyb stuff */
780: #else
781: #ifdef FIONBIO
782: x = 0;
783: x = ioctl(ttyfd,FIONBIO,&x);
784: if (x < 0) {
785: perror("ttres ioctl");
786: debug(F101,"ttres ioctl","",x);
787: }
788: #else /* not fionbio */
789: #ifdef FNDELAY
790: x = (fcntl(ttyfd,F_SETFL,fcntl(ttyfd,F_GETFL,0) & ~FNDELAY) == -1);
791: debug(F101,"ttres fcntl","",x);
792: if (x < 0) perror("fcntl");
793: #endif /* fndelay */
794: #endif /* fionbio */
795: x = stty(ttyfd,&ttold); /* Restore sgtty stuff */
796: debug(F101,"ttres stty","",x);
797: if (x < 0) perror("stty");
798: #endif /* v9 */
799: #endif /* uxiii */
800: return(x);
801: }
802:
803: /* Exclusive uucp file locking control */
804: /*
805: by H. Fischer, creative non-Bell coding !
806: copyright rights for lock modules assigned to Columbia University
807: */
808: static char *
809: xxlast(s,c) char *s; char c; { /* Equivalent to strrchr() */
810: int i;
811: for (i = strlen(s); i > 0; i--)
812: if ( s[i-1] == c ) return( s + (i - 1) );
813: return(NULL);
814: }
815: static
816: look4lk(ttname) char *ttname; {
817: extern char *strcat(), *strcpy();
818: char *device, *devname;
819: char lockfil[50]; /* Max length for lock file name */
820:
821: #ifdef ISIII
822: char *lockdir = "/etc/locks";
823: #else
824: #ifdef ATT3BX
825: char *lockdir = "/usr/spool/locks";
826: #else
827: #ifdef NEWUUCP
828: char *lockdir = "/usr/spool/uucp/LCK";
829: #else
830: char *lockdir = "/usr/spool/uucp";
831: #endif /* newuucp */
832: #endif /* att3bx */
833: #endif /* isiii */
834:
835: device = ( (devname=xxlast(ttname,'/')) != NULL ? devname+1 : ttname);
836:
837: #ifdef ISIII
838: (void) strcpy( lockfil, device );
839: #else
840: strcat( strcpy( lockfil, "LCK.." ), device );
841: #endif /* isiii */
842:
843: if (access( lockdir, 04 ) < 0) { /* read access denied on lock dir */
844: fprintf(stderr,"Warning, read access to lock directory denied\n");
845: return( 1 ); /* cannot check or set lock file */
846: }
847:
848: strcat(strcat(strcpy(flfnam,lockdir),"/"), lockfil);
849: debug(F110,"look4lk",flfnam,0);
850:
851: if ( ! access( flfnam, 00 ) ) { /* print out lock file entry */
852: char lckcmd[40] ;
853: strcat( strcpy(lckcmd, "ls -l ") , flfnam);
854: system(lckcmd);
855: if (access(flfnam,02) == 0)
856: printf("(You may type \"! rm %s\" to remove this file)\n",flfnam);
857: return( -1 );
858: }
859: if ( access( lockdir, 02 ) < 0 ) { /* lock file cannot be written */
860: fprintf(stderr,"Warning, write access to lock directory denied\n");
861: return( 1 );
862: }
863: return( 0 ); /* okay to go ahead and lock */
864: }
865:
866: /* T T L O C K */
867:
868: static
869: ttlock(ttfd) char *ttfd; { /* lock uucp if possible */
870: #ifndef aegis
871: #ifdef ATT3BX
872: FILE *lck_fild;
873: #endif /* att3bx */
874: int lck_fil, l4l;
875: int pid_buf = getpid(); /* pid to save in lock file */
876:
877: hasLock = 0; /* not locked yet */
878: l4l = look4lk(ttfd);
879: if (l4l < 0) return (-1); /* already locked */
880: if (l4l == 1) return (0); /* can't read/write lock directory */
881: lck_fil = creat(flfnam, 0444); /* create lock file ... */
882: if (lck_fil < 0) return (-1); /* create of lockfile failed */
883: /* creat leaves file handle open for writing -- hf */
884: #ifdef ATT3BX
885: fprintf((lck_fild = fdopen(lck_fil, "w")), "%10d\n", pid_buf);
886: fflush(lck_fild);
887: #else
888: write (lck_fil, &pid_buf, sizeof(pid_buf) ); /* uucp expects int in file */
889: #endif /* att3bx */
890: close (lck_fil);
891: hasLock = 1; /* now is locked */
892: #endif /* not aegis */
893: return(0);
894: }
895:
896: /* T T U N L O C K */
897:
898: static
899: ttunlck() { /* kill uucp lock if possible */
900: if (hasLock) return( unlink( flfnam ) );
901: return(0);
902: }
903:
904: /* New-style (4.3BSD) UUCP line direction control (Stan Barber, Rice U) */
905:
906: #ifdef NEWUUCP
907: acucntrl(flag,ttname) char *flag, *ttname; {
908: char x[DEVNAMLEN+32], *device, *devname;
909:
910: if (strcmp(ttname,CTTNAM) == 0 || xlocal == 0) /* If not local, */
911: return; /* just return. */
912: device = ((devname = xxlast(ttname,'/')) != NULL ? devname+1 : ttname);
913: if (strncmp(device,"LCK..",4) == 0) device += 5;
914: sprintf(x,"/usr/lib/uucp/acucntrl %s %s",flag,device);
915: debug(F000,"called ",x,0);
916: system(x);
917: }
918: #endif /* newuucp */
919:
920: /* T T P K T -- Condition the communication line for packets. */
921: /* or for modem dialing */
922:
923: #define DIALING 4 /* flags (via flow) for modem handling */
924: #define CONNECT 5
925:
926: /* If called with speed > -1, also set the speed. */
927:
928: /* Returns 0 on success, -1 on failure. */
929:
930: ttpkt(speed,flow,parity) int speed, flow, parity; {
931: int s, x;
932:
933: if (ttyfd < 0) return(-1); /* Not open. */
934: ttprty = parity; /* Let other tt functions see this. */
935: debug(F101,"ttpkt setting ttprty","",ttprty);
936: s = ttsspd(speed); /* Check the speed */
937:
938: #ifndef UXIII
939: if (flow == 1) ttraw.sg_flags |= TANDEM; /* Use XON/XOFF if selected */
940: if (flow == 0) ttraw.sg_flags &= ~TANDEM;
941: ttraw.sg_flags |= RAW; /* Go into raw mode */
942: ttraw.sg_flags &= ~(ECHO|CRMOD); /* Use CR for break character */
943: #ifdef TOWER1
944: ttraw.sg_flags &= ~ANYP; /* Must tell Tower no parity */
945: #endif /* tower1 */
946: if (s > -1) ttraw.sg_ispeed = ttraw.sg_ospeed = s; /* Do the speed */
947: #ifdef V9
948: if (ioctl(ttyfd,TIOCSETP,&ttraw) < 0) return(-1); /* Set the new modes. */
949: #else
950: if (stty(ttyfd,&ttraw) < 0) return(-1); /* Set the new modes. */
951: #endif /* v9 */
952:
953: #ifdef MYREAD
954: #ifdef BSD4
955: /* Try to make reads nonblocking */
956: #ifdef aegis
957: return(0);
958: #endif /* aegis */
959: #ifdef FIONBIO
960: x = 1;
961: if (ioctl(ttyfd,FIONBIO,&x) < 0) {
962: perror("ttpkt ioctl");
963: return(-1);
964: }
965: #else /* fionbio */
966: #ifdef FNDELAY
967: if (fcntl(ttyfd,F_SETFL,fcntl(ttyfd,F_GETFL,0) | FNDELAY) == -1) {
968: return(-1);
969: }
970: #endif /* fndelay */
971: #endif /* bsd4 */
972: ttflui(); /* Flush any pending input */
973: return(0);
974: #endif /* bsd4 */
975: #else /* myread */
976: ttflui(); /* Flush any pending input */
977: return(0);
978: #endif /* myread */
979: #endif /* not uxiii */
980:
981: #ifdef UXIII
982: if (flow == 1) ttraw.c_iflag |= (IXON|IXOFF);
983: if (flow == 0) ttraw.c_iflag &= ~(IXON|IXOFF);
984:
985: if (flow == DIALING) ttraw.c_cflag |= CLOCAL|HUPCL;
986: if (flow == CONNECT) ttraw.c_cflag &= ~CLOCAL;
987:
988: ttraw.c_lflag &= ~(ICANON|ECHO);
989: ttraw.c_lflag |= ISIG; /* do check for interrupt */
990: ttraw.c_iflag |= (BRKINT|IGNPAR);
991: ttraw.c_iflag &= ~(IGNBRK|INLCR|IGNCR|ICRNL|IUCLC|INPCK|ISTRIP|IXANY);
992: ttraw.c_oflag &= ~OPOST;
993: ttraw.c_cflag &= ~(CSIZE|PARENB);
994: ttraw.c_cflag |= (CS8|CREAD);
995: #ifdef IX370
996: ttraw.c_cc[4] = 48; /* So Series/1 doesn't interrupt on every char */
997: ttraw.c_cc[5] = 1;
998: #else
999: #ifdef VXVE
1000: ttraw.c_cc[4] = 1; /* [VMIN] for CDC VX/VE */
1001: ttraw.c_cc[5] = 0; /* [VTIME] for CDC VX/VE */
1002: #else
1003: #ifdef MYREAD
1004: ttraw.c_cc[4] = 200; /* return max of this many characters */
1005: ttraw.c_cc[5] = 1; /* or when this many secs/10 expire w/no input */
1006: #else
1007: ttraw.c_cc[4] = 1; /* [VMIN] Maybe should be bigger for all Sys V? */
1008: ttraw.c_cc[5] = 0; /* [VTIME] Should be set high enough to ignore */
1009: /* intercharacter spacing? */
1010: /* But then we have to distinguish between Sys III and Sys V.. */
1011: #endif
1012: #endif
1013: #endif
1014: if (s > -1) { /* set speed */
1015: ttraw.c_cflag &= ~CBAUD;
1016: ttraw.c_cflag |= s;
1017: }
1018: if (ioctl(ttyfd,TCSETAW,&ttraw) < 0) return(-1); /* set new modes . */
1019: if (flow == DIALING) {
1020: #ifndef aegis
1021: if (fcntl(ttyfd,F_SETFL, fcntl(ttyfd, F_GETFL, 0) & ~O_NDELAY) < 0 )
1022: return(-1);
1023: #endif /* not aegis */
1024: close( open(ttnmsv,2) ); /* magic to force mode change!!! */
1025: }
1026: ttflui();
1027: return(0);
1028: #endif /* uxiii */
1029: }
1030:
1031: /* T T V T -- Condition communication line for use as virtual terminal */
1032:
1033: ttvt(speed,flow) int speed, flow; {
1034: int s;
1035: if (ttyfd < 0) return(-1); /* Not open. */
1036:
1037: s = ttsspd(speed); /* Check the speed */
1038:
1039: #ifndef UXIII
1040: if (flow == 1) tttvt.sg_flags |= TANDEM; /* XON/XOFF if selected */
1041: if (flow == 0) tttvt.sg_flags &= ~TANDEM;
1042: tttvt.sg_flags |= RAW; /* Raw mode */
1043: #ifdef TOWER1
1044: tttvt.sg_flags &= ~(ECHO|ANYP); /* No echo or system III ??? parity */
1045: #else
1046: tttvt.sg_flags &= ~ECHO; /* No echo */
1047: #endif
1048: if (s > -1) tttvt.sg_ispeed = tttvt.sg_ospeed = s; /* Do the speed */
1049: #ifdef V9
1050: if (ioctl(ttyfd,TIOCSETP,&tttvt) < 0) return(-1);
1051: #else
1052: if (stty(ttyfd,&tttvt) < 0) return(-1);
1053: #endif
1054:
1055: #ifdef MYREAD
1056: #ifdef BSD4
1057: /* Make reads nonblocking */
1058: #ifdef aegis
1059: return(0);
1060: #endif
1061: if (fcntl(ttyfd,F_SETFL,fcntl(ttyfd,F_GETFL,0) | FNDELAY) == -1)
1062: return(-1);
1063: else return(0);
1064: #endif /* bsd4 */
1065: #endif /* myread */
1066:
1067: #else /* uxiii */
1068: if (flow == 1) tttvt.c_iflag |= (IXON|IXOFF);
1069: if (flow == 0) tttvt.c_iflag &= ~(IXON|IXOFF);
1070:
1071: if (flow == DIALING) tttvt.c_cflag |= CLOCAL|HUPCL;
1072: if (flow == CONNECT) tttvt.c_cflag &= ~CLOCAL;
1073:
1074: tttvt.c_lflag &= ~(ISIG|ICANON|ECHO);
1075: tttvt.c_iflag |= (IGNBRK|IGNPAR);
1076: tttvt.c_iflag &= ~(INLCR|IGNCR|ICRNL|IUCLC|BRKINT|INPCK|ISTRIP|IXANY);
1077: tttvt.c_oflag &= ~OPOST;
1078: tttvt.c_cflag &= ~(CSIZE|PARENB);
1079: tttvt.c_cflag |= (CS8|CREAD);
1080: tttvt.c_cc[4] = 1;
1081: tttvt.c_cc[5] = 0;
1082:
1083: if (s > -1) { /* set speed */
1084: tttvt.c_cflag &= ~CBAUD;
1085: tttvt.c_cflag |= s;
1086: }
1087: if (ioctl(ttyfd,TCSETAW,&tttvt) < 0) return(-1); /* set new modes . */
1088:
1089: if (flow == DIALING) {
1090: #ifndef aegis
1091: if (fcntl(ttyfd,F_SETFL, fcntl(ttyfd, F_GETFL, 0) & ~O_NDELAY) < 0 )
1092: return(-1);
1093: #endif
1094: close( open(ttnmsv,2) ); /* magic to force mode change!!! */
1095: }
1096: #endif
1097: return(0);
1098: }
1099:
1100: /* T T S S P D -- Return the internal baud rate code for 'speed'. */
1101:
1102: ttsspd(speed) {
1103: int s, spdok;
1104:
1105: if (speed < 0) return(-1);
1106: spdok = 1; /* Assume arg ok */
1107: switch (speed) {
1108: case 0: s = B0; break; /* Just the common ones. */
1109: case 110: s = B110; break; /* The others from ttydev.h */
1110: case 150: s = B150; break; /* could also be included if */
1111: case 300: s = B300; break; /* necessary... */
1112: case 600: s = B600; break;
1113: case 1200: s = B1200; break;
1114: case 1800: s = B1800; break;
1115: case 2400: s = B2400; break;
1116: case 4800: s = B4800; break;
1117: case 9600: s = B9600; break;
1118: #ifdef PLEXUS
1119: case 19200: s = EXTA; break;
1120: #endif
1121: #ifdef aegis
1122: case 19200: s = EXTA; break;
1123: #endif
1124: default:
1125: spdok = 0;
1126: fprintf(stderr,"Unsupported line speed - %d\n",speed);
1127: fprintf(stderr,"Current speed not changed\n");
1128: break;
1129: }
1130: if (spdok) return(s); else return(-1);
1131: }
1132:
1133: /* T T F L U I -- Flush tty input buffer */
1134:
1135: ttflui() {
1136:
1137: #ifndef UXIII
1138: long n;
1139: #endif
1140: if (ttyfd < 0) return(-1); /* Not open. */
1141:
1142: ungotn = -1; /* Initialize myread() stuff */
1143: inbufc = 0;
1144:
1145: #ifdef aegis
1146: sio_$control((short)ttyfd, sio_$flush_in, true, st);
1147: if (st.all != status_$ok)
1148: { fprintf(stderr, "flush failed: "); error_$print(st); }
1149: else { /* sometimes the flush doesn't work */
1150: for (;;)
1151: { char buf[256];
1152: /* eat all the characters that shouldn't be available */
1153: (void)ios_$get((short)ttyfd, ios_$cond_opt, buf, 256L, st);
1154: if (st.all == ios_$get_conditional_failed) break;
1155: fprintf(stderr, "flush failed(2): "); error_$print(st);
1156: }
1157: }
1158: #else
1159: #ifdef UXIII
1160: #ifndef VXVE
1161: if (ioctl(ttyfd,TCFLSH,0) < 0) perror("flush failed");
1162: #endif /* vxve */
1163: #else
1164: #ifdef TIOCFLUSH
1165: #ifdef ANYBSD
1166: n = FREAD; /* Specify read queue */
1167: if (ioctl(ttyfd,TIOCFLUSH,&n) < 0) perror("flush failed");
1168: #else
1169: if (ioctl(ttyfd,TIOCFLUSH,0) < 0) perror("flush failed");
1170: #endif
1171: #endif
1172: #endif
1173: #endif
1174: return(0);
1175: }
1176:
1177: /* Interrupt Functions */
1178:
1179:
1180: /* Timeout handler for communication line input functions */
1181:
1182: timerh() {
1183: longjmp(sjbuf,1);
1184: }
1185:
1186:
1187: /* Set up terminal interrupts on console terminal */
1188:
1189: #ifdef UXIII
1190: esctrp() { /* trap console escapes (^\) */
1191: conesc = 1;
1192: signal(SIGQUIT,SIG_IGN); /* ignore until trapped */
1193: }
1194: #endif
1195:
1196: #ifdef V7
1197: esctrp() { /* trap console escapes (^\) */
1198: conesc = 1;
1199: signal(SIGQUIT,SIG_IGN); /* ignore until trapped */
1200: }
1201: #endif
1202:
1203: #ifdef V9
1204: esctrp() { /* trap console escapes (^\) */
1205: conesc = 1;
1206: signal(SIGQUIT,SIG_IGN); /* ignore until trapped */
1207: }
1208: #endif
1209:
1210: #ifdef C70
1211: esctrp() { /* trap console escapes (^\) */
1212: conesc = 1;
1213: signal(SIGQUIT,SIG_IGN); /* ignore until trapped */
1214: }
1215: #endif
1216:
1217: /* C O N I N T -- Console Interrupt setter */
1218:
1219: conint(f) int (*f)(); { /* Set an interrupt trap. */
1220: int x, y;
1221: #ifdef SIGTSTP
1222: int stptrap(); /* Suspend trap */
1223: #endif
1224:
1225: /* Check for background operation, even if not running on real tty, so that */
1226: /* background flag can be set correctly. */
1227:
1228: #ifdef BSD4
1229: int mypgrp; /* In BSD, we can check whether */
1230: int ctpgrp; /* this process's group is the */
1231: /* same as the controlling */
1232: mypgrp = getpgrp(0); /* terminal's process group. */
1233: ioctl (1, TIOCGPGRP, &ctpgrp);
1234: x = (mypgrp != ctpgrp); /* If they differ, then background. */
1235: debug(F101,"conint process group test","",x);
1236: #else
1237: x = (signal(SIGINT,SIG_IGN) == SIG_IGN);
1238: debug(F101,"conint signal test","",x);
1239: #endif
1240: y = isatty(0);
1241: debug(F101,"conint isatty test","",y);
1242: #ifdef BSD29
1243: /* For some reason the signal() test doesn't work under 2.9 BSD... */
1244: backgrd = !y;
1245: #else
1246: backgrd = (x || !y);
1247: #endif
1248: debug(F101,"conint backgrd","",backgrd);
1249:
1250: signal(SIGHUP,f); /* Ensure lockfile cleared on hangup */
1251: signal(SIGTERM,f); /* or soft kill. */
1252:
1253: /* check if invoked in background -- if so signals set to be ignored */
1254:
1255: if (backgrd) { /* In background, ignore signals */
1256: #ifdef SIGTSTP
1257: signal(SIGTSTP,SIG_IGN); /* Keyboard stop */
1258: #endif
1259: signal(SIGQUIT,SIG_IGN); /* Keyboard quit */
1260: signal(SIGINT,SIG_IGN); /* Keyboard interrupt */
1261: } else {
1262: signal(SIGINT,f); /* Catch terminal interrupt */
1263: #ifdef SIGTSTP
1264: signal(SIGTSTP,stptrap); /* Keyboard stop */
1265: #endif
1266: #ifdef UXIII
1267: signal(SIGQUIT,esctrp); /* Quit signal, Sys III/V. */
1268: if (conesc) conesc = 0; /* Clear out pending escapes */
1269: #else
1270: #ifdef V7
1271: signal(SIGQUIT,esctrp); /* V7 like Sys III/V */
1272: if (conesc) conesc = 0;
1273: #else
1274: #ifdef V9
1275: signal(SIGQUIT,esctrp); /* V7 like Sys III/V */
1276: if (conesc) conesc = 0;
1277: #else
1278: #ifdef aegis
1279: signal(SIGQUIT,f); /* Apollo, catch it like others. */
1280: #else
1281: signal(SIGQUIT,SIG_IGN); /* Others, ignore like 4D & earlier. */
1282: #endif
1283: #endif
1284: #endif
1285: #endif
1286: conif = 1; /* Flag console interrupts on. */
1287: }
1288: return;
1289: }
1290:
1291:
1292: /* C O N N O I -- Reset console terminal interrupts */
1293:
1294: connoi() { /* Console-no-interrupts */
1295:
1296: #ifdef SIGTSTP
1297: signal(SIGTSTP,SIG_DFL);
1298: #endif
1299: signal(SIGINT,SIG_DFL);
1300: signal(SIGHUP,SIG_DFL);
1301: signal(SIGQUIT,SIG_DFL);
1302: signal(SIGTERM,SIG_DFL);
1303: conif = 0; /* Flag interrupt trapping off */
1304: }
1305:
1306: /* myread() -- For use by systems that can do nonblocking read() calls */
1307: /*
1308: Returns:
1309: -1 if no characters available, timer expired
1310: -2 upon error (such as disconnect),
1311: otherwise value of character (0 or greater)
1312: */
1313: myread() {
1314: static int inbuf_item;
1315: static CHAR inbuf[257];
1316: CHAR readit;
1317:
1318: if (ungotn >= 0) {
1319: readit = ungotn;
1320: ungotn = -1;
1321: } else {
1322: if (inbufc > 0) {
1323: readit = inbuf[++inbuf_item];
1324: } else {
1325: #ifdef aegis
1326: /* myread() returns -1 when no input is available. All the users of */
1327: /* myread() explicitly loop until it returns a character or error. */
1328: /* The Apollo code waits for input to be available. */
1329:
1330: /* read in characters */
1331: inbufc = ios_$get((short)ttyfd, ios_$cond_opt, inbuf, 256L, st);
1332: errno = EIO;
1333: if (st.all == ios_$get_conditional_failed) /* get at least one */
1334: inbufc = ios_$get((short)ttyfd, 0, inbuf, 1L, st);
1335: if (st.all == ios_$end_of_file) inbufc = 0;
1336: else if (st.all != status_$ok)
1337: { inbufc = -1; errno = EIO; }
1338: #else
1339: inbufc = read(ttyfd,inbuf,256);
1340: if (inbufc > 0) {
1341: inbuf[inbufc] = '\0';
1342: debug(F101,"myread read","",inbufc);
1343: }
1344: #endif /* aegis */
1345: if (inbufc == 0) {
1346: if (ttmdm) {
1347: debug(F101,"myread read=0, ttmdm","",ttmdm);
1348: errno = 9999; /* magic number for no carrier */
1349: return(-2); /* end of file has no errno */
1350: } else return(-1); /* in sys 5 means no data available */
1351: }
1352: if (inbufc < 0) { /* Real error */
1353: #ifdef EWOULDBLOCK
1354: if (errno == EWOULDBLOCK) return(-1); else return(-2);
1355: #else
1356: return(-2);
1357: #endif /* ewouldblock */
1358: }
1359: readit = inbuf[inbuf_item = 0];
1360: }
1361: inbufc--;
1362: }
1363: return(((int) readit) & 255);
1364: }
1365:
1366: myunrd(ch) CHAR ch; { /* push back up to one character */
1367: ungotn = ch;
1368: }
1369:
1370: /* I N I T R A W Q -- Set up to read /DEV/KMEM for character count. */
1371:
1372: #ifdef V7
1373: /*
1374: Used in Version 7 to simulate Berkeley's FIONREAD ioctl call. This
1375: eliminates blocking on a read, because we can read /dev/kmem to get the
1376: number of characters available for raw input. If your system can't
1377: or you won't let it read /dev/kmem (the world that is) then you must
1378: figure out a different way to do the counting of characters available,
1379: or else replace this by a dummy function that always returns 0.
1380: */
1381: /*
1382: * Call this routine as: initrawq(tty)
1383: * where tty is the file descriptor of a terminal. It will return
1384: * (as a char *) the kernel-mode memory address of the rawq character
1385: * count, which may then be read. It has the side-effect of flushing
1386: * input on the terminal.
1387: */
1388: /*
1389: * John Mackin, Physiology Dept., University of Sydney (Australia)
1390: * ...!decvax!mulga!physiol.su.oz!john
1391: *
1392: * Permission is hereby granted to do anything with this code, as
1393: * long as this comment is retained unmodified and no commercial
1394: * advantage is gained.
1395: */
1396: #include <a.out.h>
1397: #include <sys/proc.h>
1398:
1399: char *initrawq(tty) int tty; {
1400: #ifdef UTS24
1401: return(0);
1402: #else
1403: #ifdef BSD29
1404: return(0);
1405: #else
1406: long lseek();
1407: static struct nlist nl[] = {
1408: {PROCNAME},
1409: {NPROCNAME},
1410: {""}
1411: };
1412: static struct proc *pp;
1413: char *malloc(), *qaddr, *p, c;
1414: int m, pid, me;
1415: NPTYPE xproc; /* Its type is defined in makefile. */
1416: int catch();
1417:
1418: me = getpid();
1419: if ((m = open("/dev/kmem", 0)) < 0) err("kmem");
1420: nlist(BOOTNAME, nl);
1421: if (nl[0].n_type == 0) err("proc array");
1422:
1423: if (nl[1].n_type == 0) err("nproc");
1424:
1425: lseek(m, (long)(nl[1].n_value), 0);
1426: read (m, &xproc, sizeof(xproc));
1427: signal(SIGALRM, catch);
1428: if ((pid = fork()) == 0) {
1429: while(1)
1430: read(tty, &c, 1);
1431: }
1432: alarm(2);
1433:
1434: if(setjmp(jjbuf) == 0) {
1435: while(1)
1436: read(tty, &c, 1);
1437: }
1438: signal(SIGALRM, SIG_DFL);
1439:
1440: #ifdef DIRECT
1441: pp = (struct proc *) nl[0].n_value;
1442: #else
1443: if (lseek(m, (long)(nl[0].n_value), 0) < 0L) err("seek");
1444: if (read(m, &pp, sizeof(pp)) != sizeof(pp)) err("no read of proc ptr");
1445: #endif
1446: lseek(m, (long)(nl[1].n_value), 0);
1447: read(m, &xproc, sizeof(xproc));
1448:
1449: if (lseek(m, (long)pp, 0) < 0L) err("Can't seek to proc");
1450: if ((p = malloc(xproc * sizeof(struct proc))) == NULL) err("malloc");
1451: if (read(m,p,xproc * sizeof(struct proc)) != xproc*sizeof(struct proc))
1452: err("read proc table");
1453: for (pp = (struct proc *)p; xproc > 0; --xproc, ++pp) {
1454: if (pp -> p_pid == (short) pid) goto iout;
1455: }
1456: err("no such proc");
1457:
1458: iout:
1459: close(m);
1460: qaddr = (char *)(pp -> p_wchan);
1461: free (p);
1462: kill(pid, SIGKILL);
1463: wait((int *)0); /* Destroy the ZOMBIEs! */
1464: return (qaddr);
1465: #endif
1466: #endif
1467: }
1468:
1469: /* More V7-support functions... */
1470:
1471: static
1472: err(s) char *s; {
1473: char buf[200];
1474:
1475: sprintf(buf, "fatal error in initrawq: %s", s);
1476: perror(buf);
1477: doexit(1);
1478: }
1479:
1480: static
1481: catch() {
1482: longjmp(jjbuf, -1);
1483: }
1484:
1485:
1486: /* G E N B R K -- Simulate a modem break. */
1487:
1488: #define BSPEED B150
1489:
1490: genbrk(fn) int fn; {
1491: struct sgttyb ttbuf;
1492: int ret, sospeed;
1493:
1494: ret = ioctl(fn, TIOCGETP, &ttbuf);
1495: sospeed = ttbuf.sg_ospeed;
1496: ttbuf.sg_ospeed = BSPEED;
1497: ret = ioctl(fn, TIOCSETP, &ttbuf);
1498: ret = write(fn, "\0\0\0\0\0\0\0\0\0\0\0\0", 8);
1499: ttbuf.sg_ospeed = sospeed;
1500: ret = ioctl(fn, TIOCSETP, &ttbuf);
1501: ret = write(fn, "@", 1);
1502: return;
1503: }
1504: #endif
1505:
1506: /* T T C H K -- Tell how many characters are waiting in tty input buffer */
1507:
1508: ttchk() {
1509: int x; long n;
1510: #ifdef FIONREAD
1511: x = ioctl(ttyfd, FIONREAD, &n); /* Berkeley and maybe some others */
1512: debug(F101,"ttchk","",n);
1513: return((x < 0) ? 0 : n);
1514: #else
1515: #ifdef V7
1516: lseek(kmem[TTY], (long) qaddr[TTY], 0); /* 7th Edition Unix */
1517: x = read(kmem[TTY], &n, sizeof(int));
1518: return((x == sizeof(int))? n: 0);
1519: #else
1520: #ifdef UXIII
1521: return(inbufc + (ungotn >= 0) ); /* Sys III, Sys V */
1522: #else
1523: #ifdef PROVX1
1524: x = ioctl(ttyfd, TIOCQCNT, &ttbuf); /* Pro/3xx Venix V.1 */
1525: n = ttbuf.sg_ispeed & 0377;
1526: return((x < 0) ? 0 : n);
1527: #else
1528: #ifdef aegis
1529: return(inbufc + (ungotn >= 0) ); /* Apollo Aegis */
1530: #else
1531: #ifdef C70
1532: return(inbufc + (ungotn >= 0) ); /* etc... */
1533: #else
1534: return(0);
1535: #endif
1536: #endif
1537: #endif
1538: #endif
1539: #endif
1540: #endif
1541: }
1542:
1543:
1544: /* T T X I N -- Get n characters from tty input buffer */
1545:
1546: /* Returns number of characters actually gotten, or -1 on failure */
1547:
1548: /* Intended for use only when it is known that n characters are actually */
1549: /* Available in the input buffer. */
1550:
1551: ttxin(n,buf) int n; char *buf; {
1552: int x;
1553:
1554: #ifdef MYREAD
1555: for( x = 0; (x > -1) && (x < n); buf[x++] = myread() );
1556: #else
1557: debug(F101,"ttxin: n","",n);
1558: x = read(ttyfd,buf,n);
1559: debug(F101," x","",x);
1560: #endif
1561: if (x > 0) buf[x] = '\0';
1562: if (x < 0) x = -1;
1563: return(x);
1564: }
1565:
1566: /* T T O L -- Similar to "ttinl", but for writing. */
1567:
1568: ttol(s,n) int n; char *s; {
1569: int x;
1570: if (ttyfd < 0) return(-1); /* Not open. */
1571: x = write(ttyfd,s,n);
1572: debug(F111,"ttol",s,n);
1573: if (x < 0) debug(F101,"ttol failed","",x);
1574: return(x);
1575: }
1576:
1577:
1578: /* T T O C -- Output a character to the communication line */
1579:
1580: ttoc(c) char c; {
1581: if (ttyfd < 0) return(-1); /* Not open. */
1582: return(write(ttyfd,&c,1));
1583: }
1584:
1585: /* T T I N L -- Read a record (up to break character) from comm line. */
1586: /*
1587: If no break character encountered within "max", return "max" characters,
1588: with disposition of any remaining characters undefined. Otherwise, return
1589: the characters that were read, including the break character, in "dest" and
1590: the number of characters read as the value of the function, or 0 upon end of
1591: file, or -1 if an error occurred. Times out & returns error if not completed
1592: within "timo" seconds.
1593: */
1594: #define CTRLC '\03'
1595: ttinl(dest,max,timo,eol) int max,timo; CHAR *dest, eol; {
1596: int x = 0, ccn = 0, c, i, j, m, n; /* local variables */
1597:
1598: if (ttyfd < 0) return(-1); /* Not open. */
1599:
1600: m = (ttprty) ? 0177 : 0377; /* Parity stripping mask. */
1601: *dest = '\0'; /* Clear destination buffer */
1602: if (timo) signal(SIGALRM,timerh); /* Enable timer interrupt */
1603: alarm(timo); /* Set it. */
1604: if (setjmp(sjbuf)) { /* Timer went off? */
1605: x = -1;
1606: } else {
1607: i = 0; /* Next char to process */
1608: j = 0; /* Buffer position */
1609: while (1) {
1610: if ((n = ttchk()) > 0) { /* See how many chars have arrived */
1611: if (n > (max - j)) n = max - j;
1612: if ((n = ttxin(n,dest+i)) < 0) { /* Get them all at once */
1613: x = -1;
1614: break;
1615: }
1616: } else { /* Or else... */
1617: n = 1; /* just wait for a char */
1618: if ((c = ttinc(0)) == -1) {
1619: x = -1;
1620: break;
1621: }
1622: dest[i] = c; /* Got one. */
1623: }
1624: j = i + n; /* Remember next buffer position. */
1625: if (j >= max) {
1626: debug(F101,"ttinl buffer overflow","",j);
1627: x = -1;
1628: break;
1629: }
1630: for (i; i < j; i++) { /* Go thru all chars we just got */
1631: dest[i] &= m; /* Strip any parity */
1632: if (dest[i] == eol) { /* Got eol? */
1633: dest[++i] = '\0'; /* Yes, tie off string, */
1634: alarm(0); /* turn off timers, etc, */
1635: if (timo) signal(SIGALRM,SIG_DFL); /* and return length. */
1636: return(i);
1637: } else if ((dest[i] & 0177) == CTRLC) { /* Check for ^C^C */
1638: if (++ccn > 1) { /* If we got 2 in a row, clean up */
1639: alarm(0); /* and exit. */
1640: signal(SIGALRM,SIG_DFL);
1641: fprintf(stderr,"^C...");
1642: ttres();
1643: fprintf(stderr,"\n");
1644: return(-2);
1645: }
1646: } else ccn = 0; /* Not ^C, so reset ^C counter, */
1647: }
1648: }
1649: }
1650: debug(F100,"ttinl timout","",0); /* Get here on timeout. */
1651: debug(F111," with",dest,i);
1652: alarm(0); /* Turn off timer */
1653: signal(SIGALRM,SIG_DFL); /* and interrupt, */
1654: return(x); /* and return error code. */
1655: }
1656:
1657: /* T T I N C -- Read a character from the communication line */
1658:
1659: ttinc(timo) int timo; {
1660: int m, n = 0;
1661: CHAR ch = 0;
1662:
1663: m = (ttprty) ? 0177 : 0377; /* Parity stripping mask. */
1664: if (ttyfd < 0) return(-1); /* Not open. */
1665: if (timo <= 0) { /* Untimed. */
1666: #ifdef MYREAD
1667: /* comm line failure returns -1 thru myread, so no &= 0377 */
1668: while ((n = myread()) == -1) ; /* Wait for a character... */
1669: if (n == -2) n++;
1670: return( (n < 0) ? -1 : n & m );
1671: #else
1672: while ((n = read(ttyfd,&ch,1)) == 0) ; /* Wait for a character. */
1673: return( (n < 0) ? -1 : (ch & 0377) );
1674: #endif
1675: }
1676: signal(SIGALRM,timerh); /* Timed, set up timer. */
1677: alarm(timo);
1678: if (setjmp(sjbuf)) {
1679: n = -1;
1680: } else {
1681: #ifdef MYREAD
1682: while ((n = myread()) == -1) ; /* If managing own buffer... */
1683: if (n == -2) {
1684: n++;
1685: } else {
1686: ch = n;
1687: n = 1;
1688: }
1689: #else
1690: n = read(ttyfd,&ch,1); /* Otherwise call the system. */
1691: #endif
1692: }
1693: alarm(0); /* Turn off timer, */
1694: signal(SIGALRM,SIG_DFL); /* and interrupt. */
1695: return( (n < 0) ? -1 : (ch & m) ); /* Return char or -1. */
1696: }
1697:
1698: /* T T S N D B -- Send a BREAK signal */
1699:
1700: ttsndb() {
1701: int x; long n; char spd;
1702:
1703: if (ttyfd < 0) return(-1); /* Not open. */
1704:
1705: #ifdef PROVX1
1706: gtty(ttyfd,&ttbuf); /* Get current tty flags */
1707: spd = ttbuf.sg_ospeed; /* Save speed */
1708: ttbuf.sg_ospeed = B50; /* Change to 50 baud */
1709: stty(ttyfd,&ttbuf); /* ... */
1710: write(ttyfd,brnuls,3); /* Send 3 nulls */
1711: ttbuf.sg_ospeed = spd; /* Restore speed */
1712: stty(ttyfd,&ttbuf); /* ... */
1713: return(0);
1714: #else
1715: #ifdef aegis
1716: sio_$control((short)ttyfd, sio_$send_break, 250, st);
1717: return(0);
1718: #else
1719: #ifdef UXIII
1720: if (ioctl(ttyfd,TCSBRK,(char *)0) < 0) { /* Send a BREAK */
1721: perror("Can't send BREAK");
1722: return(-1);
1723: }
1724: return(0);
1725: #else
1726: #ifdef ANYBSD
1727: n = FWRITE; /* Flush output queue. */
1728: ioctl(ttyfd,TIOCFLUSH,&n); /* Ignore any errors.. */
1729: if (ioctl(ttyfd,TIOCSBRK,(char *)0) < 0) { /* Turn on BREAK */
1730: perror("Can't send BREAK");
1731: return(-1);
1732: }
1733: x = msleep(275); /* Sleep for so many milliseconds */
1734: if (ioctl(ttyfd,TIOCCBRK,(char *)0) < 0) { /* Turn off BREAK */
1735: perror("BREAK stuck!!!");
1736: doexit(1); /* Get out, closing the line. */
1737: /* with exit status = 1 */
1738: }
1739: return(x);
1740: #else
1741: #ifdef V7
1742: genbrk(ttyfd); /* Simulate a BREAK */
1743: return(x);
1744: #endif
1745: #endif
1746: #endif
1747: #endif
1748: #endif
1749: }
1750:
1751: /* M S L E E P -- Millisecond version of sleep(). */
1752:
1753: /*
1754: Intended only for small intervals. For big ones, just use sleep().
1755: */
1756:
1757: msleep(m) int m; {
1758:
1759: #ifdef aegis
1760: time_$clock_t dur;
1761:
1762: dur.c2.high16 = 0;
1763: dur.c2.low32 = 250 * m; /* one millisecond = 250 four microsecond ticks */
1764: time_$wait(time_$relative, dur, st);
1765: return(0);
1766: #else
1767: #ifdef PROVX1
1768: if (m <= 0) return(0);
1769: sleep(-((m * 60 + 500) / 1000));
1770: return(0);
1771: #endif
1772:
1773: #ifdef ANYBSD
1774: int t1, t3, t4;
1775: if (m <= 0) return(0);
1776: #ifndef BSD42
1777: /* 2.9 and 4.1 BSD do it this way */
1778: if (ftime(&ftp) < 0) return(-1); /* Get current time. */
1779: t1 = ((ftp.time & 0xff) * 1000) + ftp.millitm;
1780: while (1) {
1781: ftime(&ftp); /* new time */
1782: t3 = (((ftp.time & 0xff) * 1000) + ftp.millitm) - t1;
1783: if (t3 > m) return(t3);
1784: }
1785: #else
1786: /* 4.2 & above can do it with select()... */
1787: if (gettimeofday(&tv, &tz) < 0) return(-1); /* Get current time. */
1788: t1 = tv.tv_sec; /* Seconds */
1789:
1790: tv.tv_sec = 0; /* Use select() */
1791: tv.tv_usec = m * 1000;
1792: return(select( 0, (int *)0, (int *)0, (int *)0, &tv) );
1793: #endif
1794: #endif
1795:
1796: /* The clock-tick business is a pain. Wm. E. Davidsen suggested: */
1797: /* #include <sys/param.h> */
1798: /* #define CLOCK_TICK 1000/HZ */
1799: /* But I don't see the symbol HZ in this file on my VAX. */
1800: /* Maybe just for XENIX. */
1801:
1802: #ifdef UXIII
1803: #ifdef XENIX
1804: /* Actually, watch out. It's 50 on the AT, 20 on older PCs... */
1805: #define CLOCK_TICK 50 /* millisecs per clock tick */
1806: #else
1807: #ifndef XENIX
1808: #define CLOCK_TICK 17 /* 1/60 sec */
1809: #endif
1810: #endif
1811:
1812: extern long times();
1813: long t1, t2, tarray[4];
1814: int t3;
1815:
1816: /* In SCO Xenix 2.1.3 or later, you can use nap((long)m) to do this. */
1817:
1818: if (m <= 0) return(0);
1819: if ((t1 = times(tarray)) < 0) return(-1);
1820: while (1) {
1821: if ((t2 = times(tarray)) < 0) return(-1);
1822: t3 = ((int)(t2 - t1)) * CLOCK_TICK;
1823: if (t3 > m) return(t3);
1824: }
1825: #endif
1826:
1827: #ifdef TOWER1
1828: int t1, t3;
1829: if (m <= 0) return(0);
1830: if (ftime(&ftp) < 0) return(-1); /* Get current time. */
1831: t1 = ((ftp.time & 0xff) * 1000) + ftp.millitm;
1832: while (1) {
1833: ftime(&ftp); /* new time */
1834: t3 = (((ftp.time & 0xff) * 1000) + ftp.millitm) - t1;
1835: if (t3 > m) return (t3);
1836: }
1837: #endif
1838: #endif
1839: }
1840:
1841: /* R T I M E R -- Reset elapsed time counter */
1842:
1843: rtimer() {
1844: tcount = time( (long *) 0 );
1845: }
1846:
1847:
1848: /* G T I M E R -- Get current value of elapsed time counter in seconds */
1849:
1850: gtimer() {
1851: int x;
1852: x = (int) (time( (long *) 0 ) - tcount);
1853: rtimer();
1854: return( (x < 0) ? 0 : x );
1855: }
1856:
1857:
1858: /* Z T I M E -- Return date/time string */
1859:
1860: ztime(s) char **s; {
1861:
1862: #ifdef UXIII
1863: extern long time(); /* Sys III/V way to do it */
1864: char *ctime();
1865: long clock_storage;
1866:
1867: clock_storage = time( (long *) 0 );
1868: *s = ctime( &clock_storage );
1869: #endif
1870:
1871: #ifdef PROVX1
1872: int utime[2]; /* Venix way */
1873: time(utime);
1874: *s = ctime(utime);
1875: #endif
1876:
1877: #ifdef ANYBSD
1878: char *asctime(); /* Berkeley way */
1879: struct tm *localtime();
1880: struct tm *tp;
1881: #ifdef BSD42
1882: gettimeofday(&tv, &tz); /* BSD 4.2 */
1883: time(&tv.tv_sec);
1884: tp = localtime(&tv.tv_sec);
1885: #else
1886: time(&clock); /* BSD 4.1, 2.9 ... ceb */
1887: tp = localtime(&clock);
1888: #endif
1889: *s = asctime(tp);
1890: #endif
1891:
1892: #ifdef TOWER1
1893: char *asctime(); /* Tower way */
1894: struct tm *localtime();
1895: struct tm *tp;
1896:
1897: time(&clock);
1898: tp = localtime(&clock);
1899: *s = asctime(tp);
1900: #endif
1901: #ifdef V7
1902: char *asctime(); /* V7 way */
1903: struct tm *localtime();
1904: struct tm *tp;
1905:
1906: time(&clock);
1907: tp = localtime(&clock);
1908: *s = asctime(tp);
1909: #endif
1910: }
1911:
1912: /* C O N G M -- Get console terminal modes. */
1913:
1914: /*
1915: Saves current console mode, and establishes variables for switching between
1916: current (presumably normal) mode and other modes.
1917: */
1918:
1919: congm() {
1920: if (!isatty(0)) return(0); /* only for real ttys */
1921: #ifdef aegis
1922: ios_$inq_type_uid(ios_$stdin, conuid, st);
1923: if (st.all != status_$ok)
1924: { fprintf(stderr, "problem getting stdin objtype: "); error_$print(st); }
1925: concrp = (conuid == mbx_$uid);
1926: conbufn = 0;
1927: #endif
1928: #ifndef UXIII
1929: #ifdef V9
1930: if (ioctl(0,TIOCGETP,&ccold) < 0) {
1931: perror("ckutio:congm:ioctl(...ccold)");
1932: return(-1);
1933: }
1934: if (ioctl(0,TIOCGETP,&cccbrk) < 0) {
1935: perror("ckutio:congm:ioctl(...cccbrk)");
1936: return(-1);
1937: }
1938: if (ioctl(0,TIOCGETP,&ccraw) < 0) {
1939: perror("ckutio:congm:ioctl(...ccraw)");
1940: return(-1);
1941: }
1942: #else
1943: gtty(0,&ccold); /* Structure for restoring */
1944: gtty(0,&cccbrk); /* For setting CBREAK mode */
1945: gtty(0,&ccraw); /* For setting RAW mode */
1946: #endif
1947: #else
1948: ioctl(0,TCGETA,&ccold);
1949: ioctl(0,TCGETA,&cccbrk);
1950: ioctl(0,TCGETA,&ccraw);
1951: #endif
1952: #ifdef VXVE
1953: cccbrk.c_line = 0; /* STTY line 0 for CDC VX/VE */
1954: ioctl(0,TCSETA,&cccbrk);
1955: ccraw.c_line = 0; /* STTY line 0 for CDC VX/VE */
1956: ioctl(0,TCSETA,&ccraw);
1957: #endif /* vxve */
1958: cgmf = 1; /* Flag that we got them. */
1959: return(0);
1960: }
1961:
1962:
1963: /* C O N C B -- Put console in cbreak mode. */
1964:
1965: /* Returns 0 if ok, -1 if not */
1966:
1967: concb(esc) char esc; {
1968: int x;
1969: if (!isatty(0)) return(0); /* only for real ttys */
1970: if (cgmf == 0) congm(); /* Get modes if necessary. */
1971: escchr = esc; /* Make this available to other fns */
1972: ckxech = 1; /* Program can echo characters */
1973: #ifdef aegis
1974: conbufn = 0;
1975: if (concrp) return(write(1, "\035\002", 2));
1976: if (conuid == input_pad_$uid) {pad_$raw(ios_$stdin, st); return(0);}
1977: #endif
1978: #ifndef UXIII
1979: cccbrk.sg_flags |= CBREAK; /* Set to character wakeup, */
1980: cccbrk.sg_flags &= ~ECHO; /* no echo. */
1981: #ifdef V9
1982: x = ioctl(0,TIOCSETP,&cccbrk); /* set new modes . */
1983: #else
1984: x = stty(0,&cccbrk);
1985: #endif
1986: #else
1987: cccbrk.c_lflag &= ~(ICANON|ECHO);
1988: cccbrk.c_cc[0] = 003; /* interrupt char is control-c */
1989: cccbrk.c_cc[1] = escchr; /* escape during packet modes */
1990: cccbrk.c_cc[4] = 1;
1991: #ifdef ZILOG
1992: cccbrk.c_cc[5] = 0;
1993: #else
1994: cccbrk.c_cc[5] = 1;
1995: #endif /* zilog */
1996: x = ioctl(0,TCSETAW,&cccbrk); /* set new modes . */
1997: #endif
1998:
1999: #ifndef aegis
2000: if (x > -1) setbuf(stdout,NULL); /* Make console unbuffered. */
2001: #endif
2002: #ifdef V7
2003: if (kmem[CON] < 0) {
2004: qaddr[CON] = initrawq(0);
2005: if((kmem[CON] = open("/dev/kmem", 0)) < 0) {
2006: fprintf(stderr, "Can't read /dev/kmem in concb.\n");
2007: perror("/dev/kmem");
2008: exit(1);
2009: }
2010: }
2011: #endif
2012: return(x);
2013: }
2014:
2015: /* C O N B I N -- Put console in binary mode */
2016:
2017: /* Returns 0 if ok, -1 if not */
2018:
2019: conbin(esc) char esc; {
2020: if (!isatty(0)) return(0); /* only for real ttys */
2021: if (cgmf == 0) congm(); /* Get modes if necessary. */
2022: escchr = esc; /* Make this available to other fns */
2023: ckxech = 1; /* Program can echo characters */
2024: #ifdef aegis
2025: conbufn = 0; if (concrp) return(write(1, "\035\002", 2));
2026: if (conuid == input_pad_$uid) {pad_$raw(ios_$stdin, st); return(0);}
2027: #endif
2028: #ifndef UXIII
2029: ccraw.sg_flags |= (RAW|TANDEM); /* Set rawmode, XON/XOFF */
2030: ccraw.sg_flags &= ~(ECHO|CRMOD); /* Set char wakeup, no echo */
2031: #ifdef V9
2032: return(ioctl(0,TIOCSETP,&ccraw));
2033: #else
2034: return(stty(0,&ccraw));
2035: #endif
2036: #else
2037: ccraw.c_lflag &= ~(ISIG|ICANON|ECHO);
2038: ccraw.c_iflag |= (BRKINT|IGNPAR);
2039: ccraw.c_iflag &= ~(IGNBRK|INLCR|IGNCR|ICRNL|IUCLC|IXON|IXANY|IXOFF
2040: |INPCK|ISTRIP);
2041: ccraw.c_oflag &= ~OPOST;
2042:
2043: /*** Kermit used to put the console in 8-bit raw mode, but some users have
2044: *** pointed out that this should not be done, since some sites actually
2045: *** use terminals with parity settings on their Unix systems, and if we
2046: *** override the current settings and stop doing parity, then their terminals
2047: *** will display blotches for characters whose parity is wrong. Therefore,
2048: *** the following two lines are commented out (Larry Afrin, Clemson U):
2049: ***
2050: *** ccraw.c_cflag &= ~(PARENB|CSIZE);
2051: *** ccraw.c_cflag |= (CS8|CREAD);
2052: ***
2053: *** Sys III/V sites that have trouble with this can restore these lines.
2054: ***/
2055: ccraw.c_cc[4] = 1;
2056: ccraw.c_cc[5] = 1;
2057: return(ioctl(0,TCSETAW,&ccraw) ); /* set new modes . */
2058: #endif
2059: }
2060:
2061:
2062: /* C O N R E S -- Restore the console terminal */
2063:
2064: conres() {
2065: if (cgmf == 0) return(0); /* Don't do anything if modes */
2066: if (!isatty(0)) return(0); /* only for real ttys */
2067: #ifndef UXIII /* except for sIII, */
2068: sleep(1); /* not known! */
2069: #endif /* (sIII does wait in ioctls) */
2070: ckxech = 0; /* System should echo chars */
2071: #ifdef aegis
2072: conbufn = 0; if (concrp) return(write(1, "\035\001", 2));
2073: if (conuid == input_pad_$uid) {pad_$cooked(ios_$stdin, st); return(0);}
2074: #endif
2075: #ifndef UXIII
2076: #ifdef V9
2077: return(ioctl(0,TIOCSETP,&ccold));
2078: #else
2079: return(stty(0,&ccold)); /* Restore controlling tty */
2080: #endif
2081: #else
2082: return(ioctl(0,TCSETAW,&ccold));
2083: #endif
2084: }
2085:
2086: /* C O N O C -- Output a character to the console terminal */
2087:
2088: conoc(c) char c; {
2089: write(1,&c,1);
2090: }
2091:
2092: /* C O N X O -- Write x characters to the console terminal */
2093:
2094: conxo(x,s) char *s; int x; {
2095: write(1,s,x);
2096: }
2097:
2098: /* C O N O L -- Write a line to the console terminal */
2099:
2100: conol(s) char *s; {
2101: int len;
2102: len = strlen(s);
2103: write(1,s,len);
2104: }
2105:
2106: /* C O N O L A -- Write an array of lines to the console terminal */
2107:
2108: conola(s) char *s[]; {
2109: int i;
2110: for (i=0 ; *s[i] ; i++) conol(s[i]);
2111: }
2112:
2113: /* C O N O L L -- Output a string followed by CRLF */
2114:
2115: conoll(s) char *s; {
2116: conol(s);
2117: write(1,"\r\n",2);
2118: }
2119:
2120: /* C O N C H K -- Return how many characters available at console */
2121:
2122: conchk() {
2123: int x; long n;
2124:
2125: #ifdef PROVX1
2126: x = ioctl(0, TIOCQCNT, &ttbuf);
2127: n = ttbuf.sg_ispeed & 0377;
2128: return((x < 0) ? 0 : n);
2129: #else
2130: #ifdef aegis
2131: if (conbufn > 0) return(conbufn); /* use old count if nonzero */
2132:
2133: /* read in more characters */
2134: conbufn = ios_$get(ios_$stdin,
2135: ios_$cond_opt, conbuf, (long)sizeof(conbuf), st);
2136: if (st.all != status_$ok) conbufn = 0;
2137: conbufp = conbuf;
2138: return(conbufn);
2139: #else
2140: #ifdef V7
2141: lseek(kmem[CON], (long) qaddr[CON], 0);
2142: x = read(kmem[CON], &n, sizeof(int));
2143: return((x == sizeof(int))? n: 0);
2144: #else
2145: #ifdef UXIII
2146: if (conesc) { /* Escape typed */
2147: conesc = 0;
2148: signal(SIGQUIT,esctrp); /* Restore escape */
2149: return(1);
2150: }
2151: return(0);
2152: #else
2153: #ifdef C70
2154: if (conesc) { /* Escape typed */
2155: conesc = 0;
2156: signal(SIGQUIT,esctrp); /* Restore escape */
2157: return(1);
2158: }
2159: return(0);
2160: #else
2161: #ifdef FIONREAD
2162: x = ioctl(0, FIONREAD, &n); /* BSD and maybe some others */
2163: return((x < 0) ? 0 : n);
2164: #else
2165: return(0); /* Others can't do. */
2166: #endif
2167: #endif
2168: #endif
2169: #endif
2170: #endif
2171: #endif
2172: }
2173:
2174: /* C O N I N C -- Get a character from the console */
2175:
2176: coninc(timo) int timo; {
2177: int n = 0; char ch;
2178: #ifdef aegis
2179: fflush(stdout);
2180: if (conchk() > 0)
2181: { --conbufn; return(*conbufp++ & 0377); }
2182: #endif
2183: if (timo <= 0 ) { /* untimed */
2184: n = read(0, &ch, 1); /* Read a character. */
2185: ch &= 0377;
2186: if (n > 0) return(ch); /* Return the char if read */
2187: else
2188: #ifdef UXIII
2189: #ifndef CIE /* CIE Regulus has no such symbol */
2190: if (n < 0 && errno == EINTR) /* if read was interrupted by QUIT */
2191: return(escchr); /* user entered escape character */
2192: else /* couldnt be ^c, sigint never returns */
2193: #endif
2194: #endif
2195: return(-1); /* Return the char, or -1. */
2196: }
2197: signal(SIGALRM,timerh); /* Timed read, so set up timer */
2198: alarm(timo);
2199: if (setjmp(sjbuf)) n = -2;
2200: else {
2201: n = read(0, &ch, 1);
2202: ch &= 0377;
2203: }
2204: alarm(0); /* Stop timing, we got our character */
2205: signal(SIGALRM,SIG_DFL);
2206: if (n > 0) return(ch);
2207: else
2208: #ifdef UXIII
2209: #ifndef CIE /* CIE Regulus has no such symbol */
2210: if (n == -1 && errno == EINTR) /* If read interrupted by QUIT, */
2211: return(escchr); /* user entered escape character, */
2212: else /* can't be ^c, sigint never returns */
2213: #endif
2214: #endif
2215: return(-1);
2216: }
2217:
2218: #ifdef ATT7300
2219: #include <sys/phone.h>
2220: #include <dial.h>
2221: #define ATT7300 4 /* REH */
2222: CALL tcfig;
2223: struct termio ctermio = {0};
2224: struct updata ph;
2225: static int att7300 = 0; /* REH */
2226:
2227: /* A T T D I A L -- Dial up the remote system */
2228:
2229: /* Purpose: to open and dial a number on the internal modem available on the
2230: * ATT7300 UNIX PC. Richard E. Hill, Dickinson, TX.
2231: */
2232:
2233: attdial(ttname,speed,telnbr) char *ttname,*telnbr; int speed; {
2234: int err;
2235:
2236: if (ttyfd > 0) {
2237: ioctl(ttyfd,TCGETA,&ctermio); /* save current settings */
2238: err=ttclos(); /* close port */
2239: } else ioctl(0,TCGETA,&ctermio); /* get standard settings */
2240:
2241: /* Open line, check availability & data mode, turn on speaker, close port. */
2242:
2243: ttyfd = open (ttname,O_RDWR | O_NDELAY);
2244: if (err=ioctl(ttyfd,PIOCOFFHOOK,&ph)) {
2245: printf("Phone line for %s not available:%d %d %d\n",
2246: ttname,ttyfd,err,errno);
2247: close(ttyfd);
2248: ttyfd = -1;
2249: return(-1);
2250: }
2251: ioctl(ttyfd,PIOCGETP,&ph); /* set phone parameters */
2252: if (ph.c_lineparam & VOICE) {
2253: printf("Phone line %s not in data mode. Switch to data & redial\n",
2254: ttname);
2255: ioctl(ttyfd,PIOCDISC,&ph);
2256: close(ttyfd);
2257: ttyfd = -1;
2258: return(-1);
2259: }
2260: ph.c_feedback |= (SPEAKERON | RINGON | NORMSPK);
2261: ioctl(ttyfd,PIOCSETP,&ph); /* set phone parameters */
2262: ioctl(ttyfd,PIOCDISC,&ph); /* release phone resources for dial */
2263: close(ttyfd);
2264: /*
2265: fprintf(stderr,"Phone line status. line_par:%o dialtone_wait:%o \
2266: line_status:%o feedback:%o\n",
2267: ph.c_lineparam, ph.c_waitdialtone, ph.c_linestatus,ph.c_feedback);
2268: */
2269:
2270: /* Close line so that it can be reopened using system routine "dial". */
2271: /* Set terminal configuration parameters. */
2272:
2273: ctermio.c_iflag |= (BRKINT|IGNPAR|IXON|IXOFF);
2274: ctermio.c_iflag &= ~(IGNBRK|INLCR|IGNCR|ICRNL|IUCLC|INPCK|ISTRIP| IXANY);
2275: ctermio.c_oflag &= ~OPOST;
2276: ctermio.c_cflag = (B1200 | CS8 | CREAD | CLOCAL | HUPCL);
2277: ctermio.c_lflag &= ~(ICANON|ECHO);
2278: ctermio.c_cc[4] = 1;
2279: ctermio.c_cc[5] = 0;
2280: tcfig.attr = &ctermio;
2281: tcfig.baud = speed <= 1200 ? speed : 1200;
2282: tcfig.speed = speed <= 300 ? 300 : 1200;
2283: tcfig.line = ttname;
2284: tcfig.telno = telnbr;
2285: tcfig.modem = 0;
2286: fprintf (stderr,"dialing:%s on line:%s at %d baud, speed:%d\n",
2287: tcfig.telno,tcfig.line,tcfig.baud,tcfig.speed);
2288: if ((ttyfd = dial(tcfig)) > 0) {
2289: att7300 = 1;
2290: /*
2291: ioctl(ttyfd,TCGETA,&ctermio);
2292: fprintf(stderr,"after dial:iflag:%o, oflag:%o, cflag:%o, lflag:%o,\
2293: line:%o\n", ctermio.c_iflag,ctermio.c_oflag,ctermio.c_cflag,
2294: ctermio.c_lflag, ctermio.c_line);
2295: */
2296: return(0);
2297: }
2298: printf("Sorry, connection not made. Error status: %d\n",ttyfd);
2299: return(-2);
2300: }
2301: #endif /* ATT7300 */
2302:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.