|
|
1.1 root 1: char *ckxv = "UNIX tty I/O, 5A(087), 8 Feb 92";
2:
3: /* C K U T I O */
4:
5: /* C-Kermit interrupt, terminal control & i/o functions for UNIX */
6:
7: /*
8: Author: Frank da Cruz ([email protected], [email protected]),
9: Columbia University Center for Computing Activities. Many other contributors.
10: First released January 1985.
11: Copyright (C) 1985, 1992, Trustees of Columbia University in the City of New
12: York. Permission is granted to any individual or institution to use, copy, or
13: redistribute this software so long as it is not sold for profit, provided this
14: copyright notice is retained.
15: */
16:
17: /* Includes for all Unixes (conditional includes come later) */
18:
19: #include "ckcdeb.h" /* This moved to here. */
20: #include "ckcnet.h" /* Symbols for network types. */
21:
22: #include <errno.h> /* System error numbers */
23:
24: #ifdef SDIRENT /* Directory bits... */
25: #define DIRENT
26: #endif /* SDIRENT */
27:
28: #ifdef XNDIR
29: #include <sys/ndir.h>
30: #else /* !XNDIR */
31: #ifdef NDIR
32: #include <ndir.h>
33: #else /* !NDIR, !XNDIR */
34: #ifdef RTU
35: #include "/usr/lib/ndir.h"
36: #else /* !RTU, !NDIR, !XNDIR */
37: #ifdef DIRENT
38: #ifdef SDIRENT
39: #include <sys/dirent.h>
40: #else
41: #include <dirent.h>
42: #endif /* SDIRENT */
43: #else /* !RTU, !NDIR, !XNDIR, !DIRENT, i.e. all others */
44: #include <sys/dir.h>
45: #endif /* DIRENT */
46: #endif /* RTU */
47: #endif /* NDIR */
48: #endif /* XNDIR */
49:
50: /* Definition of HZ, used in msleep() */
51:
52: #ifdef MIPS
53: #define HZ ( 1000 / CLOCK_TICK )
54: #else
55: #ifdef ATTSV
56: #ifndef NAP
57: #ifndef TRS16
58: #include <sys/param.h>
59: #else
60: #define HZ ( 1000 / CLOCK_TICK )
61: #endif /* TRS16 */
62: #endif /* NAP */
63: #endif /* ATTSV */
64: #endif /* MIPS */
65:
66: #ifdef M_UNIX
67: #undef NGROUPS_MAX /* Prevent multiple definition warnings */
68: #endif /* M_UNIX */
69:
70: #include <signal.h> /* Signals */
71:
72: /* For setjmp and longjmp */
73:
74: #ifndef ZILOG
75: #include <setjmp.h>
76: #else
77: #include <setret.h>
78: #endif /* ZILOG */
79:
80: /* Maximum length for the name of a tty device */
81:
82: #ifndef DEVNAMLEN
83: #define DEVNAMLEN 25
84: #endif
85:
86: #ifdef NETCONN
87: #undef DEVNAMLEN
88: #define DEVNAMLEN 50 /* longer field for host:service */
89: #endif /* NETCONN */
90:
91: /*
92: The following test differentiates between 4.1 BSD and 4.2 & later.
93: If you have a 4.1BSD system with the DIRENT library, this test could
94: mistakenly diagnose 4.2BSD and then later enable the use of system calls
95: that aren't defined. If indeed there are such systems, we can use some
96: other way of testing for 4.1BSD, or add yet another compile-time switch.
97: */
98: #ifdef BSD4
99: #ifdef MAXNAMLEN
100: #ifndef FT21
101: #ifndef FT18 /* Except for Fortune. */
102: #define BSD42
103: #endif /* FT18 */
104: #endif /* FT21 */
105: #endif /* MAXNAMLEN */
106: #endif /* BSD4 */
107:
108: /*
109: Minix support added by Charles Hedrick,
110: Rutgers University: [email protected]
111: Minix also has V7 enabled.
112: */
113: #ifdef MINIX
114: #define TANDEM 0
115: #define MYREAD
116: #include <limits.h>
117: #endif /* MINIX */
118:
119: #include "ckuver.h" /* Version herald */
120: char *ckxsys = HERALD;
121:
122: /* UUCP lock file name definition */
123:
124: #ifndef NOUUCP
125:
126: /* Name of UUCP tty device lock file */
127:
128: #ifdef ACUCNTRL
129: #define LCKDIR
130: #endif /* ACUCNTRL */
131: /*
132: LOCK_DIR is the name of the lockfile directory.
133: If LOCK_DIR is already defined (e.g. on command line), we don't change it.
134: PIDSTRING means use ASCII string to represent pid in lockfile.
135: */
136: #ifndef LOCK_DIR
137: #ifdef COHERENT
138: #define PIDSTRING
139: #define LOCK_DIR "/tmp";
140: #else
141: #ifdef RTAIX /* IBM RT PC AIX 2.2.1 */
142: #define PIDSTRING
143: #define LOCK_DIR "/etc/locks";
144: #else
145: #ifdef AIXRS
146: #define PIDSTRING
147: #define LOCK_DIR "/etc/locks";
148: #else
149: #ifdef ISIII
150: #define LOCK_DIR "/etc/locks";
151: #else
152: #ifdef HDBUUCP
153: #define PIDSTRING
154: #ifdef M_SYS5 /* wht@n4hgf - SCO */
155: #define LOCK_DIR "/usr/spool/uucp";
156: #else
157: #ifdef M_UNIX
158: #define LOCK_DIR "/usr/spool/uucp";
159: #else
160: #ifdef SVR4
161: #define LOCK_DIR "/var/spool/locks";
162: #else
163: #ifdef SUNOS4
164: #define LOCK_DIR "/var/spool/locks";
165: #else
166: #define LOCK_DIR "/usr/spool/locks";
167: #endif /* SUNOS4 */
168: #endif /* SVR4 */
169: #endif /* M_UNIX */
170: #endif /* M_SYS5 */
171: #else
172: #ifdef LCKDIR
173: #define LOCK_DIR "/usr/spool/uucp/LCK";
174: #else
175: #define LOCK_DIR "/usr/spool/uucp";
176: #endif /* LCKDIR */
177: #endif /* HDBUUCP */
178: #endif /* ISIII */
179: #endif /* AIXRS */
180: #endif /* RTAIX */
181: #endif /* COHERENT */
182: #endif /* !LOCK_DIR (outside ifndef) */
183:
184: #endif /* !NOUUCP */
185:
186: #ifdef ATTSV
187: #define MYREAD
188: #endif /* ATTSV */
189:
190: #ifdef ATT7300
191: #define MYREAD
192: /* bits for attmodem: internal modem in use, restart getty */
193: #define ISMODEM 1
194: #define DOGETY 512
195: #endif /* ATT7300 */
196:
197: #ifdef BSD42
198: #define MYREAD
199: #endif /* BSD42 */
200:
201: #ifdef POSIX
202: #define MYREAD
203: #endif /* POSIX */
204:
205: /*
206: Variables available to outside world:
207:
208: dftty -- Pointer to default tty name string, like "/dev/tty".
209: dfloc -- 0 if dftty is console, 1 if external line.
210: dfprty -- Default parity
211: dfflow -- Default flow control
212: ckxech -- Flag for who echoes console typein:
213: 1 - The program (system echo is turned off)
214: 0 - The system (or front end, or terminal).
215: functions that want to do their own echoing should check this flag
216: before doing so.
217:
218: flfnam -- Name of lock file, including its path, e.g.,
219: "/usr/spool/uucp/LCK..cul0" or "/etc/locks/tty77"
220: lkflfn -- Name of link to lock file, including its paths
221: haslock -- Flag set if this kermit established a uucp lock.
222: backgrd -- Flag indicating program executing in background ( & on
223: end of shell command). Used to ignore INT and QUIT signals.
224: rtu_bug -- Set by stptrap(). RTU treats ^Z as EOF (but only when we handle
225: SIGTSTP)
226:
227: Functions for assigned communication line (either external or console tty):
228:
229: sysinit() -- System dependent program initialization
230: syscleanup() -- System dependent program shutdown
231: ttopen(ttname,local,mdmtyp,timo) -- Open the named tty for exclusive access.
232: ttclos() -- Close & reset the tty, releasing any access lock.
233: ttsspd(cps) -- Set the transmission speed of the tty.
234: ttgspd() -- Get (read) the the transmission speed of the tty.
235: ttpkt(speed,flow,parity) -- Put the tty in packet mode and set the speed.
236: ttvt(speed,flow) -- Put the tty in virtual terminal mode.
237: or in DIALING or CONNECTED modem control state.
238: ttres() -- Restore original tty modes.
239: ttscarr(carrier) -- Set carrier control mode, on/off/auto.
240: ttinl(dest,max,timo) -- Timed read line from the tty.
241: ttinc(timo) -- Timed read character from tty.
242: myread() -- Raw mode bulk buffer read, gives subsequent
243: chars one at a time and simulates FIONREAD.
244: myunrd(c) -- Places c back in buffer to be read (one only)
245: ttchk() -- See how many characters in tty input buffer.
246: ttxin(n,buf) -- Read n characters from tty (untimed).
247: ttol(string,length) -- Write a string to the tty.
248: ttoc(c) -- Write a character to the tty.
249: ttflui() -- Flush tty input buffer.
250: ttsndb() -- Send BREAK signal.
251: ttsndlb() -- Send Long BREAK signal.
252:
253: ttlock(ttname) -- "Lock" tty device against uucp collisions.
254: ttunlck() -- Unlock tty device.
255:
256: For ATT7300/Unix PC, System V:
257: attdial(ttname,speed,telnbr) -- dials ATT7300/Unix PC internal modem
258: offgetty(ttname) -- Turns off getty(1m) for comms line
259: ongetty(ttname) -- Restores getty() to comms line
260: */
261:
262: /*
263: Functions for console terminal:
264:
265: congm() -- Get console terminal modes.
266: concb(esc) -- Put the console in single-character wakeup mode with no echo.
267: conbin(esc) -- Put the console in binary (raw) mode.
268: conres() -- Restore the console to mode obtained by congm().
269: conoc(c) -- Unbuffered output, one character to console.
270: conol(s) -- Unbuffered output, null-terminated string to the console.
271: conola(s) -- Unbuffered output, array of strings to the console.
272: conxo(n,s) -- Unbuffered output, n characters to the console.
273: conchk() -- Check if characters available at console (bsd 4.2).
274: Check if escape char (^\) typed at console (System III/V).
275: coninc(timo) -- Timed get a character from the console.
276: congks(timo) -- Timed get keyboard scan code.
277: conint() -- Enable terminal interrupts on the console if not background.
278: connoi() -- Disable terminal interrupts on the console if not background.
279:
280: Time functions
281:
282: msleep(m) -- Millisecond sleep
283: ztime(&s) -- Return pointer to date/time string
284: rtimer() -- Reset timer
285: gtimer() -- Get elapsed time since last call to rtimer()
286: */
287:
288: /* Conditional Includes */
289:
290: /* Whether to include <sys/file.h> */
291:
292: #ifdef RTU /* RTU doesn't */
293: #define NOFILEH
294: #endif /* RTU */
295:
296: #ifdef CIE /* CIE does. */
297: #undef NOFILEH
298: #endif /* CIE */
299:
300: #ifdef BSD41 /* 4.1 BSD doesn't */
301: #define NOFILEH
302: #endif /* BSD41 */
303:
304: #ifdef is68k /* is68k (whatever that is) */
305: #define NOFILEH
306: #endif /* is68k */
307:
308: #ifdef MINIX /* MINIX */
309: #define NOFILEH
310: #endif /* MINIX */
311:
312: #ifdef COHERENT /* Coherent */
313: #define NOFILEH
314: #endif /* COHERENT */
315:
316: #ifndef NOFILEH /* Now include if selected. */
317: #include <sys/file.h>
318: #endif /* NOFILEH */
319:
320: /* System III, System V */
321:
322: #ifdef ATTSV
323: #include <termio.h>
324: #ifdef SVR3 /* Sys V R3 and later */
325: #ifdef TERMIOX
326: /* Need this for termiox structure, RTS/CTS and DTR/CD flow control */
327: #include <termiox.h>
328: struct termiox rctsx;
329: #else
330: #ifdef STERMIOX
331: #include <sys/termiox.h>
332: struct termiox rctsx;
333: #endif /* STERMIOX */
334: #endif /* TERMIOX */
335: #endif /* SVR3 */
336: #endif /* ATTSV */
337:
338: /* POSIX */
339:
340: #ifdef POSIX /* POSIX uses termios.h */
341: #include <termios.h>
342: #define NOSYSIOCTLH /* No ioctl's allowed. */
343: #undef ultrix /* Turn off any ultrix features. */
344: #endif /* POSIX */
345:
346: #ifdef MINIX /* MINIX uses ioctl's */
347: #define NOSYSIOCTLH /* but has no <sys/ioctl.h> */
348: #endif /* MINIX */
349:
350: /* Others */
351:
352: #ifndef NOSYSIOCTLH /* Others use ioctl() */
353: #include <sys/ioctl.h>
354: #endif /* NOSYSIOCTLH */
355:
356: /* Whether to include <fcntl.h> */
357:
358: #ifndef is68k /* Only a few don't have this one. */
359: #ifndef BSD41
360: #ifndef FT21
361: #ifndef FT18
362: #include <fcntl.h>
363: #endif /* FT18 */
364: #endif /* FT21 */
365: #endif /* BSD41 */
366: #endif /* not is68k */
367:
368: #ifdef ATT7300 /* Unix PC, internal modem dialer */
369: #include <sys/phone.h>
370: #endif /* ATT7300 */
371:
372: #ifdef HPUX /* HP-UX variations. */
373: #define HPUXJOBCTL
374: #include <sys/modem.h> /* HP-UX modem signals */
375: #ifdef hp9000s500 /* Model 500 */
376: #undef HPUXJOBCTL
377: #endif /* hp9000s500 */
378: #ifdef HPUXPRE65
379: #undef HPUXJOBCTL
380: typedef int mflag;
381: #endif /* HPUXPRE65 */
382: #ifdef HPUXJOBCTL
383: #include <sys/bsdtty.h> /* HP-UX Berkeley tty support */
384: #endif /* HPUXJOBCTL */
385: #endif /* HPUX */
386:
387: /* BSD, V7, Coherent, Minix, et al. */
388:
389: #ifndef SVORPOSIX /* Not AT&T Sys V or POSIX */
390: #include <sgtty.h> /* So we use <sgtty.h> */
391: #ifndef PROVX1 /* Now <sys/time.h> ... */
392: #ifndef V7
393: #ifndef BSD41
394: #ifndef COHERENT
395: #include <sys/time.h> /* Clock info (for break generation) */
396: #endif /* COHERENT */
397: #endif /* BSD41 */
398: #endif /* V7 */
399: #endif /* PROVX1 */
400: #endif /* SVORPOSIX */
401:
402: #ifdef BSD41 /* BSD 4.1 */
403: #include <sys/timeb.h>
404: #endif /* BSD41 */
405:
406: #ifdef FT21 /* For:Pro 2.1 */
407: #include <sys/timeb.h>
408: #endif /* FT21 */
409:
410: #ifdef BSD29 /* BSD 2.9 */
411: #include <sys/timeb.h>
412: #endif /* BSD29 */
413:
414: #ifdef TOWER1
415: #include <sys/timeb.h> /* Clock info for NCR Tower */
416: #endif /* TOWER1 */
417:
418: #ifdef COHERENT
419: #include <sys/timeb.h> /* Clock info for NCR Tower */
420: #endif /* COHERENT */
421:
422: #ifdef aegis
423: #include "/sys/ins/base.ins.c"
424: #include "/sys/ins/error.ins.c"
425: #include "/sys/ins/ios.ins.c"
426: #include "/sys/ins/sio.ins.c"
427: #include "/sys/ins/pad.ins.c"
428: #include "/sys/ins/time.ins.c"
429: #include "/sys/ins/pfm.ins.c"
430: #include "/sys/ins/pgm.ins.c"
431: #include "/sys/ins/ec2.ins.c"
432: #include "/sys/ins/type_uids.ins.c"
433: #include <default_acl.h>
434: #undef TIOCEXCL
435: #undef FIONREAD
436: #endif /* aegis */
437:
438: #ifdef sxaE50 /* PFU Compact A SX/A TISP V10/L50 */
439: #undef FIONREAD
440: #endif /* sxaE50 */
441:
442: /* The following #defines are catch-alls for those systems */
443: /* that didn't have or couldn't find <file.h>... */
444:
445: #ifndef FREAD
446: #define FREAD 0x01
447: #endif /* FREAD */
448:
449: #ifndef FWRITE
450: #define FWRITE 0x10
451: #endif /* FWRITE */
452:
453: #ifndef O_RDONLY
454: #define O_RDONLY 000
455: #endif /* O_RDONLY */
456:
457: /* Declarations */
458:
459: #ifdef _POSIX_SOURCE /* This includes MINIX */
460: #include <time.h>
461: #ifdef __GNUC__
462: #ifdef XENIX
463: /*
464: Because Xenix <time.h> doesn't declare time() if we're using gcc.
465: */
466: time_t time();
467: #endif /* XENIX */
468: #endif /* __GNUC__ */
469: #else
470: time_t time(); /* All Unixes should have this... */
471: #endif /* _POSIX_SOURCE */
472:
473: /* Special stuff for V7 input buffer peeking */
474:
475: #ifdef V7
476: int kmem[2] = { -1, -1};
477: char *initrawq(), *qaddr[2]={0,0};
478: #define CON 0
479: #define TTY 1
480: #endif /* V7 */
481:
482: /* dftty is the device name of the default device for file transfer */
483: /* dfloc is 0 if dftty is the user's console terminal, 1 if an external line */
484:
485: #ifndef DFTTY
486: #ifdef PROVX1
487: char *dftty = "/dev/com1.dout"; /* Only example so far of a system */
488: char *dfmdm = "none";
489: int dfloc = 1; /* that goes in local mode by default */
490: #else
491: #ifdef COHERENT
492: char *dftty = "/dev/modem";
493: char *dfmdm = "none";
494: int dfloc = 1;
495: #else
496: char *dftty = CTTNAM; /* Remote by default, use normal */
497: char *dfmdm = "none";
498: int dfloc = 0; /* controlling terminal name. */
499: #endif /* COHERENT */
500: #endif /* PROVX1 */
501: #else
502: char *dftty = DFTTY; /* Default location specified on */
503: char *dfmdm = "none"; /* command line. */
504: int dfloc = 1; /* controlling terminal name. */
505: #endif /* DFTTY */
506:
507: #ifdef RTU
508: int rtu_bug = 0; /* set to 1 when returning from SIGTSTP */
509: #endif /* RTU */
510:
511: int dfprty = 0; /* Default parity (0 = none) */
512: int ttprty = 0; /* Parity in use. */
513: static int ttpmsk = 0377; /* Parity stripping mask. */
514: int ttmdm = 0; /* Modem in use. */
515: int ttcarr = CAR_AUT; /* Carrier handling mode. */
516: int dfflow = 1; /* Xon/Xoff flow control */
517: int backgrd = 0; /* Assume in foreground (no '&' ) */
518: #ifdef ultrix
519: int iniflags = 0; /* fcntl flags for ttyfd */
520: #endif /* ultrix */
521: int fdflag = 0; /* Flag for redirected stdio */
522: int ttfdflg = 0; /* Open File descriptor was given */
523: int tvtflg = 0; /* Flag that ttvt has been called */
524: long ttspeed = -1; /* For saving speed */
525: int ttflow = -9; /* For saving flow */
526: int ttld = -1; /* Line discipline */
527:
528: #ifdef sony_news
529: static int km_con = -1; /* Kanji mode for console tty */
530: static int km_ext = -1; /* Kanji mode for external device */
531: #endif /* sony_news */
532:
533: extern int ttnproto;
534: extern int ttnet;
535:
536: int ckxech = 0; /* 0 if system normally echoes console characters, else 1 */
537:
538: /* Declarations of variables global within this module */
539:
540: static time_t tcount; /* Elapsed time counter */
541: SIGTYP (*saval)() = NULL; /* For saving alarm handler */
542:
543: /*
544: BREAKNULS is defined for systems that simulate sending a BREAK signal
545: by sending a bunch of NUL characters at low speed.
546: */
547: #ifdef PROVX1
548: #ifndef BREAKNULS
549: #define BREAKNULS
550: #endif /* BREAKNULS */
551: #endif /* PROVX1 */
552:
553: #ifdef V7
554: #ifndef BREAKNULS
555: #define BREAKNULS
556: #endif /* BREAKNULS */
557: #endif /* V7 */
558:
559: #ifdef BREAKNULS
560: static char /* A string of nulls */
561: *brnuls = "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0";
562: #endif /* BREAKNULS */
563:
564: static jmp_buf sjbuf; /* Longjump buffers */
565: #ifdef V7
566: static jmp_buf jjbuf;
567: #endif /* V7 */
568:
569: /* static */ /* (Not static any more) */
570: int ttyfd = -1; /* TTY file descriptor */
571:
572: int telnetfd = 0; /* File descriptor is for telnet */
573: int x25fd = 0; /* File descriptor is for X.25 */
574:
575: static int lkf = 0, /* Line lock flag */
576: cgmf = 0, /* Flag that console modes saved */
577: xlocal = 0, /* Flag for tty local or remote */
578: curcarr = 0; /* Carrier mode: require/ignore. */
579:
580: static int netconn = 0; /* 1 if network connection active */
581:
582: static char escchr; /* Escape or attn character */
583:
584: #ifdef BSD42
585: static struct timeval tv; /* For getting time, from sys/time.h */
586: static struct timezone tz;
587: #endif /* BSD42 */
588:
589: #ifdef BSD29
590: static long xclock; /* For getting time from sys/time.h */
591: static struct timeb ftp; /* And from sys/timeb.h */
592: #endif /* BSD29 */
593:
594: #ifdef BSD41
595: static long xclock; /* For getting time from sys/time.h */
596: static struct timeb ftp; /* And from sys/timeb.h */
597: #endif /* BSD41 */
598:
599: #ifdef FT21
600: static long xclock; /* For getting time from sys/time.h */
601: static struct timeb ftp; /* And from sys/timeb.h */
602: #endif /* FT21 */
603:
604: #ifdef TOWER1
605: static long xclock; /* For getting time from sys/time.h */
606: static struct timeb ftp; /* And from sys/timeb.h */
607: #endif /* TOWER1 */
608:
609: #ifdef COHERENT
610: static long xclock; /* For getting time from sys/time.h */
611: static struct timeb ftp; /* And from sys/timeb.h */
612: #endif /* COHERENT */
613:
614: #ifdef V7
615: static long xclock;
616: #endif /* V7 */
617:
618: /* sgtty/termio information... */
619:
620: #ifdef ATTSV
621:
622: static struct termio ttold = {0}; /* Init'd for word alignment, */
623: static struct termio ttraw = {0}; /* which is important for some */
624: static struct termio tttvt = {0}; /* systems, like Zilog... */
625: static struct termio ttcur = {0};
626: static struct termio ccold = {0};
627: static struct termio ccraw = {0};
628: static struct termio cccbrk = {0};
629: #else
630: #ifdef POSIX /* POSIX */
631: static struct termios
632: ttold, ttraw, tttvt, ttcur,
633: ccold, ccraw, cccbrk;
634: #else /* BSD, V7, etc */
635: static struct sgttyb /* sgtty info... */
636: ttold, ttraw, tttvt, ttcur, /* for communication line */
637: ccold, ccraw, cccbrk; /* and for console */
638: #ifdef TIOCGETC
639: #ifdef MINIX
640: static struct sgttyb tchold, tchnoi; /* Special chars */
641: #else
642: static struct tchars tchold, tchnoi;
643: #endif /* MINIX */
644: static int tcharf;
645: #endif /* TIOCGETC */
646: #ifdef TIOCGLTC
647: #ifdef MINIX
648: static struct sgttyb ltchold, ltchnoi;
649: #else
650: static struct ltchars ltchold, ltchnoi;
651: #endif /* MINIX */
652: static int ltcharf;
653: #endif /* TIOCGLTC */
654: int lmodef = 0; /* Local modes */
655: int lmode = 0;
656: #endif /* POSIX */
657: #endif /* ATTSV */
658:
659: #ifdef PROVX1
660: static struct sgttyb ttbuf;
661: #endif /* PROVX1 */
662:
663: #ifdef ultrix
664: /* do we really need this? */
665: static struct sgttyb vanilla;
666: #endif /* ultrix */
667:
668: #ifdef ATT7300
669: static int attmodem = 0; /* ATT7300 internal-modem status */
670: struct updata dialer = {0}; /* Condition dialer for data call */
671: #endif /* ATT7300 */
672:
673: char flfnam[80]; /* uucp lock file path name */
674: #ifdef RTAIX
675: char lkflfn[80]; /* and possible link to it */
676: #endif /* RTAIX */
677: int haslock = 0; /* =1 if this kermit locked uucp */
678:
679: #ifdef SVORPOSIX
680: static int conesc = 0; /* set to 1 if esc char (^\) typed */
681: #else
682: #ifdef V7
683: static int conesc = 0;
684: #else
685: #ifdef C70
686: static int conesc = 0;
687: #endif /* C70 */
688: #endif /* V7 */
689: #endif /* ATTSV */
690:
691: static char ttnmsv[DEVNAMLEN]; /* Copy of open path for tthang */
692:
693: #ifdef aegis
694: static status_$t st; /* error status return value */
695: static short concrp = 0; /* true if console is CRP pad */
696: #define CONBUFSIZ 10
697: static char conbuf[CONBUFSIZ]; /* console readahead buffer */
698: static int conbufn = 0; /* # chars in readahead buffer */
699: static char *conbufp; /* next char in readahead buffer */
700: static uid_$t ttyuid; /* tty type uid */
701: static uid_$t conuid; /* stdout type uid */
702:
703: /* APOLLO Aegis main()
704: * establish acl usage and cleanup handling
705: * this makes sure that CRP pads
706: * get restored to a usable mode
707: */
708: main(argc,argv) int argc; char **argv; {
709: status_$t status;
710: pfm_$cleanup_rec dirty;
711:
712: PID_T pid = getpid();
713:
714: /* acl usage according to invoking environment */
715: default_acl(USE_DEFENV);
716:
717: /* establish a cleanup continuation */
718: status = pfm_$cleanup(dirty);
719: if (status.all != pfm_$cleanup_set) {
720: /* only handle faults for the original process */
721: if (pid == getpid() && status.all > pgm_$max_severity) {
722: /* blew up in main process */
723: status_$t quo;
724: pfm_$cleanup_rec clean;
725:
726: /* restore the console in any case */
727: conres();
728:
729: /* attempt a clean exit */
730: debug(F101, "cleanup fault status", "", status.all);
731:
732: /* doexit(), then send status to continuation */
733: quo = pfm_$cleanup(clean);
734: if (quo.all == pfm_$cleanup_set)
735: doexit(pgm_$program_faulted,-1);
736: else if (quo.all > pgm_$max_severity)
737: pfm_$signal(quo); /* blew up in doexit() */
738: }
739: /* send to the original continuation */
740: pfm_$signal(status);
741: /*NOTREACHED*/
742: }
743: return(ckcmai(argc, argv));
744: }
745: #endif /* aegis */
746:
747: /* ANSI-style prototypes for internal functions. */
748: /* Functions used outside this module are prototyped in ckcker.h. */
749:
750: #ifdef apollo
751: _PROTOTYP( SIGTYP timerh, () );
752: _PROTOTYP( SIGTYP cctrap, () );
753: _PROTOTYP( SIGTYP esctrp, () );
754: _PROTOTYP( SIGTYP sig_ign, () );
755: #else
756: _PROTOTYP( SIGTYP timerh, (int) );
757: _PROTOTYP( SIGTYP cctrap, (int) );
758: _PROTOTYP( SIGTYP esctrp, (int) );
759: #endif /* apollo */
760: _PROTOTYP( int do_open, (char *) );
761: _PROTOTYP( int ttrpid, (char *) );
762: _PROTOTYP( static int ttlock, (char *) );
763: _PROTOTYP( static int ttunlck, (void) );
764: _PROTOTYP( int mygetbuf, (void) );
765: _PROTOTYP( int myfillbuf, (void) );
766: _PROTOTYP( VOID conbgt, (void) );
767: #ifdef ACUCNTRL
768: _PROTOTYP( VOID acucntrl, (char *, char *) );
769: #endif /* ACUCNTRL */
770:
771: #ifdef ATTSV
772: _PROTOTYP( int carrctl, (struct termio *, int) );
773: #else
774: #ifdef POSIX
775: _PROTOTYP( int carrctl, (struct termios *, int) );
776: #else
777: _PROTOTYP( int carrctl, (struct sgttyb *, int) );
778: #endif /* POSIX */
779: #endif /* ATTSV */
780:
781: #ifdef ATT7300
782: _PROTOTYP( int attdial, (char *, long, char *) );
783: _PROTOTYP( int offgetty, (char *) );
784: _PROTOTYP( int ongetty, (char *) );
785: #endif /* ATT7300 */
786:
787: #ifdef CK_ANSIC
788: static char *
789: xxlast(char *s, char c)
790: #else
791: static char *
792: xxlast(s,c) char *s; char c;
793: #endif /* CK_ANSIC */
794: /* xxlast */ { /* Last occurrence of character c in string s. */
795: int i;
796: for (i = (int)strlen(s); i > 0; i--)
797: if ( s[i-1] == c ) return( s + (i - 1) );
798: return(NULL);
799: }
800:
801: /* Timeout handler for communication line input functions */
802:
803: SIGTYP
804: timerh(foo) int foo; {
805: ttimoff();
806: longjmp(sjbuf,1);
807: }
808:
809: /* Control-C trap for communication line input functions */
810:
811: int cc_int; /* Flag */
812: SIGTYP (* occt)(); /* For saving old SIGINT handler */
813:
814: SIGTYP
815: cctrap(foo) int foo; { /* Needs arg for ANSI C */
816: cc_int = 1; /* signal() prototype. */
817: return;
818: }
819:
820: /* S Y S I N I T -- System-dependent program initialization. */
821:
822: int
823: sysinit() {
824: int x;
825:
826: conbgt(); /* See if we're in the background */
827: congm(); /* Get console modes */
828:
829: #ifdef ultrix
830: gtty(0,&vanilla); /* Get sgtty info */
831: iniflags = fcntl(0,F_GETFL,0); /* Get flags */
832: #else
833: #ifdef AUX
834: set42sig(); /* Don't ask! ([email protected]) */
835: #endif /* AUX */
836: #endif /* ultrix */
837:
838: /* Initialize the setuid package. */
839: /* Change to the user's real user and group id. */
840: /* If this can't be done, don't run at all. */
841:
842: if (x = priv_ini()) {
843: if (x | 1) fprintf(stderr,"Fatal: setuid failure.\n");
844: if (x | 2) fprintf(stderr,"Fatal: setgid failure.\n");
845: if (x | 4) fprintf(stderr,"Fatal: C-Kermit setuid to root!\n");
846: exit(1);
847: }
848: return(0);
849: }
850:
851: /* S Y S C L E A N U P -- System-dependent program cleanup. */
852:
853: int
854: syscleanup() {
855: #ifdef ultrix
856: stty(0,&vanilla); /* Get sgtty info */
857: fcntl(0,F_SETFL,iniflags); /* Restore flags */
858: #endif /* ultrix */
859: /* No need to call anything in the suid package here, right? */
860: return(0);
861: }
862:
863: /*
864: Major change in 5A(174). We used to use LPASS8, if it was defined, in all
865: versions except ENCORE, to allow 8-bit data and Xon/Xoff flow control at the
866: same time. But this LPASS8 business seems to have been causing trouble for
867: everybody but me! For example, Annex terminal servers, commonly used with
868: Encore computers, do not support LPASS8 even though the Encore itself does.
869: Now, reportedly, even vanilla 4.3 BSD systems can't do this. So let's turn
870: it off for everybody. That means we goes back to using
871: raw mode, with no flow control. Phooey.
872: */
873: #ifdef LPASS8
874: #undef LPASS8
875: #endif /* LPASS8 */
876:
877: /* T T O P E N -- Open a tty for exclusive access. */
878:
879: /*
880: Call with:
881: ttname: character string - device name or network host name.
882: lcl:
883: If called with lcl < 0, sets value of lcl as follows:
884: 0: the terminal named by ttname is the job's controlling terminal.
885: 1: the terminal named by ttname is not the job's controlling terminal.
886: But watch out: if a line is already open, or if requested line can't
887: be opened, then lcl remains (and is returned as) -1.
888: modem:
889: Less than zero: ttname is a network host name.
890: Zero or greater: ttname is a terminal device name.
891: Zero means a local connection (don't use modem signals).
892: Positive means use modem signals.
893: timo:
894: 0 = no timer.
895: nonzero = number of seconds to wait for open() to return before timing out.
896:
897: Returns:
898: 0 on success
899: -5 if device is in use
900: -4 if access to device is denied
901: -3 if access to lock directory denied
902: -2 upon timeout waiting for device to open
903: -1 on other error
904: */
905: static int ttotmo = 0; /* Timeout flag */
906: /* Flag kept here to avoid being clobbered by longjmp. */
907:
908: int
909: ttopen(ttname,lcl,modem,timo) char *ttname; int *lcl, modem, timo; {
910:
911: #ifdef SVORPOSIX
912: #ifndef CIE
913: extern char *ctermid(); /* Wish they all had this! */
914: #else /* CIE Regulus */
915: #define ctermid(x) strcpy(x,"")
916: #endif /* CIE */
917: #endif /* SVORPOSIX */
918:
919: char *x; /* what's this ? */
920:
921: #ifndef MINIX
922: extern char* ttyname();
923: #endif /* MINIX */
924: char cname[DEVNAMLEN+4];
925:
926: #define NAMEFD /* Feature to allow name to be an open file descriptor */
927:
928: #ifdef NAMEFD
929: int i, j; char *p;
930:
931: debug(F101,"ttopen telnetfd","",telnetfd);
932: #endif /* NAMEFD */
933:
934: debug(F111,"ttopen entry modem",ttname,modem);
935: debug(F101," ttyfd","",ttyfd);
936: debug(F101," lcl","",*lcl);
937:
938: if (ttyfd > -1) { /* if device already opened */
939: if (strncmp(ttname,ttnmsv,DEVNAMLEN)) /* are new & old names equal? */
940: ttclos(ttyfd); /* no, close old ttname, open new */
941: else /* else same, ignore this call, */
942: return(0); /* and return. */
943: }
944:
945: #ifdef NETCONN
946: if (modem < 0) { /* modem < 0 = special code for net */
947: int x;
948: ttmdm = modem;
949: modem = -modem; /* Positive network type number */
950: fdflag = 0; /* Stdio not redirected. */
951: netconn = 1; /* And it's a network connection */
952: debug(F111,"ttopen net",ttname,modem);
953: #ifdef NAMEFD
954: for (p = ttname; isdigit(*p); p++) ; /* Check for all digits */
955: if (*p == '\0') {
956: ttyfd = atoi(ttname); /* Is there a way to test it's open? */
957: ttfdflg = 1; /* We got an open file descriptor */
958: debug(F111,"ttopen got open network fd",ttname,ttyfd);
959: strncpy(ttnmsv,ttname,DEVNAMLEN); /* Remember the "name". */
960: x = 1; /* Return code is "good". */
961: if (telnetfd) {
962: ttnet = NET_TCPB;
963: ttnproto = NP_TELNET;
964: #ifdef SUNX25
965: } else if (x25fd) {
966: ttnet = NET_SX25;
967: ttnproto = NP_NONE;
968: #endif /* SUNX25 */
969: }
970: } else { /* Host name or address given */
971: #endif /* NAMEFD */
972: x = netopen(ttname, lcl, modem); /* (see ckcnet.h) */
973: if (x > -1) {
974: strncpy(ttnmsv,ttname,DEVNAMLEN);
975: } else netconn = 0;
976: #ifdef NAMEFD
977: }
978: #endif /* NAMEFD */
979:
980: #ifdef sony_news /* Sony NEWS */
981: if (ioctl(ttyfd,TIOCKGET,&km_ext) < 0) { /* Get Kanji mode */
982: perror("ttopen error getting Kanji mode (network)");
983: debug(F111,"ttopen error getting Kanji mode","network",0);
984: km_ext = -1; /* Make sure this stays undefined. */
985: }
986: #endif /* sony_news */
987:
988: xlocal = *lcl = 1; /* Network connections are local. */
989: debug(F101,"ttopen net x","",x);
990:
991: if (x > -1 && !x25fd)
992: x = tn_ini(); /* Initialize TELNET protocol */
993: return(x);
994: } else { /* Terminal device */
995: #endif /* NETCONN */
996:
997: #ifdef NAMEFD
998: /*
999: This code lets you give Kermit an open file descriptor for a serial
1000: communication device, rather than a device name. Kermit assumes that the
1001: line is already open, locked, conditioned with the right parameters, etc.
1002: */
1003: for (p = ttname; isdigit(*p); p++) ; /* Check for all digits */
1004: if (*p == '\0') {
1005: ttyfd = atoi(ttname); /* Is there a way to test it's open? */
1006: debug(F111,"ttopen got open fd",ttname,ttyfd);
1007: strncpy(ttnmsv,ttname,DEVNAMLEN); /* Remember the "name". */
1008: xlocal = *lcl = 1; /* Assume it's local. */
1009: netconn = 0; /* Assume it's not a network. */
1010: tvtflg = 0; /* Might need to initialize modes. */
1011: ttmdm = modem; /* Remember modem type. */
1012: fdflag = 0; /* Stdio not redirected. */
1013: ttfdflg = 1; /* Flag we were opened this way. */
1014:
1015: #ifdef sony_news /* Sony NEWS */
1016: /* Get device Kanji mode */
1017: if (ioctl(ttyfd,TIOCKGET,&km_ext) < 0) {
1018: perror("ttopen error getting Kanji mode");
1019: debug(F101,"ttopen error getting Kanji mode","",0);
1020: km_ext = -1; /* Make sure this stays undefined. */
1021: }
1022: #endif /* sony_news */
1023: return(0); /* Return success */
1024: }
1025: #endif /* NAMEFD */
1026: #ifdef NETCONN
1027: }
1028: #endif /* NETCONN */
1029:
1030: /* Here we have to open a serial device of the given name. */
1031:
1032: occt = signal(SIGINT, cctrap); /* Set Control-C trap, save old one */
1033:
1034: tvtflg = 0; /* Flag for use by ttvt(). */
1035: /* 0 = ttvt not called yet for this device */
1036:
1037: fdflag = (!isatty(0) || !isatty(1)); /* Flag for stdio redirected */
1038: debug(F101,"ttopen fdflag","",fdflag);
1039:
1040: ttmdm = modem; /* Make this available to other fns */
1041: xlocal = *lcl; /* Make this available to other fns */
1042:
1043: /* Code for handling bidirectional tty lines goes here. */
1044: /* Use specified method for turning off logins and suppressing getty. */
1045:
1046: #ifdef ACUCNTRL
1047: /* Should put call to priv_on() here, but that would be very risky! */
1048: acucntrl("disable",ttname); /* acucntrl() program. */
1049: /* and priv_off() here... */
1050: #else
1051: #ifdef ATT7300
1052: if ((attmodem & DOGETY) == 0) /* offgetty() program. */
1053: attmodem |= offgetty(ttname); /* Remember response. */
1054: #endif /* ATT7300 */
1055: #endif /* ACUCNTRL */
1056:
1057: /*
1058: In the following section, we open the tty device for read/write.
1059: If a modem has been specified via "set modem" prior to "set line"
1060: then the O_NDELAY parameter is used in the open, provided this symbol
1061: is defined (e.g. in fcntl.h), so that the program does not hang waiting
1062: for carrier (which in most cases won't be present because a connection
1063: has not been dialed yet). O_NDELAY is removed later on in ttopen(). It
1064: would make more sense to first determine if the line is local before
1065: doing this, but because ttyname() requires a file descriptor, we have
1066: to open it first. See do_open().
1067:
1068: Now open the device using the desired treatment of carrier.
1069: If carrier is REQUIRED, then open could hang forever, so an optional
1070: timer is provided. If carrier is not required, the timer should never
1071: go off, and should do no harm...
1072: */
1073: ttotmo = 0; /* Flag no timeout */
1074: saval = signal(SIGALRM,timerh); /* Timed, set up timer. */
1075: if (timo > 0) {
1076: alarm(timo); /* Timed open() */
1077: if (setjmp(sjbuf)) {
1078: ttotmo = 1; /* Flag timeout. */
1079: } else ttyfd = do_open(ttname);
1080: ttimoff();
1081: debug(F111,"ttopen","modem",modem);
1082: debug(F101," ttyfd","",ttyfd);
1083: debug(F101," alarm return","",ttotmo);
1084: } else ttyfd = do_open(ttname);
1085: debug(F111,"ttopen ttyfd",ttname,ttyfd);
1086: if (ttyfd < 0) { /* If couldn't open, fail. */
1087: #ifdef ATT7300
1088: if (attmodem & DOGETY) /* was getty(1m) running before us? */
1089: ongetty(ttnmsv); /* yes, restart on tty line */
1090: attmodem &= ~DOGETY; /* no phone in use, getty restored */
1091: #else
1092: #if ACUCNTRL
1093: /* Should put call to priv_on() here, but that would be risky! */
1094: acucntrl("enable",ttname); /* acucntrl() program. */
1095: /* and priv_off() here... */
1096: #endif /* ACUNTRL */
1097: #endif /* ATT7300 */
1098:
1099: signal(SIGINT,occt); /* Put old Ctrl-C trap back. */
1100: if (errno == EACCES) { /* Device is protected against user */
1101: perror(ttname); /* Print message */
1102: debug(F111,"ttopen tty access denied",ttname,errno);
1103: return(-4);
1104: } else return(ttotmo ? -2 : -1);
1105: }
1106:
1107: /* Make sure it's a real tty. */
1108: if (!isatty(ttyfd)) {
1109: fprintf(stderr,"%s is not a tty!\n",ttname);
1110: debug(F110,"ttopen not a tty",ttname,0);
1111: close(ttyfd);
1112: ttyfd = -1;
1113: signal(SIGINT,occt);
1114: return(-1);
1115: }
1116:
1117: #ifdef aegis
1118: /* Apollo C runtime claims that console pads are tty devices, which
1119: * is reasonable, but they aren't any good for packet transfer. */
1120: ios_$inq_type_uid((short)ttyfd, ttyuid, st);
1121: if (st.all != status_$ok) {
1122: fprintf(stderr, "problem getting tty object type: ");
1123: error_$print(st);
1124: } else if (ttyuid != sio_$uid) { /* reject non-SIO lines */
1125: close(ttyfd); ttyfd = -1;
1126: errno = ENOTTY; perror(ttname);
1127: signal(SIGINT,occt);
1128: return(-1);
1129: }
1130: #endif /* aegis */
1131:
1132: strncpy(ttnmsv,ttname,DEVNAMLEN); /* Keep copy of name locally. */
1133:
1134: /* Caller wants us to figure out if line is controlling tty */
1135:
1136: if (*lcl < 0) {
1137: int x0 = 0, x1 = 0;
1138: if (strcmp(ttname,CTTNAM) == 0) { /* "/dev/tty" always remote */
1139: xlocal = 0;
1140: debug(F111," ttname=CTTNAM",ttname,xlocal);
1141:
1142: /* If any of 0, 1, or 2 not redirected, we can use ttyname() to get */
1143: /* the name of the controlling terminal... */
1144:
1145: } else if ((x0 = isatty(0)) || (x1 = isatty(1)) || isatty(2)) {
1146: #ifndef MINIX
1147: if (x0)
1148: x = ttyname(0); /* and compare it with the */
1149: else if (x1) /* tty device name. */
1150: x = ttyname(1);
1151: else x = ttyname(2);
1152: strncpy(cname,x,DEVNAMLEN); /* (copy from internal static buf) */
1153: debug(F110," cname",x,0);
1154: x = ttyname(ttyfd); /* Gat real name of ttname. */
1155: xlocal = (strncmp(x,cname,DEVNAMLEN) == 0) ? 0 : 1; /* Compare. */
1156: debug(F111," ttyname",x,xlocal);
1157: #else
1158: xlocal = 1; /* Can't do this test in MINIX */
1159: #endif /* MINIX */
1160: } else { /* Else, if stdin redirected... */
1161: #ifdef SVORPOSIX
1162: /* System V provides nice ctermid() function to get name of controlling tty */
1163: ctermid(cname); /* Get name of controlling terminal */
1164: debug(F110," ctermid",cname,0);
1165: x = ttyname(ttyfd); /* Compare with name of comm line. */
1166: xlocal = (strncmp(x,cname,DEVNAMLEN) == 0) ? 0 : 1;
1167: debug(F111," ttyname",x,xlocal);
1168: #else
1169: /* Just assume local */
1170: xlocal = 1;
1171: #endif /* SVORPOSIX */
1172: debug(F101," redirected stdin","",xlocal);
1173: }
1174: }
1175:
1176: /* Note, the following code was added so that Unix "idle-line" snoopers */
1177: /* would not think Kermit was idle when it was transferring files, and */
1178: /* maybe log people out. */
1179: if (xlocal == 0) { /* Remote mode */
1180: if (fdflag == 0) { /* Standard i/o is not redirected */
1181: debug(F100,"ttopen setting ttyfd = 0","",0);
1182: close(ttyfd); /* Use file descriptor 0 */
1183: ttyfd = 0;
1184: } else { /* Standard i/o is redirected */
1185: debug(F101,"ttopen stdio redirected","",ttyfd);
1186: }
1187: }
1188:
1189: /* Now check if line is locked -- if so fail, else lock for ourselves */
1190: /* Note: After having done this, don't forget to delete the lock if you */
1191: /* leave ttopen() with an error condition. */
1192:
1193: lkf = 0; /* Check lock */
1194: if (xlocal > 0) {
1195: int xx; int xpid;
1196: if ((xx = ttlock(ttname)) < 0) { /* Can't lock it. */
1197: debug(F111,"ttopen ttlock fails",ttname,xx);
1198: close(ttyfd); /* Close the device. */
1199: ttyfd = -1; /* Erase its file descriptor. */
1200: signal(SIGINT,occt); /* Put old SIGINT back. */
1201: if (xx == -2) { /* If lockfile says tty is in use, */
1202: char *p = malloc(200); /* print an ls -l listing */
1203: if (p) { /* if we can get space... */
1204: sprintf(p,"/bin/ls -l %s",flfnam);
1205: zsyscmd(p); /* Get listing. */
1206: free(p); /* free the space */
1207: xpid = ttrpid(flfnam); /* Try to read pid from lockfile */
1208: priv_off(); /* Turn privs back off. */
1209: if (xpid > -1) printf("pid = %d\n",xpid); /* show pid */
1210: }
1211: return(-5); /* Code for device in use */
1212: } else return(-3); /* Access denied */
1213: } else lkf = 1;
1214: }
1215:
1216: /* Got the line, now set the desired value for local. */
1217:
1218: if (*lcl != 0) *lcl = xlocal;
1219:
1220: /* Some special stuff for v7... */
1221:
1222: #ifdef V7
1223: #ifndef MINIX
1224: if (kmem[TTY] < 0) { /* If open, then skip this. */
1225: qaddr[TTY] = initrawq(ttyfd); /* Init the queue. */
1226: if ((kmem[TTY] = open("/dev/kmem", 0)) < 0) {
1227: fprintf(stderr, "Can't read /dev/kmem in ttopen.\n");
1228: perror("/dev/kmem");
1229: exit(1);
1230: }
1231: }
1232: #endif /* !MINIX */
1233: #endif /* V7 */
1234:
1235: /* No failure returns after this point */
1236:
1237: #ifdef ultrix
1238: #ifdef TIOCSINUSE
1239: if (xlocal && ioctl(ttyfd, TIOCSINUSE, NULL) < 0) {
1240: fprintf(stderr, "Can't set in-use flag on modem.\n");
1241: perror("TIOCSINUSE");
1242: }
1243: #endif /* TIOCSINUSE */
1244: #endif /* ultrix */
1245:
1246: /* Get tty device settings */
1247:
1248: #ifdef ATTSV /* AT&T UNIX */
1249: ioctl(ttyfd,TCGETA,&ttold);
1250: debug(F101,"ttopen ioctl TCGETA ttold.c_lflag","",ttold.c_lflag);
1251: ioctl(ttyfd,TCGETA,&ttraw);
1252: ioctl(ttyfd,TCGETA,&tttvt);
1253: #else
1254: #ifdef POSIX /* POSIX */
1255: tcgetattr(ttyfd,&ttold);
1256: debug(F101,"ttopen tcgetattr ttold.c_lflag","",ttold.c_lflag);
1257: tcgetattr(ttyfd,&ttraw);
1258: tcgetattr(ttyfd,&tttvt);
1259: #else /* BSD, V7, and all others */
1260: gtty(ttyfd,&ttold);
1261: debug(F101,"ttopen gtty ttold.sg_flags","",ttold.sg_flags);
1262:
1263: #ifdef sony_news /* Sony NEWS */
1264: if (ioctl(ttyfd,TIOCKGET,&km_ext) < 0) { /* Get console Kanji mode */
1265: perror("ttopen error getting Kanji mode");
1266: debug(F101,"ttopen error getting Kanji mode","",0);
1267: km_ext = -1; /* Make sure this stays undefined. */
1268: }
1269: #endif /* sony_news */
1270:
1271: #ifdef TIOCGETC
1272: tcharf = 0; /* In remote mode, also get */
1273: if (xlocal == 0) { /* special characters */
1274: if (ioctl(ttyfd,TIOCGETC,&tchold) < 0) {
1275: debug(F100,"ttopen TIOCGETC failed","",0);
1276: } else {
1277: tcharf = 1; /* It worked. */
1278: ioctl(ttyfd,TIOCGETC,&tchnoi); /* Get another copy */
1279: debug(F100,"ttopen TIOCGETC ok","",0);
1280: }
1281: }
1282: #else
1283: debug(F100,"ttopen TIOCGETC not defined","",0);
1284: #endif /* TIOCGETC */
1285:
1286: #ifdef TIOCGLTC
1287: ltcharf = 0; /* In remote mode, also get */
1288: if (xlocal == 0) { /* local special characters */
1289: if (ioctl(ttyfd,TIOCGLTC,<chold) < 0) {
1290: debug(F100,"ttopen TIOCGLTC failed","",0);
1291: } else {
1292: ltcharf = 1; /* It worked. */
1293: ioctl(ttyfd,TIOCGLTC,<chnoi); /* Get another copy */
1294: debug(F100,"ttopen TIOCGLTC ok","",0);
1295: }
1296: }
1297: #else
1298: debug(F100,"ttopen TIOCGLTC not defined","",0);
1299: #endif /* TIOCGLTC */
1300:
1301: #ifdef TIOCLGET
1302: lmodef = 0;
1303: if (ioctl(ttyfd,TIOCLGET,&lmode) < 0) {
1304: debug(F100,"ttopen TIOCLGET failed","",0);
1305: } else {
1306: lmodef = 1;
1307: debug(F100,"ttopen TIOCLGET ok","",0);
1308: }
1309: #endif /* TIOCLGET */
1310:
1311: gtty(ttyfd,&ttraw); /* And a copy of it for packets*/
1312: gtty(ttyfd,&tttvt); /* And one for virtual tty service */
1313:
1314: #endif /* POSIX */
1315: #endif /* ATTSV */
1316:
1317: /* Section for changing line discipline. It's restored in ttres(). */
1318:
1319: #ifdef BSD41
1320: /* For 4.1BSD only, force "old" tty driver, new one botches TANDEM. */
1321: { int k;
1322: ioctl(ttyfd, TIOCGETD, &ttld); /* Get and save line discipline */
1323: debug(F101,"4.1bsd line discipline","",ttld);
1324: k = OTTYDISC; /* Switch to "old" discipline */
1325: k = ioctl(ttyfd, TIOCSETD, &k);
1326: debug(F101,"4.1bsd tiocsetd","",k);
1327: }
1328: #endif /* BSD41 */
1329:
1330: #ifdef aegis
1331: /* This was previously done before the last two TCGETA or gtty above,
1332: * in both the ATTSV and not-ATTSV case. If it is not okay to have only
1333: * one copy if it here instead, give us a shout!
1334: */
1335: sio_$control((short)ttyfd, sio_$raw_nl, false, st);
1336: if (xlocal) { /* ignore breaks from local line */
1337: sio_$control((short)ttyfd, sio_$int_enable, false, st);
1338: sio_$control((short)ttyfd, sio_$quit_enable, false, st);
1339: }
1340: #endif /* aegis */
1341:
1342: #ifdef VXVE
1343: ttraw.c_line = 0; /* STTY line 0 for VX/VE */
1344: tttvt.c_line = 0; /* STTY line 0 for VX/VE */
1345: ioctl(ttyfd,TCSETA,&ttraw);
1346: #endif /* vxve */
1347:
1348: /* If O_NDELAY was used during open(), then remove it now. */
1349:
1350: #ifdef O_NDELAY
1351: if (fcntl(ttyfd, F_GETFL, 0) & O_NDELAY) {
1352:
1353: #ifndef aegis
1354: if (fcntl(ttyfd,F_SETFL, fcntl(ttyfd, F_GETFL, 0) & ~O_NDELAY) < 0 )
1355: perror("Can't unset O_NDELAY");
1356: #endif /* aegis */
1357: /* Some systems, notably Xenix (don't know how common this is in
1358: * other systems), need special treatment to get rid of the O_NDELAY
1359: * behaviour on read() with respect to carrier presence (i.e. read()
1360: * returning 0 when carrier absent), even though the above fcntl()
1361: * is enough to make read() wait for input when carrier is present.
1362: * This magic, in turn, requires CLOCAL for working when the carrier
1363: * is absent. But if xlocal == 0, presumably you already have CLOCAL
1364: * or you have a carrier, otherwise you wouldn't be running this.
1365: */
1366: #ifdef ATTSV
1367: if (xlocal) {
1368: ttraw.c_cflag |= CLOCAL;
1369: ioctl(ttyfd, TCSETA, &ttraw);
1370: }
1371: #endif /* ATTSV */
1372: #ifndef SCO3R2
1373: /* Reportedly lets uugetty grab the device in SCO UNIX 3.2 / XENIX 2.3 */
1374: close( priv_opn(ttname, O_RDWR) ); /* Magic to force change. */
1375: #endif /* SCO3R2 */
1376: }
1377: #endif /* O_NDELAY */
1378:
1379: /* Instruct the system how to treat the carrier, and set a few other tty
1380: * parameters.
1381: *
1382: * This also undoes the temporary setting of CLOCAL that may have been done
1383: * for the close(open()) above (except in Xenix). Also throw in ~ECHO, to
1384: * prevent the other end of the line from sitting there talking to itself,
1385: * producing garbage when the user performs a connect.
1386: *
1387: * SCO Xenix unfortunately seems to ignore the actual state of CLOCAL.
1388: * Now it thinks CLOCAL is always on. It seems the only real solution for
1389: * Xenix is to switch between the lower and upper case device names.
1390: *
1391: * This section may at some future time expand into setting a complete
1392: * collection of tty parameters, or call a function shared with ttpkt()/
1393: * ttvt() that does so. On the other hand, the initial parameters are not
1394: * that important, since ttpkt() or ttvt() should always fix that before
1395: * any communication is done. Well, we'll see...
1396: */
1397: if (xlocal) {
1398: curcarr = -2;
1399: carrctl(&ttraw, ttcarr == CAR_ON);
1400:
1401: #ifdef SVORPOSIX
1402: ttraw.c_lflag &= ~ECHO;
1403: ttold.c_lflag &= ~ECHO;
1404: #ifdef ATTSV
1405: ioctl(ttyfd, TCSETA, &ttraw);
1406: #else
1407: tcsetattr(ttyfd, TCSADRAIN, &ttraw);
1408: #endif /* ATTSV */
1409:
1410: #else /* BSD, etc */
1411: ttraw.sg_flags &= ~ECHO;
1412: ttold.sg_flags &= ~ECHO;
1413: stty(ttyfd,&ttraw);
1414: #endif /* SVORPOSIX */
1415: /* ttflui(); This fails some reason */
1416: }
1417:
1418: /* Get current speed */
1419:
1420: ttspeed = ttgspd();
1421: debug(F101,"ttopen ttspeed","",ttspeed);
1422:
1423: /* Done, make entries in debug log, restore Ctrl-C trap, and return. */
1424:
1425: debug(F101,"ttopen, ttyfd","",ttyfd);
1426: debug(F101," lcl","",*lcl);
1427: debug(F111," lock file",flfnam,lkf);
1428: signal(SIGINT,occt);
1429: return(0);
1430: }
1431:
1432:
1433: /* D O _ O P E N -- Do the right kind of open() call for the tty. */
1434:
1435: int
1436: do_open(ttname) char *ttname; {
1437:
1438: #ifndef O_NDELAY /* O_NDELAY not defined */
1439: return(priv_opn(ttname,2));
1440: #else /* O_NDELAY defined */
1441:
1442: #ifdef ATT7300
1443: /*
1444: Open comms line without waiting for carrier so initial call does not hang
1445: because state of "modem" is likely unknown at the initial call -jrd.
1446: If this is needed for the getty stuff to work, and the open would not work
1447: without O_NDELAY when getty is still on, then this special case is ok.
1448: Otherwise, get rid of it. -ske
1449: */
1450: return(priv_opn(ttname, O_RDWR | O_NDELAY));
1451:
1452: #else /* !ATT7300 */
1453:
1454: /* Normal case. Use O_NDELAY according to SET CARRIER. See ttscarr(). */
1455:
1456: return(priv_opn(ttname, O_RDWR | ((ttcarr != CAR_ON) ? O_NDELAY : 0) ));
1457:
1458: #endif /* !ATT7300 */
1459: #endif /* O_NDELAY */
1460: }
1461:
1462: /* T T C L O S -- Close the TTY, releasing any lock. */
1463:
1464: int
1465: ttclos(foo) int foo; { /* Arg req'd for signal() prototype */
1466: int x = 0;
1467:
1468: debug(F101,"ttclos ttyfd","",ttyfd);
1469: if (ttyfd < 0) return(0); /* Wasn't open. */
1470:
1471: if (ttfdflg) return(0); /* If we got ttyfd from another */
1472: /* process, don't close it. */
1473: tvtflg = 0;
1474: #ifdef NETCONN
1475: if (netconn) { /* Network connection. */
1476: debug(F100,"ttclos closing net","",0);
1477: netclos(); /* Close it. */
1478: netconn = 0;
1479: return(0);
1480: }
1481: #endif /* NETCONN */
1482: #ifdef FT21
1483: if (xlocal) ioctl(ttyfd,TIOCHPCL, NULL);
1484: #endif /* FT21 */
1485: #ifdef ultrix
1486: if (xlocal) ioctl(ttyfd, TIOCNCAR, NULL);
1487: #endif /* ultrix */
1488: if (xlocal) {
1489: debug(F100,"ttclos about to call ttunlck","",0);
1490: if (ttunlck()) /* Release uucp-style lock */
1491: fprintf(stderr,"Warning, problem releasing lock\r\n");
1492: debug(F100,"ttclos about to call ttres","",0);
1493: }
1494: if (ttyfd > 0) {
1495: saval = signal(SIGALRM,timerh); /* Enable timer interrupt. */
1496: alarm(5); /* Allow 5 seconds for this. */
1497: if (setjmp(sjbuf)) { /* Timer went off? */
1498: x = -1;
1499: } else { /* What we're really trying to do */
1500: if (xlocal) {
1501: tthang(); /* Hang up first, then... */
1502: ttres(); /* reset device modes. */
1503: }
1504: debug(F101,"ttclos about to call close","",ttyfd);
1505: close(ttyfd); /* Close the device. */
1506: x = 1;
1507: }
1508: ttimoff(); /* Turn off timer. */
1509: if (x < 0) {
1510: fprintf(stderr,"?Timed out closing device: %s\n",ttnmsv);
1511: debug(F100,"ttclos timed out","",0);
1512: }
1513: }
1514: ttyfd = -1; /* Invalidate the file descriptor. */
1515: #ifdef sony_news
1516: km_ext = -1; /* Invalidate device's Kanji-mode */
1517: #endif /* sony_news */
1518:
1519: /* For bidirectional lines, restore getty if it was there before. */
1520:
1521: #ifdef ACUCNTRL /* 4.3BSD acucntrl() method. */
1522: acucntrl("enable",ttnmsv); /* Enable getty on the device. */
1523: #else
1524: #ifdef ATT7300 /* ATT UNIX PC (3B1, 7300) method. */
1525: if (attmodem & DOGETY) /* Was getty(1m) running before us? */
1526: ongetty(ttnmsv); /* Yes, restart getty on tty line */
1527: attmodem &= ~DOGETY; /* No phone in use, getty restored */
1528: #endif /* ATT7300 */
1529: #endif /* System-dependent getty-restoring methods */
1530:
1531: debug(F100,"ttclos done","",0);
1532: return(0);
1533: }
1534:
1535: /* T T H A N G -- Hangup phone line or network connection. */
1536: /*
1537: Returns:
1538: 0 if it does nothing.
1539: 1 if it believes that it hung up successfully.
1540: -1 if it believes that the hangup attempt failed.
1541: */
1542:
1543: #define HUPTIME 500 /* Milliseconds for hangup */
1544:
1545: int
1546: tthang() {
1547: int x = 0; /* Sometimes used as return code. */
1548: #ifndef POSIX
1549: int z; /* worker */
1550: #endif /* POSIX */
1551:
1552: #ifdef SVORPOSIX /* AT&T, POSIX, HPUX declarations. */
1553: int spdsav; /* for saving speed */
1554: #ifdef HPUX
1555: mflag dtr_down = 00000000000,
1556: modem_rtn;
1557: mflag modem_sav;
1558: char modem_state[64];
1559: #endif /* HPUX */
1560: int flags; /* fcntl flags */
1561: unsigned short ttc_save;
1562: #endif /* SVORPOSIX */
1563:
1564: if (ttyfd < 0) return(0); /* Don't do this if not open */
1565: if (xlocal < 1) return(0); /* Don't do this if not local */
1566:
1567: #ifdef NETCONN
1568: if (netconn) { /* Network connection. */
1569: if (netclos() < 0) return(-1); /* Close it */
1570: tvtflg = 0;
1571: ttyfd = -1;
1572: x = 1;
1573: if (netopen(ttnmsv, &x, ttmdm) < 0) /* Open it again */
1574: return(-1);
1575: else
1576: return(1);
1577: }
1578: #endif /* NETCONN */
1579:
1580: /* From here down, we handle real tty devices. */
1581:
1582: #ifdef POSIX
1583: /* Should add some error checking here... */
1584: spdsav = cfgetospeed(&ttcur); /* Get current speed */
1585: cfsetospeed(&ttcur,B0); /* Replace by 0 */
1586: tcsetattr(ttyfd,TCSADRAIN,&ttcur); /* Set it */
1587: msleep(HUPTIME); /* Sleep */
1588: cfsetospeed(&ttcur,spdsav); /* Restore previous speed */
1589: tcsetattr(ttyfd,TCSADRAIN,&ttcur);
1590: return(1);
1591: #endif /* POSIX */
1592:
1593: #ifdef aegis /* Apollo Aegis */
1594: sio_$control((short)ttyfd, sio_$dtr, false, st); /* DTR down */
1595: msleep(HUPTIME); /* pause */
1596: sio_$control((short)ttyfd, sio_$dtr, true, st); /* DTR up */
1597: return(1);
1598: #endif /* aegis */
1599:
1600: #ifdef ANYBSD /* Any BSD version. */
1601: debug(F100,"tthang BSD style","",0);
1602: if (ioctl(ttyfd,TIOCCDTR,0) < 0) { /* Clear DTR. */
1603: debug(F101,"tthang TIOCCDTR fails","",errno);
1604: return(-1);
1605: }
1606: msleep(HUPTIME); /* For about 1/2 sec */
1607: errno = 0;
1608: x = ioctl(ttyfd,TIOCSDTR,0); /* Restore DTR */
1609: if (x < 0) {
1610: /*
1611: For some reason, this tends to fail with "no such device or address"
1612: but the operation still works, probably because of the close/open
1613: later on. So let's not scare the user unnecessarily here.
1614: */
1615: debug(F101,"tthang TIOCSDTR errno","",errno); /* Log the error */
1616: x = 1; /* Pretend we succeeded */
1617: } else if (x == 0) x = 1; /* Success */
1618: #ifdef COMMENT
1619: #ifdef FT21
1620: ioctl(ttyfd, TIOCSAVEMODES, 0);
1621: ioctl(ttyfd, TIOCHPCL, 0);
1622: close(ttyfd); /* Yes, must do this twice */
1623: if ((ttyfd = open(ttnmsv,2)) < 0) /* on Fortune computers... */
1624: return(-1); /* (but why?) */
1625: else x = 1;
1626: #endif /* FT21 */
1627: #endif /* COMMENT */
1628: close(do_open(ttnmsv)); /* Clear i/o error condition */
1629: errno = 0;
1630: #ifdef COMMENT
1631: /* This is definitely dangerous. Why was it here? */
1632: z = ttvt(ttspeed,ttflow); /* Restore modes. */
1633: debug(F101,"tthang ttvt returns","",z);
1634: return(z < 0 ? -1 : 1);
1635: #else
1636: return(x);
1637: #endif /* COMMENT */
1638: #endif /* ANYBSD */
1639:
1640: #ifdef ATTSV
1641: /* AT&T UNIX section, includes HP-UX and generic AT&T System III/V... */
1642:
1643: #ifdef HPUX
1644: /* Hewlett Packard allows explicit manipulation of modem signals. */
1645:
1646: #ifdef COMMENT
1647: /* Old way... */
1648: debug(F100,"tthang HP-UX style","",0);
1649: if (ioctl(ttyfd,MCSETAF,&dtr_down) < 0) /* lower DTR */
1650: return(-1); /* oops, can't. */
1651: msleep(HUPTIME); /* Pause half a second. */
1652: x = 1; /* Set return code */
1653: if (ioctl(ttyfd,MCGETA,&modem_rtn) > -1) { /* Get line status. */
1654: if ((modem_rtn & MDCD) != 0) /* Check if CD is low. */
1655: x = -1; /* CD didn't drop, fail. */
1656: } else x = -1;
1657:
1658: /* Even if above calls fail, RTS & DTR should be turned back on. */
1659: modem_rtn = MRTS | MDTR;
1660: if (ioctl(ttyfd,MCSETAF,&modem_rtn) < 0) x = -1;
1661: return(x);
1662: #else
1663: /* New way, from Hellmuth Michaelis */
1664: debug(F100,"tthang HP-UX style, HPUXDEBUG","",0);
1665: if (ioctl(ttyfd,MCGETA,&modem_rtn) == -1) { /* Get current status. */
1666: debug(F100,"tthang HP-UX: can't get modem lines, NO HANGUP!","",0);
1667: return(-1);
1668: }
1669: sprintf(modem_state,"%#lx",modem_rtn);
1670: debug(F110,"tthang HP-UX: modem lines got = ",modem_state,0);
1671: modem_sav = modem_rtn; /* save line status */
1672: modem_rtn &= ~MDTR; /* DTR bit down */
1673: sprintf(modem_state,"%#lx",modem_rtn);
1674: debug(F110,"tthang HP-UX: modem lines lowerd DTR = ",modem_state,0);
1675: if (ioctl(ttyfd,MCSETAF,&modem_rtn) < 0) { /* lower DTR */
1676: debug(F100,"tthang HP-UX: can't lower DTR!","",0);
1677: return(-1); /* oops, can't. */
1678: }
1679: msleep(HUPTIME); /* Pause half a second. */
1680: x = 1; /* Set return code */
1681: if (ioctl(ttyfd,MCGETA,&modem_rtn) > -1) { /* Get line status. */
1682: sprintf(modem_state,"%#lx",modem_rtn);
1683: debug(F110,"tthang HP-UX: modem lines got = ",modem_state,0);
1684: if ((modem_rtn & MDCD) != 0) { /* Check if CD is low. */
1685: debug(F100,"tthang HP-UX: DCD didn't get down!","",0);
1686: x = -1; /* CD didn't drop, fail. */
1687: } else {
1688: debug(F100,"tthang HP-UX: DCD down!","",0);
1689: }
1690: } else {
1691: x = -1;
1692: debug(F100,"tthang HP-UX: can't get DCD status !","",0);
1693: }
1694:
1695: /* Even if above calls fail, RTS & DTR should be turned back on. */
1696:
1697: modem_sav |= (MRTS | MDTR);
1698: if (ioctl(ttyfd,MCSETAF,&modem_sav) < 0) {
1699: x = -1;
1700: debug(F100,"tthang HP-UX: can't set saved state |=(RTS | DTR)","",0);
1701: } else {
1702: sprintf(modem_state,"%#lx",modem_sav);
1703: debug(F110,"tthang HP-UX: final modem lines = ",modem_state,0);
1704: }
1705: return(x);
1706: #endif /* COMMENT */
1707:
1708: #else /* AT&T but not HP-UX */
1709:
1710: /* SVID for AT&T System V R3 defines ioctl's for handling modem signals. */
1711: /* It is not known how many, if any, systems actually implement them, */
1712: /* so we include them here in ifdef's. */
1713:
1714: #ifdef TIOCMBIS /* Bit Set */
1715: #ifdef TIOCMBIC /* Bit Clear */
1716: #ifdef TIOCM_DTR /* DTR */
1717:
1718: /* Clear DTR, sleep 300 msec, turn it back on. */
1719: /* If any of the ioctl's return failure, go on to the next section. */
1720:
1721: z = TIOCM_DTR; /* Code for DTR. */
1722: #ifdef TIOCM_RTS /* Lower RTS too if symbol is known. */
1723: #ifndef _IBMR2 /* Don't do this on RS/6000... */
1724: z |= TIOCM_RTS;
1725: #endif /* _IBMR2 */ /* or DTR will never come up again. */
1726: #endif /* TIOCM_RTS */
1727:
1728: debug(F101,"tthang TIOCM signal mask","",z);
1729: #ifndef _IBMR2
1730: /* SVID says the argument must be a pointer to an int. */
1731: if (ioctl(ttyfd,TIOCMBIC,&z) > -1)
1732: #else
1733: /* Reportedly, the RS/6000 requires an int, not a pointer. */
1734: if (ioctl(ttyfd,TIOCMBIC,z) > -1)
1735: #endif /* _IBMR2 */
1736: { /* Try to lower DTR. */
1737: debug(F100,"tthang TIOCMBIC ok","",0);
1738: msleep(HUPTIME); /* Pause half a second. */
1739: #ifndef _IBMR2
1740: if (ioctl(ttyfd,TIOCMBIS,&z) > -1) /* Try to turn it back on. */
1741: #else
1742: if (ioctl(ttyfd,TIOCMBIS,z) > -1)
1743: #endif /* _IBMR2 */
1744: {
1745: debug(F100,"tthang TIOCMBIS ok","",0);
1746: return(1); /* Success, done. */
1747: } else { /* Couldn't raise, continue. */
1748: debug(F101,"tthang TIOCMBIS errno","",errno);
1749: }
1750: } else { /* Couldn't lower, continue. */
1751: debug(F101,"tthang TIOCMBIC errno","",errno);
1752: }
1753: #endif /* TIOCM_DTR */
1754: #endif /* TIOCMBIC */
1755: #endif /* TIOCMBIS */
1756:
1757: /*
1758: General AT&T UNIX case, not HPUX. The following code is highly suspect. No
1759: two AT&T-based systems seem to do this the same way. The object is simply
1760: to turn off DTR and then turn it back on. SVID says the universal method
1761: for turning off DTR is to set the speed to zero, and this does seem to do
1762: the trick in all cases. But neither SVID nor any known man pages say how to
1763: turn DTR back on again. Some variants, like most Xenix implementations,
1764: raise DTR again when the speed is restored to a nonzero value. Others
1765: require the device to be closed and opened again, but this is risky because
1766: getty could seize the device during the instant it is closed.
1767: */
1768:
1769: /* Return code for ioctl failures... */
1770: #ifdef ATT6300
1771: x = 1; /* ATT6300 doesn't want to fail... */
1772: #else
1773: x = -1;
1774: #endif /* ATT6300 */
1775:
1776: debug(F100,"tthang get settings","",0);
1777: if (ioctl(ttyfd,TCGETA,&ttcur) < 0) /* Get current settings. */
1778: return(x); /* Fail if this doesn't work. */
1779: if ((flags = fcntl(ttyfd,F_GETFL,0)) < 0) /* Get device flags. */
1780: return(x);
1781: ttc_save = ttcur.c_cflag; /* Remember current speed. */
1782: spdsav = ttc_save & CBAUD;
1783: debug(F101,"tthang speed","",spdsav);
1784:
1785: #ifdef O_NDELAY
1786: debug(F100,"tthang O_NDELAY on","",0);
1787: fcntl(ttyfd, F_SETFL, flags | O_NDELAY); /* Activate O_NDELAY */
1788: #endif /* O_NDELAY */
1789:
1790: #ifdef ATT7300 /* This is the way it is SUPPOSED to work */
1791: ttcur.c_cflag &= ~CBAUD; /* Change the speed to zero. */
1792: #else
1793: #ifdef RTAIX
1794: ttcur.c_cflag &= ~CBAUD; /* Change the speed to zero. */
1795: #else /* This way really works but may be dangerous */
1796: #ifdef u3b2
1797: ttcur.c_cflag = ~(CBAUD|CLOCAL); /* Special for AT&T 3B2s */
1798: /* (CLOCAL must be OFF) */
1799: #else
1800: #ifdef SCO3R2 /* SCO UNIX 3.2 */
1801: /*
1802: This is complete nonsense, but an SCO user claimed this change made
1803: hanging up work. Comments from other SCO UNIX 3.2 users would be
1804: appreciated.
1805: */
1806: ttcur.c_cflag = CBAUD|B0;
1807: #else /* None of the above. */
1808: ttcur.c_cflag = CLOCAL|HUPCL; /* Change all but these to zero */
1809: /* (CLOCAL must be ON) */
1810: #endif /* SCO3R2 */
1811: #endif /* u3b2 */
1812: #endif /* RTAIX */
1813: #endif /* ATT7300 */
1814:
1815: #ifdef COMMENT
1816: /* and if none of those work, try one of these... */
1817: ttcur.c_cflag = 0;
1818: ttcur.c_cflag = CLOCAL;
1819: ttcur.c_cflag &= ~(CBAUD|HUPCL);
1820: ttcur.c_cflag &= ~(CBAUD|CREAD);
1821: ttcur.c_cflag &= ~(CBAUD|CREAD|HUPCL);
1822: /* or other combinations */
1823: #endif /* COMMENT */
1824:
1825: #ifdef TCXONC
1826: debug(F100,"tthang TCXONC","",0);
1827: ioctl(ttyfd, TCXONC, 1);
1828: #endif /* TCXONC */
1829:
1830: #ifdef TIOCSTART
1831: debug(F100,"tthang TIOCSTART","",0);
1832: ioctl(ttyfd, TIOCSTART, 0);
1833: #endif /* TIOCSTART */
1834:
1835: if (ioctl(ttyfd,TCSETAF,&ttcur) < 0) { /* Fail if we can't. */
1836: fcntl(ttyfd, F_SETFL, flags); /* Restore flags */
1837: return(-1); /* before returning. */
1838: }
1839: msleep(300); /* Give modem time to notice. */
1840:
1841: /* Now, even though it doesn't say this in SVID or any man page, we have */
1842: /* to close and reopen the device. This is not necessary for all systems, */
1843: /* but it's impossible to predict which ones need it and which ones don't. */
1844:
1845: #ifdef ATT7300
1846: /*
1847: Special handling for ATT 7300 UNIX PC and 3B1, which have "phone"
1848: related ioctl's for their internal modems. attmodem has getty status and
1849: modem-in-use bit. Reportedly the ATT7300/3B1 PIOCDISC call is necessary,
1850: but also ruins the file descriptor, and no other phone(7) ioctl call can fix
1851: it. Whateverit does, it seems to escape detection with PIOCGETA and TCGETA.
1852: The only way to undo the damage is to close the fd and then reopen it.
1853: */
1854: if (attmodem & ISMODEM) {
1855: debug(F100,"tthang attmodem close/open","",0);
1856: ioctl(ttyfd,PIOCUNHOLD,&dialer); /* Return call to handset. */
1857: ioctl(ttyfd,PIOCDISC,&dialer); /* Disconnect phone. */
1858: close(ttyfd); /* Close and reopen the fd. */
1859: ttyfd = priv_opn(ttnmsv, O_RDWR | O_NDELAY);
1860: attmodem &= ~ISMODEM; /* Phone no longer in use. */
1861: }
1862: #else /* !ATT7300 */
1863: /* It seems we have to close and open the device for other AT&T systems */
1864: /* too, and this is the place to do it. The following code does the */
1865: /* famous close(open(...)) magic by default. If that doesn't work for you, */
1866: /* then try uncommenting the following statement or putting -DCLSOPN in */
1867: /* the makefile CFLAGS. */
1868:
1869: /* #define CLSOPN */
1870:
1871: #ifndef SCO32 /* Not needed by, and harmful to, SCO UNIX 3.2 / Xenix 2.3 */
1872:
1873: #ifdef RTAIX /* RT AIX needs this too... */
1874: #define CLSOPN
1875: #endif /* RTAIX */
1876:
1877: #ifdef O_NDELAY
1878: #define OPENFLGS O_RDWR | O_NDELAY
1879: #else
1880: #define OPENFLGS O_RDWR
1881: #endif
1882:
1883: #ifndef CLSOPN
1884: /* This method is used by default. */
1885: /* It is thought to be safer because there is no window where getty */
1886: /* can seize control of the device. The drawback is that it might not work. */
1887:
1888: debug(F101,"tthang close(open()), OPENFLGS","",OPENFLGS);
1889: close(priv_opn(ttnmsv, OPENFLGS));
1890:
1891: #else
1892: /* This method is used if you #define CLSOPN. It is more likely to work */
1893: /* than the previous method, but it's also more dangerous. */
1894:
1895: debug(F101,"tthang close/open, OPENFLGS","",OPENFLGS);
1896: close(ttyfd);
1897: msleep(10);
1898: #ifdef COMMENT
1899: /* Why did we return? */
1900: if (ttyfd = priv_opn(ttnmsv, OPENFLGS)) return(1);
1901: #else
1902: /* We still need to restore the flags, etc. */
1903: ttyfd = priv_opn(ttnmsv, OPENFLGS);
1904: #endif /* COMMENT */
1905:
1906: #endif /* CLSOPN */
1907: #undef OPENFLGS
1908:
1909: #endif /* SCO32 */
1910: #endif /* ATT7300 */
1911:
1912: /* Now put all flags & modes back the way we found them. */
1913: /* (Does the order of ioctl & fcntl matter ? ) */
1914:
1915: debug(F100,"tthang restore settings","",0);
1916: ttcur.c_cflag = ttc_save; /* Get old speed back. */
1917: if (ioctl(ttyfd,TCSETAF,&ttcur) < 0) /* ioctl parameters. */
1918: return(-1);
1919: if (fcntl(ttyfd,F_SETFL,flags) < 0) /* fcntl parameters */
1920: return(-1);
1921:
1922: return(1);
1923: #endif /* not HPUX */
1924: #endif /* ATTSV */
1925: }
1926:
1927: /* T T R E S -- Restore terminal to "normal" mode. */
1928:
1929: /* [email protected]: There are two choices for what this function should do.
1930: * (1) Restore the tty to current "normal" mode, with carrier treatment
1931: * according to ttcarr, to be used after every kermit command. (2) Restore
1932: * the tty to the state it was in before kermit opened it. These choices
1933: * conflict, since ttold can't hold both choices of tty parameters. ttres()
1934: * is currently being called as in choice (1), but ttold basically holds
1935: * the initial parameters, as in (2), and the description at the beginning
1936: * of this file says (2).
1937: *
1938: * I don't think restoring tty parameters after all kermit commands makes
1939: * much of a difference. Restoring them upon exit from kermit may be of
1940: * some use in some cases (when the line is not restored automatically on
1941: * close, by the operating system).
1942: *
1943: * I can't choose which one it should be, so I haven't changed it. It
1944: * probably works as it is, too. It would probably even work even with
1945: * ttres() entirely deleted...
1946: *
1947: * (from fdc: Actually, this function operates in remote mode too, so
1948: * it restores the console (command) terminal to whatever mode it was
1949: * in before packet operations began, so that commands work right again.)
1950: */
1951: int
1952: ttres() { /* Restore the tty to normal. */
1953: int x;
1954:
1955: if (ttyfd < 0) return(-1); /* Not open. */
1956:
1957: if (ttfdflg) return(0); /* Don't mess with terminal modes if */
1958: /* we got ttyfd from another process */
1959: #ifdef NETCONN
1960: if (netconn) return (0); /* Network connection, do nothing */
1961: #endif /* NETCONN */
1962:
1963: /* Real terminal device, so restore its original modes */
1964:
1965: #ifdef ATTSV /* For AT&T versions... */
1966: x = ioctl(ttyfd,TCSETAW,&ttold); /* Restore tty modes this way. */
1967: #else
1968: #ifdef POSIX /* For POSIX like this */
1969: x = tcsetattr(ttyfd,TCSADRAIN,&ttold);
1970: #else /* For all others... */
1971: msleep(HUPTIME); /* This replaces sleep(1)... */
1972: /* Put back sleep(1) if tty is */
1973: /* messed up after close. */
1974:
1975: /* Here we restore the modes for BSD */
1976:
1977: #ifdef LPASS8 /* Undo "pass8" if it were done */
1978: if (lmodef) {
1979: if (ioctl(ttyfd,TIOCLSET,&lmode) < 0)
1980: debug(F100,"ttres TIOCLSET failed","",0);
1981: else
1982: debug(F100,"ttres TIOCLSET ok","",0);
1983: }
1984: #endif /* LPASS8 */
1985:
1986: #ifdef UTEK /* Undo hardware flow if it were done */
1987: if (lmodef) {
1988: if (ioctl(ttyfd,TIOCLSET,&lmode) < 0)
1989: debug(F100,"ttres TIOCLSET failed","",0);
1990: else
1991: debug(F100,"ttres TIOCLSET ok","",0);
1992: }
1993: #endif /* UTEK */
1994:
1995: #ifdef TIOCGETC /* Put back special characters */
1996: if (tcharf && (xlocal == 0)) {
1997: if (ioctl(ttyfd,TIOCSETC,&tchold) < 0)
1998: debug(F100,"ttres TIOCSETC failed","",0);
1999: else
2000: debug(F100,"ttres TIOCSETC ok","",0);
2001: }
2002: #endif /* TIOCGETC */
2003:
2004: #ifdef TIOCGLTC /* Put back local special characters */
2005: if (ltcharf && (xlocal == 0)) {
2006: if (ioctl(ttyfd,TIOCSLTC,<chold) < 0)
2007: debug(F100,"ttres TIOCSLTC failed","",0);
2008: else
2009: debug(F100,"ttres TIOCSLTC ok","",0);
2010: }
2011: #endif /* TIOCGLTC */
2012:
2013: x = stty(ttyfd,&ttold); /* restore tty modes the old way. */
2014:
2015: #endif /* POSIX */
2016: #endif /* ATTSV */
2017:
2018: debug(F101,"ttres tty modes restore","",x);
2019: if (x < 0) debug(F101,"ttres errno","",errno);
2020:
2021: #ifdef BSD41
2022: if (ttld > -1) { /* Put back line discipline */
2023: x = ioctl(ttyfd, TIOCSETD, &ttld);
2024: debug(F101,"ttres line discipline restore","",x);
2025: if (x < 0) debug(F101,"...ioctl errno","",errno);
2026: ttld = -1;
2027: }
2028: #endif /* BSD41 */
2029:
2030: #ifdef sony_news
2031: x = xlocal ? km_ext : km_con; /* Restore Kanji mode. */
2032: if (x != -1) { /* Make sure we know original modes. */
2033: if (ioctl(ttyfd,TIOCKSET, &x) < 0) {
2034: perror("ttres can't set Kanji mode");
2035: debug(F101,"ttres error setting Kanji mode","",x);
2036: return(-1);
2037: }
2038: }
2039: debug(F100,"ttres set Kanji mode ok","",0);
2040: #endif /* sony_news */
2041:
2042: tvtflg = 0; /* Invalidate terminal mode settings */
2043: return(x);
2044: }
2045:
2046: /* T T R P I D -- Read pid from lockfile "name" (used by ttlock) */
2047:
2048: int
2049: ttrpid(name) char *name; {
2050: int x, fd, pid;
2051:
2052: fd = open(name,O_RDONLY); /* Try to open lockfile. */
2053: if (fd > 0) {
2054:
2055: #ifdef PIDSTRING
2056: char buf[12];
2057: x = read(fd, buf, 11); /* For HDP UUCP, read pid string */
2058: if (x < 0) return(-1);
2059: buf[11] = '\0';
2060: if (x == 11)
2061: x = sscanf(buf,"%d",&pid); /* Get the integer pid from it. */
2062: #else
2063: x = read(fd, (char *)&pid, sizeof(pid)); /* Else read integer pid */
2064: #endif /* PIDSTRING */
2065:
2066: if (x < 0) pid = -1; /* Return any errors. */
2067: close(fd); /* Close the lockfile. */
2068: } else pid = -1;
2069: return(pid);
2070: }
2071:
2072: /* T T L O C K */
2073:
2074: /*
2075: This function attempts to coordinate use of the communication device with
2076: other copies of Kermit and any other program that follows the UUCP
2077: device-locking conventions, which, unfortunately, vary among different UNIX
2078: implementations. The idea is to look for a file of a certain name, the
2079: "lockfile", in a certain directory. If such a file is found, then the line
2080: is presumed to be in use, and Kermit should not use it. If no such file is
2081: found, Kermit attempts to create one so that other programs will not use the
2082: same line at the same time. Because the lockfile and/or the directory it's
2083: in might lack write permission for the person running Kermit, Kermit could
2084: find itself running setuid to uucp or other user that does have the
2085: necessary permissions. At startup, Kermit has changed its effective uid to
2086: the user's real uid, and so ttlock() must switch back to the original
2087: effective uid in order to create the lockfile, and then back again to the
2088: real uid to prevent unauthorized access to other directories or files owned
2089: by the user the program is setuid to.
2090:
2091: Totally rewritten for C-Kermit 5A to eliminate windows of vulnerability,
2092: based on suggestions from Warren Tucker. Call with pointer to name of
2093: tty device. Returns:
2094:
2095: 0 on success
2096: -1 on failure
2097:
2098: Note: Once privileges are turned on using priv_on(), it is essential that
2099: they are turned off again before this function returns.
2100: */
2101: #ifdef SVR4 /* Lockfile uses device numbers. */
2102: #ifndef LFDEVNO /* Define this for SVR4 */
2103: #define LFDEVNO /* If anybody else needs it, */
2104: #endif /* LFDEVNO */ /* define it here or on CC */
2105: #endif /* SVR4 */ /* command line. */
2106:
2107: #ifdef LFDEVNO
2108: #include <sys/stat.h> /* For major() & minor() macros. */
2109: /* Should be in <sys/types.h>. */
2110: #ifndef major /* If we didn't find it */
2111: #ifdef SVR4 /* then for Sys V R4 */
2112: #include <sys/mkdev.h> /* look here */
2113: #else /* or for Sunos versions */
2114: #ifdef SUNOS4 /* ... */
2115: #include <sys/sysmacros.h> /* look here */
2116: #else /* Otherwise take a chance: */
2117: #define major(dev) ( (int) ( ((unsigned)(dev) >> 8) & 0xff))
2118: #define minor(dev) ( (int) ( (dev) & 0xff))
2119: #endif /* SUNOS4 */
2120: #endif /* SVR4 */
2121: #endif /* major */
2122: #endif /* LFDEVNO */
2123: /*
2124: Note for RS/6000: routines ttylock(devicename), ttyunlock(devicename),
2125: and ttylocked(devicename) from the standard library (libc.a) could be
2126: used here instead. It's not clear whether there is any advantage in this.
2127: */
2128: static int
2129: ttlock(ttdev) char *ttdev; {
2130: int x;
2131:
2132: #ifdef MINIX
2133: char *buf;
2134: #endif /* MINIX */
2135:
2136: #ifdef NOUUCP
2137: strcpy(flfnam,"NOLOCK");
2138: haslock = 1;
2139: return(0);
2140: #else /* !NOUUCP */
2141: int lockfd; /* File descriptor for lock file. */
2142: PID_T pid; /* Process id of this process. */
2143: int fpid; /* pid found in existing lockfile. */
2144: int tries; /* How many times we've tried... */
2145: #ifdef LFDEVNO
2146: struct stat devbuf; /* For device numbers (SVR4). */
2147: #endif /* LFDEVNO */
2148:
2149: #ifdef PIDSTRING
2150: char pid_str[12]; /* My pid in string format. */
2151: #endif /* PIDSTRING */
2152:
2153: char *device, *devname;
2154:
2155: #define LFNAML 50 /* Max length for lock file name. */
2156: char lockfil[LFNAML]; /* Lock file name */
2157: #ifdef RTAIX
2158: char lklockf[LFNAML]; /* Name for link to lock file */
2159: #endif
2160: char tmpnam[LFNAML+30]; /* Temporary lockfile name. */
2161: char *lockdir = LOCK_DIR; /* Defined near top of this file, */
2162: /* or on cc command line. */
2163:
2164: haslock = 0; /* Not locked yet. */
2165: *flfnam = '\0'; /* Lockfile name is empty. */
2166: pid = getpid(); /* Get id of this process. */
2167:
2168: /* Construct name of lockfile and temporary file */
2169:
2170: /* device = name of tty device without the path, e.g. "ttyh8" */
2171: /* lockfil = name of lock file, without path, e.g. "LCK..ttyh8" */
2172:
2173: device = ((devname=xxlast(ttdev,'/')) != NULL ? devname+1 : ttdev);
2174:
2175: #ifdef ISIII /* Interactive System III, PC/IX */
2176: strcpy(lockfil, device);
2177: #else
2178: #ifdef LFDEVNO /* Lockfilename has device numbers. */
2179: if (stat(ttdev,&devbuf) < 0)
2180: return(-1);
2181: sprintf(lockfil,"LK.%03d.%03d.%03d",
2182: major(devbuf.st_dev), /* inode */
2183: major(devbuf.st_rdev), /* major device number */
2184: minor(devbuf.st_rdev)); /* minor device number */
2185:
2186: #else /* Others... */
2187: #ifdef PTX /* Dynix PTX */
2188: if (device != &ttdev[5] && strncmp(ttdev,"/dev/",5)==0) {
2189: sprintf(lockfil,"LCK..%.3s%s", &ttdev[5], device);
2190: } else
2191: #endif /* PTX */
2192: sprintf(lockfil,"LCK..%s", device);
2193: #ifdef M_XENIX /* SCO Xenix */
2194: { int x; char c;
2195: x = (int)strlen(lockfil) - 1; /* Get last letter of device name. */
2196: if (x > 0) { /* If it's uppercase, lower it. */
2197: c = lockfil[x];
2198: if (c >= 'A' && c <= 'Z') lockfil[x] += ('a' - 'A');
2199: }
2200: }
2201: #endif /* M_XENIX */
2202: #ifdef RTAIX
2203: strcpy(lklockf,device);
2204: #endif /* RTAIX */
2205: #endif /* LFDEVNO */
2206: #endif /* ISIII */
2207:
2208: /* flfnam = full lockfile pathname, e.g. "/usr/spool/uucp/LCK..ttyh8" */
2209: /* tmpnam = temporary unique, e.g. "/usr/spool/uucp/LTMP..pid" */
2210:
2211: sprintf(flfnam,"%s/%s",lockdir,lockfil);
2212: #ifdef RTAIX
2213: sprintf(lkflfn,"%s/%s",lockdir,lklockf);
2214: #endif
2215: sprintf(tmpnam,"%s/LTMP.%05d",lockdir,(int) pid);
2216: debug(F110,"ttlock flfnam",flfnam,0);
2217: debug(F110,"ttlock tmpnam",tmpnam,0);
2218:
2219: priv_on(); /* Turn on privileges if possible. */
2220: lockfd = creat(tmpnam, 0444); /* Try to create temp lock file. */
2221: if (lockfd < 0) { /* Create failed. */
2222: debug(F111,"ttlock creat failed",tmpnam,errno);
2223: if (errno == ENOENT) {
2224: perror(lockdir);
2225: printf("UUCP not installed or Kermit misconfigured\n");
2226: } else {
2227: perror(lockdir);
2228: unlink(tmpnam); /* Get rid of the temporary file. */
2229: }
2230: priv_off(); /* Turn off privileges!!! */
2231: return(-1); /* Return failure code. */
2232: }
2233: /* Now write the pid into the temp lockfile in the appropriate format */
2234:
2235: #ifdef PIDSTRING /* For Honey DanBer UUCP, */
2236: sprintf(pid_str,"%10d\n", (int) pid); /* write pid as decimal string. */
2237: write(lockfd, pid_str, 11);
2238: debug(F111,"ttlock hdb pid string",pid_str,(int) pid);
2239: #else /* Others use integer pid */
2240: write(lockfd, (char *)&pid, sizeof(pid) );
2241: debug(F111,"ttlock pid","",(int) pid);
2242: #endif /* PIDSTRING */
2243:
2244: /* Now try to rename the temp file to the real lock file name. */
2245: /* This will fail if a lock file of that name already exists. */
2246:
2247: close(lockfd); /* Close the temp lockfile. */
2248: chmod(tmpnam,0444); /* Permission for a valid lock. */
2249: tries = 0;
2250: while (!haslock && tries++ < 2) {
2251: haslock = (link(tmpnam,flfnam) == 0); /* Create a link to it. */
2252: if (haslock) { /* If we got the lockfile */
2253: #ifdef RTAIX
2254: link(flfnam,lkflfn);
2255: #endif
2256: break; /* we're done. */
2257: } else { /* Otherwise, */
2258: if ((fpid = ttrpid(flfnam)) > -1) { /* Read pid from lockfile */
2259: if (fpid > 0) {
2260: debug(F101,"ttlock fpid","",fpid);
2261: errno = 0; /* See if process still exists. */
2262: x = kill((PID_T) fpid,0);
2263: debug(F101,"ttlock kill","",x);
2264: debug(F101,"ttlock kill errno","",errno);
2265: if (x < 0 && errno == ESRCH) { /* pid is invalid */
2266: debug(F111,"ttlock removing stale lock",flfnam,
2267: fpid);
2268: if (!backgrd)
2269: printf(
2270: "Removing stale lock %s (pid %d terminated)\n",
2271: flfnam,fpid);
2272: x = unlink(flfnam); /* remove the lockfile. */
2273: debug(F111,"ttlock unlink",flfnam,x);
2274: continue; /* and go back and try again. */
2275: } else if (x < 0 && errno == EPERM || x == 0) {
2276: unlink(tmpnam); /* Delete the tempfile */
2277: debug(F101,"ttlock found tty locked","",fpid);
2278: priv_off(); /* Turn off privs */
2279: return(-2); /* Code for device is in use. */
2280: }
2281: } else {
2282: debug(F101,"ttlock can't get fpid","",fpid);
2283: break;
2284: }
2285: } else break;
2286: }
2287: }
2288: unlink(tmpnam); /* Unlink (remove) the temp file. */
2289: priv_off(); /* Turn off privs */
2290: return(haslock ? 0 : -1); /* Return link's return code. */
2291: #endif /* !NOUUCP */
2292: }
2293:
2294: /* T T U N L O C K */
2295:
2296: static int
2297: ttunlck() { /* Remove UUCP lockfile. */
2298: #ifndef NOUUCP
2299: if (haslock && *flfnam) {
2300: priv_on(); /* Turn privileges on. */
2301: unlink(flfnam); /* Remove the lockfile. */
2302: #ifdef RTAIX
2303: unlink(lkflfn);
2304: #endif
2305: *flfnam = '\0'; /* Erase the name. */
2306: priv_off(); /* Turn privileges off. */
2307: }
2308: #endif /* !NOUUCP */
2309: return(0);
2310: }
2311:
2312: /* 4.3BSD-style UUCP line direction control (Stan Barber, Rice U) */
2313:
2314: #ifdef ACUCNTRL
2315: VOID
2316: acucntrl(flag,ttname) char *flag, *ttname; {
2317: char x[DEVNAMLEN+32], *device, *devname;
2318:
2319: if (strcmp(ttname,CTTNAM) == 0 || xlocal == 0) /* If not local, */
2320: return; /* just return. */
2321: device = ((devname = xxlast(ttname,'/')) != NULL ? devname+1 : ttname);
2322: if (strncmp(device,"LCK..",4) == 0) device += 5;
2323: sprintf(x,"/usr/lib/uucp/acucntrl %s %s",flag,device);
2324: debug(F110,"called ",x,0);
2325: zsyscmd(x);
2326: }
2327: #endif /* ACUCNTRL */
2328:
2329: /* T T P K T -- Condition the communication line for packets. */
2330: /* or for modem dialing */
2331:
2332: #define DIALING 4 /* flags (via flow) for modem handling */
2333: #define CONNECT 5
2334:
2335: /* If called with speed > -1, also set the speed. */
2336:
2337: /* Returns 0 on success, -1 on failure. */
2338:
2339: int
2340: ttpkt(speed,flow,parity) long speed; int flow, parity; {
2341: int s2;
2342: int s = -1;
2343: #ifndef SVORPOSIX
2344: int x;
2345: #endif /* SVORPOSIX */
2346:
2347: if (ttyfd < 0) return(-1); /* Not open. */
2348:
2349: debug(F101,"ttpkt parity","",parity);
2350: debug(F101,"ttpkt flow","",flow);
2351: debug(F101,"ttpkt speed","",(int) speed);
2352:
2353: ttprty = parity; /* Let other tt functions see these. */
2354: ttpmsk = ttprty ? 0177 : 0377; /* Parity stripping mask */
2355: ttspeed = speed;
2356: ttflow = flow; /* Now make this available too. */
2357:
2358: #ifdef NETCONN /* Nothing to do for telnet */
2359: if (netconn) return (0);
2360: #endif /* NETCONN */
2361:
2362: if (ttfdflg && !isatty(ttyfd)) return(0);
2363:
2364: #ifndef SVORPOSIX /* Berkeley, V7, etc. */
2365: #ifdef LPASS8
2366: /*
2367: For some reason, with BSD terminal drivers, you can't set FLOW to XON/XOFF
2368: after having previously set it to NONE without closing and reopening the
2369: device. Unless there's something I overlooked below...
2370: */
2371: if (ttflow == FLO_NONE && flow == FLO_XONX && xlocal == 0) {
2372: debug(F101,"ttpkt executing horrible flow kludge","",0);
2373: ttclos(0); /* Close it */
2374: x = 0;
2375: ttopen(ttnmsv,&x,ttmdm,0); /* Open it again */
2376: }
2377: #endif /* LPASS8 */
2378: #endif /* SVORPOSIX */
2379:
2380: if (xlocal) {
2381: s2 = (int) (speed / 10L); /* Convert bps to cps */
2382: s = ttsspd(s2); /* Check and set the speed */
2383: debug(F101,"ttpkt carrier","",flow);
2384: carrctl(&ttraw, flow != DIALING /* Carrier control */
2385: && (ttcarr == CAR_ON));
2386: tvtflg = 0; /* So ttvt() will work next time */
2387: }
2388:
2389: #ifndef SVORPOSIX /* BSD section */
2390: #ifdef UTEK
2391: hardflow(flow);
2392: if (flow == FLO_NONE || flow == FLO_HARD) /* Something besides Xon/Xoff */
2393: #else
2394: if (flow == FLO_NONE) /* No Xon/Xoff flow control */
2395: #endif /* UTEK */
2396: {
2397: debug(F100,"ttpkt turning TANDEM off, RAW on","",0);
2398: ttraw.sg_flags &= ~TANDEM; /* Don't ask for it. */
2399: ttraw.sg_flags |= RAW;
2400: } else if (flow == FLO_XONX) { /* Xon/Xoff requested. */
2401: debug(F100,"ttpkt turning on TANDEM","",0);
2402: ttraw.sg_flags |= TANDEM; /* So ask for it. */
2403:
2404: #ifdef LPASS8 /* Can pass 8-bit data through? */
2405: /* If the LPASS8 local mode is available, then flow control can always */
2406: /* be used, even if parity is none and we are transferring 8-bit data. */
2407: /* But we only need to do all this if Xon/Xoff is requested. */
2408: /* BUT... this tends not to work through IP or LAT connections, terminal */
2409: /* servers, telnet, rlogin, etc, so it is not generally used. */
2410: x = LPASS8; /* If LPASS8 defined, then */
2411: debug(F100,"ttpkt executing LPASS8 code","",0);
2412: if (lmodef) { /* TIOCLBIS must be too. */
2413: x = ioctl(ttyfd,TIOCLBIS,&x); /* Try to set LPASS8. */
2414: if (x < 0) {
2415: debug(F100,"ttpkt TIOCLBIS error","",0);
2416: } else {
2417: lmodef++;
2418: debug(F100,"ttpkt TIOCLBIS ok","",0);
2419: }
2420: }
2421: /*
2422: But if we use LPASS8 mode, we must explicitly turn off
2423: terminal interrupts of all kinds.
2424: */
2425: #ifdef TIOCGETC /* Not rawmode, */
2426: if (tcharf && (xlocal == 0)) { /* must turn off */
2427: tchnoi.t_intrc = -1; /* interrupt character */
2428: tchnoi.t_quitc = -1; /* and quit character. */
2429: tchnoi.t_startc = 17; /* Make sure xon */
2430: tchnoi.t_stopc = 19; /* and xoff not ignored. */
2431: if (ioctl(ttyfd,TIOCSETC,&tchnoi) < 0) {
2432: debug(F100,"ttpkt TIOCSETC failed","",0);
2433: } else {
2434: tcharf = 1;
2435: debug(F100,"ttpkt TIOCSETC ok","",0);
2436: }
2437: #ifdef COMMENT
2438: /* only for paranoid debugging */
2439: if (tcharf) {
2440: struct tchars foo;
2441: char tchbuf[100];
2442: ioctl(0,TIOCGETC,&foo);
2443: sprintf(tchbuf,
2444: "intr=%d,quit=%d, start=%d, stop=%d, eof=%d, brk=%d",
2445: foo.t_intrc, foo.t_quitc, foo.t_startc,
2446: foo.t_stopc, foo.t_eofc, foo.t_brkc);
2447: debug(F110,"ttpkt chars",tchbuf,0);
2448: }
2449: #endif /* COMMENT */
2450: }
2451: ttraw.sg_flags |= CBREAK; /* Needed for unknown reason */
2452: #endif /* TIOCGETC */
2453:
2454: /* Prevent suspend during packet mode */
2455: #ifdef TIOCGLTC /* Not rawmode, */
2456: if (ltcharf && (xlocal == 0)) { /* must turn off */
2457: ltchnoi.t_suspc = -1; /* suspend character */
2458: ltchnoi.t_dsuspc = -1; /* and delayed suspend character */
2459: if (ioctl(ttyfd,TIOCSLTC,&tchnoi) < 0) {
2460: debug(F100,"ttpkt TIOCSLTC failed","",0);
2461: } else {
2462: ltcharf = 1;
2463: debug(F100,"ttpkt TIOCSLTC ok","",0);
2464: }
2465: }
2466: #endif /* TIOCGLTC */
2467:
2468: #else /* LPASS8 not defined */
2469:
2470: /* Previously, BSD-based implementations always */
2471: /* used rawmode for packets. Now, we use rawmode only if parity is NONE. */
2472: /* This allows the flow control requested above to actually work, but only */
2473: /* if the user asks for parity (which also means they get 8th-bit quoting). */
2474:
2475: if (parity) { /* If parity, */
2476: ttraw.sg_flags &= ~RAW; /* use cooked mode */
2477: #ifdef COMMENT
2478: /* WHY??? */
2479: if (xlocal)
2480: #endif /* COMMENT */
2481: ttraw.sg_flags |= CBREAK;
2482: debug(F101,"ttpkt cooked, cbreak, parity","",parity);
2483: #ifdef TIOCGETC /* Not rawmode, */
2484: if (tcharf && (xlocal == 0)) { /* must turn off */
2485: tchnoi.t_intrc = -1; /* interrupt character */
2486: tchnoi.t_quitc = -1; /* and quit character. */
2487: tchnoi.t_startc = 17; /* Make sure xon */
2488: tchnoi.t_stopc = 19; /* and xoff not ignored. */
2489: if (ioctl(ttyfd,TIOCSETC,&tchnoi) < 0) {
2490: debug(F100,"ttpkt TIOCSETC failed","",0);
2491: } else {
2492: tcharf = 1;
2493: debug(F100,"ttpkt TIOCSETC ok","",0);
2494: }
2495: }
2496: #endif /* TIOCGETC */
2497: #ifdef TIOCGLTC /* Not rawmode, */
2498: /* Prevent suspend during packet mode */
2499: if (ltcharf && (xlocal == 0)) { /* must turn off */
2500: ltchnoi.t_suspc = -1; /* suspend character */
2501: ltchnoi.t_dsuspc = -1; /* and delayed suspend character */
2502: if (ioctl(ttyfd,TIOCSLTC,&tchnoi) < 0) {
2503: debug(F100,"ttpkt TIOCSLTC failed","",0);
2504: } else {
2505: ltcharf = 1;
2506: debug(F100,"ttpkt TIOCSLTC ok","",0);
2507: }
2508: }
2509: #endif /* TIOCGLTC */
2510: } else { /* If no parity, */
2511: ttraw.sg_flags |= RAW; /* must use 8-bit raw mode. */
2512: debug(F101,"ttpkt setting rawmode, parity","",parity);
2513: }
2514: } else { /* No Xon/Xoff */
2515: debug(F101,"ttpkt setting rawmode, flow","",flow);
2516: ttraw.sg_flags |= RAW; /* Can use 8-bit raw mode. */
2517: #endif /* LPASS8 */
2518: }
2519:
2520: /* Don't echo, don't map CR to CRLF on output, don't fool with case */
2521: #ifdef LCASE
2522: ttraw.sg_flags &= ~(ECHO|CRMOD|LCASE);
2523: #else
2524: ttraw.sg_flags &= ~(ECHO|CRMOD);
2525: #endif /* LCASE */
2526:
2527: #ifdef TOWER1
2528: ttraw.sg_flags &= ~ANYP; /* Must tell Tower no parity */
2529: #endif /* TOWER1 */
2530:
2531: if (stty(ttyfd,&ttraw) < 0) return(-1); /* Set the new modes. */
2532: debug(F100,"ttpkt stty ok","",0);
2533:
2534: #ifdef sony_news
2535: x = xlocal ? km_ext : km_con; /* Put line in ASCII mode. */
2536: if (x != -1) { /* Make sure we know original modes. */
2537: x &= ~KM_TTYPE;
2538: x |= KM_ASCII;
2539: if (ioctl(ttyfd,TIOCKSET, &x) < 0) {
2540: perror("ttpkt can't set ASCII mode");
2541: debug(F101,"ttpkt error setting ASCII mode","",x);
2542: return(-1);
2543: }
2544: }
2545: debug(F100,"ttpkt set ASCII mode ok","",0);
2546: #endif /* sony_news */
2547:
2548: if (xlocal == 0) /* Turn this off so we can read */
2549: signal(SIGINT,SIG_IGN); /* Ctrl-C chars typed at console */
2550:
2551: tvtflg = 0; /* So ttvt() will work next time */
2552: return(0);
2553:
2554: #endif /* Not ATTSV or POSIX */
2555:
2556: /* AT&T UNIX and POSIX */
2557:
2558: #ifdef SVORPOSIX
2559: if (flow == FLO_XONX) ttraw.c_iflag |= (IXON|IXOFF);
2560: if (flow == FLO_NONE) ttraw.c_iflag &= ~(IXON|IXOFF);
2561: if (flow == FLO_RTSC) {
2562: /* RTS/CTS Flow control... */
2563: #ifdef RTSXOFF
2564: /* This is the preferred way, according to SVID R4 */
2565: if (ioctl(ttyfd,TCGETX,&rctsx) > -1) {
2566: rctsx.x_hflag |= RTSXOFF | CTSXON;
2567: ioctl(ttyfd,TCSETX,&rctsx); /* Ignore errors for now. */
2568: }
2569: #else
2570: #ifdef CRTSCTS
2571: /* Found this one in <termios.h> */
2572: ttraw.c_iflag |= CRTSCTS;
2573: #endif /* CRTSCRS */
2574: #endif /* RTSXOFF */
2575: }
2576: if (flow == FLO_DTRC) {
2577: /* DTR/CD Flow control... */
2578: #ifdef DTRXOFF
2579: /* This is straight out of SVID R3 */
2580: if (ioctl(ttyfd,TCGETX,&rctsx) > -1) {
2581: rctsx.x_hflag |= DTRXOFF | CDXON;
2582: ioctl(ttyfd,TCSETX,&rctsx); /* Ignore errors. */
2583: }
2584: #endif /* DTRXOFF */
2585: }
2586:
2587: ttraw.c_lflag &= ~(ICANON|ECHO);
2588: ttraw.c_lflag &= ~ISIG; /* Do NOT check for interrupt chars */
2589: ttraw.c_lflag |= NOFLSH; /* Don't flush */
2590: ttraw.c_iflag |= (BRKINT|IGNPAR);
2591: #ifdef ATTSV
2592: ttraw.c_iflag &= ~(IGNBRK|INLCR|IGNCR|ICRNL|IUCLC|INPCK|ISTRIP|IXANY);
2593: #else /* POSIX */
2594: ttraw.c_iflag &= ~(IGNBRK|INLCR|IGNCR|ICRNL|INPCK|ISTRIP);
2595: #endif /* ATTSV */
2596: ttraw.c_oflag &= ~OPOST;
2597: ttraw.c_cflag &= ~(CSIZE|PARENB);
2598: ttraw.c_cflag |= (CS8|CREAD|HUPCL);
2599: #ifdef IX370
2600: ttraw.c_cc[4] = 48; /* So Series/1 doesn't interrupt on every char */
2601: ttraw.c_cc[5] = 1;
2602: #else
2603: ttraw.c_cc[4] = 1; /* [VMIN] return max of this many characters or */
2604: ttraw.c_cc[5] = 0; /* [VTIME] when this many secs/10 expire w/no input */
2605: #endif /* IX370 */
2606:
2607: #ifdef VINTR /* Turn off interrupt character */
2608: if (xlocal == 0) /* so ^C^C can break us out of */
2609: ttraw.c_cc[VINTR] = 0; /* packet mode. */
2610: #endif /* VINTR */
2611:
2612: #ifdef ATTSV
2613: if (xlocal && (s > 0)) { /* set speed */
2614: ttraw.c_cflag &= ~CBAUD;
2615: ttraw.c_cflag |= s;
2616: }
2617: if (ioctl(ttyfd,TCSETAW,&ttraw) < 0) return(-1); /* set new modes . */
2618: #else /* POSIX */
2619: if (xlocal && (s > 0)) {
2620: cfsetispeed(&ttraw,s);
2621: cfsetospeed(&ttraw,s);
2622: }
2623: if (tcsetattr(ttyfd,TCSADRAIN,&ttraw) < 0) return(-1);
2624: #endif /* ATTSV */
2625: tvtflg = 0;
2626: return(0);
2627: #endif /* ATTSV */
2628: }
2629:
2630: /* T T V T -- Condition communication line for use as virtual terminal */
2631:
2632: int
2633: ttvt(speed,flow) long speed; int flow; {
2634: int s, s2;
2635:
2636: debug(F101,"ttvt ttyfd","",ttyfd);
2637: debug(F101,"ttvt tvtflg","",tvtflg);
2638: debug(F101,"ttvt speed","",speed);
2639: if (ttyfd < 0) return(-1); /* Not open. */
2640: #ifdef NETCONN
2641: if (netconn) {
2642: tvtflg = 1; /* Network connections */
2643: return(0); /* require no special setup */
2644: }
2645: #endif /* NETCONN */
2646:
2647: if (tvtflg != 0 && speed == ttspeed && flow == ttflow && ttcarr == curcarr)
2648: return(0); /* Already been called. */
2649:
2650: if (ttfdflg && !isatty(ttyfd)) return(0);
2651:
2652: if (xlocal) { /* For external lines... */
2653: s2 = (int) (speed / 10L);
2654: s = ttsspd(s2); /* Check/set the speed */
2655: carrctl(&tttvt, flow != DIALING /* Do carrier control */
2656: && (ttcarr == CAR_ON || ttcarr == CAR_AUT && ttmdm != 0));
2657: } else s = s2 = -1;
2658:
2659: #ifndef SVORPOSIX
2660: /* Berkeley, V7, etc */
2661: if (flow == FLO_XONX) tttvt.sg_flags |= TANDEM; /* XON/XOFF if selected */
2662: #ifdef UTEK
2663: hardflow(flow);
2664: if (flow == FLO_NONE || flow == FLO_HARD) tttvt.sg_flags &= ~TANDEM;
2665: #else
2666: if (flow == FLO_NONE) tttvt.sg_flags &= ~TANDEM;
2667: #endif /* UTEK */
2668: tttvt.sg_flags |= RAW; /* Raw mode */
2669: #ifdef TOWER1
2670: tttvt.sg_flags &= ~(ECHO|ANYP); /* No echo or parity */
2671: #else
2672: tttvt.sg_flags &= ~ECHO; /* No echo */
2673: #endif /* TOWER1 */
2674:
2675: if (stty(ttyfd,&tttvt) < 0) return(-1);
2676:
2677: #else /* It is ATTSV or POSIX */
2678:
2679: if (flow == FLO_XONX) tttvt.c_iflag |= (IXON|IXOFF);
2680: if (flow == FLO_NONE) tttvt.c_iflag &= ~(IXON|IXOFF);
2681:
2682: tttvt.c_lflag &= ~(ISIG|ICANON|ECHO);
2683: tttvt.c_iflag |= (IGNBRK|IGNPAR);
2684: #ifdef ATTSV
2685: tttvt.c_iflag &= ~(INLCR|IGNCR|ICRNL|IUCLC|BRKINT|INPCK|ISTRIP|IXANY);
2686: #else /* POSIX */
2687: tttvt.c_iflag &= ~(INLCR|IGNCR|ICRNL|BRKINT|INPCK|ISTRIP);
2688: #endif /* ATTSV */
2689: tttvt.c_oflag &= ~OPOST;
2690: tttvt.c_cflag &= ~(CSIZE|PARENB);
2691: tttvt.c_cflag |= (CS8|CREAD|HUPCL);
2692: tttvt.c_cc[4] = 1;
2693: tttvt.c_cc[5] = 0;
2694:
2695: #ifdef ATTSV
2696: if (s > 0) { /* Set speed */
2697: tttvt.c_cflag &= ~CBAUD;
2698: tttvt.c_cflag |= s;
2699: }
2700: if (ioctl(ttyfd,TCSETAW,&tttvt) < 0) return(-1); /* set new modes . */
2701: #else /* POSIX */
2702: if (xlocal && (s > 0)) {
2703: cfsetispeed(&tttvt,s);
2704: cfsetospeed(&tttvt,s);
2705: }
2706: if (tcsetattr(ttyfd,TCSADRAIN,&tttvt) < 0) return(-1);
2707: #endif /* ATTSV */
2708: #endif /* SVORPOSIX */
2709:
2710: ttspeed = speed; /* Done, remember how we were */
2711: ttflow = flow; /* called, so we can decide how to */
2712: tvtflg = 1; /* respond next time. */
2713:
2714: debug(F101,"ttvt done","",tvtflg);
2715: return(0);
2716: }
2717:
2718: /* T T S S P D -- Checks and sets transmission rate. */
2719:
2720: /* Call with speed in characters (not bits!) per second. */
2721: /* Returns internal speed code if successful, -1 otherwise. */
2722:
2723: int
2724: ttsspd(cps) int cps; {
2725: int s, s2;
2726:
2727: debug(F101,"ttsspd","",cps);
2728:
2729: #ifdef NETCONN
2730: if (netconn) return (0);
2731: #endif /* NETCONN */
2732:
2733: if (cps < 0) return(-1);
2734: s = s2 = -1;
2735:
2736: /* First check that the given speed is valid. */
2737:
2738: switch (cps) {
2739: #ifndef MINIX
2740: case 0: s = B0; break;
2741: case 5: s = B50; break;
2742: case 7: s = B75; break;
2743: #endif
2744: case 11: s = B110; break;
2745: #ifndef MINIX
2746: case 15: s = B150; break;
2747: case 20: s = B200; break;
2748: #endif
2749: case 30: s = B300; break;
2750: #ifndef MINIX
2751: case 60: s = B600; break;
2752: #endif
2753: case 120: s = B1200; break;
2754: #ifndef MINIX
2755: case 180: s = B1800; break;
2756: #endif
2757: case 240: s = B2400; break;
2758: case 480: s = B4800; break;
2759: #ifndef MINIX
2760: case 888: s = B75; s2 = B1200; break; /* 888 = 75/1200 split speed */
2761: #endif
2762: case 960: s = B9600; break;
2763: #ifdef B19200
2764: case 1920: s = B19200; break;
2765: #else
2766: #ifdef EXTA
2767: case 1920: s = EXTA; break;
2768: #endif
2769: #endif
2770: #ifdef B38400
2771: case 3840: s = B38400; break;
2772: #else
2773: #ifdef EXTB
2774: case 3840: s = EXTB; break;
2775: #endif
2776: #endif
2777: default:
2778: return(-1);
2779: }
2780: /* Actually set the speed */
2781:
2782: if (ttyfd > -1 && s > -1 && xlocal != 0) {
2783: if (s2 == -1) s2 = s;
2784:
2785: #ifdef ATTSV
2786: if (cps == 888) return(-1); /* No split speeds, sorry. */
2787: if (ioctl(ttyfd,TCGETA,&ttcur) < 0) return(-1);
2788: ttcur.c_cflag &= ~CBAUD;
2789: ttcur.c_cflag |= s;
2790: tttvt.c_cflag &= ~CBAUD;
2791: tttvt.c_cflag |= s;
2792: ttraw.c_cflag &= ~CBAUD;
2793: ttraw.c_cflag |= s;
2794: ttold.c_cflag &= ~CBAUD;
2795: ttold.c_cflag |= s;
2796: if (ioctl(ttyfd,TCSETAW,&ttcur) < 0) return(-1);
2797: #else
2798: #ifdef POSIX
2799: if (tcgetattr(ttyfd,&ttcur) < 0) return(-1);
2800: cfsetospeed(&ttcur,s);
2801: cfsetispeed(&ttcur,s2);
2802: cfsetospeed(&ttraw,s);
2803: cfsetispeed(&ttraw,s2);
2804: cfsetospeed(&tttvt,s);
2805: cfsetispeed(&tttvt,s2);
2806: cfsetospeed(&ttold,s);
2807: cfsetispeed(&ttold,s2);
2808: if (tcsetattr(ttyfd,TCSADRAIN,&ttcur) < 0) return(-1);
2809: #else
2810: if (gtty(ttyfd,&ttcur) < 0) return(-1);
2811: ttcur.sg_ospeed = s; ttcur.sg_ispeed = s2;
2812: tttvt.sg_ospeed = s; tttvt.sg_ispeed = s2;
2813: ttraw.sg_ospeed = s; ttraw.sg_ispeed = s2;
2814: ttold.sg_ospeed = s; ttold.sg_ispeed = s2;
2815: if (stty(ttyfd,&ttcur) < 0) return(-1);
2816: #endif /* POSIX */
2817: #endif /* ATTSV */
2818: }
2819: return(s);
2820: }
2821:
2822: /* T T G S P D - Get speed of currently selected tty line */
2823:
2824: /*
2825: Unreliable. After SET LINE, it returns an actual speed, but not the real
2826: speed. Apparently it always returns the line's nominal speed, from
2827: /etc/ttytab. Even if you SET SPEED to something else, this function might
2828: not notice.
2829: */
2830: long
2831: ttgspd() { /* Get current tty speed */
2832: int s; long ss;
2833: char temp[12];
2834:
2835: #ifdef NETCONN
2836: if (netconn) return(-1); /* -1 if network connection */
2837: #endif /* NETCONN */
2838:
2839: if (ttyfd < 0) {
2840: #ifdef ATTSV
2841: s = ccold.c_cflag & CBAUD;
2842: #else
2843: #ifdef POSIX
2844: s = cfgetospeed(&ccold);
2845: #else
2846: s = ccold.sg_ospeed; /* (obtained by congm()) */
2847: #endif /* POSIX */
2848: #endif /* ATTSV */
2849: } else {
2850: #ifdef ATTSV
2851: if (ioctl(ttyfd,TCGETA,&ttcur) < 0) return(-1);
2852: s = ttcur.c_cflag & CBAUD;
2853: #else
2854: #ifdef POSIX
2855: if (tcgetattr(ttyfd,&ttcur) < 0) return(-1);
2856: s = cfgetospeed(&ttcur);
2857: #else
2858: if (gtty(ttyfd,&ttcur) < 0) return(-1);
2859: s = ttcur.sg_ospeed;
2860: #endif /* POSIX */
2861: #endif /* ATTSV */
2862: }
2863: debug(F101,"ttgspd ttyfd","",ttyfd);
2864: debug(F101,"ttgspd code","",s);
2865: switch (s) {
2866: #ifdef B0
2867: case B0: ss = 0L; break;
2868: #endif
2869:
2870: #ifndef MINIX
2871: /*
2872: MINIX defines the Bxx symbols to be bps/100, so B50==B75, B110==B134==B150,
2873: etc, making for many "duplicate case in switch" errors, which are fatal.
2874: */
2875: #ifdef B50
2876: case B50: ss = 50L; break;
2877: #endif
2878: #ifdef B75
2879: case B75: ss = 75L; break;
2880: #endif
2881: #endif /* MINIX */
2882:
2883: #ifdef B110
2884: case B110: ss = 110L; break;
2885: #endif
2886:
2887: #ifndef MINIX
2888: #ifdef B134
2889: case B134: ss = 134L; break;
2890: #endif
2891: #ifdef B150
2892: case B150: ss = 150L; break;
2893: #endif
2894: #endif /* MINIX */
2895:
2896: #ifdef B200
2897: case B200: ss = 200L; break;
2898: #endif
2899:
2900: #ifdef B300
2901: case B300: ss = 300L; break;
2902: #endif
2903: #ifdef B600
2904: case B600: ss = 600L; break;
2905: #endif
2906: #ifdef B1200
2907: case B1200: ss = 1200L; break;
2908: #endif
2909: #ifdef B1800
2910: case B1800: ss = 1800L; break;
2911: #endif
2912: #ifdef B2400
2913: case B2400: ss = 2400L; break;
2914: #endif
2915: #ifdef B4800
2916: case B4800: ss = 4800L; break;
2917: #endif
2918: #ifdef B9600
2919: case B9600: ss = 9600L; break;
2920: #endif
2921: #ifdef B19200
2922: case B19200: ss = 19200L; break;
2923: #else
2924: #ifdef EXTA
2925: case EXTA: ss = 19200L; break;
2926: #endif
2927: #endif
2928:
2929: #ifndef MINIX
2930: #ifdef B38400
2931: case B38400: ss = 38400L; break;
2932: #else
2933: #ifdef EXTB
2934: case EXTB: ss = 38400L; break;
2935: #endif
2936: #endif
2937: #endif /* MINIX */
2938:
2939: default:
2940: ss = -1; break;
2941: }
2942: sprintf(temp,"%l",ss);
2943: debug(F110,"speed",temp,0);
2944: return(ss);
2945: }
2946:
2947: /* ckumyr.c by Kristoffer Eriksson, [email protected], 15 Mar 1990. */
2948:
2949: #ifdef COHERENT
2950: #ifdef FIONREAD
2951: #undef FIONREAD
2952: #endif
2953: #define FIONREAD TIOCQUERY
2954: #define PEEKTYPE int
2955: #else
2956: #define PEEKTYPE long
2957: #endif /* COHERENT */
2958:
2959: #ifdef MYREAD
2960:
2961: /* Private buffer for myread() and its companions. Not for use by anything
2962: * else. ttflui() is allowed to reset them to initial values. ttchk() is
2963: * allowed to read my_count.
2964: *
2965: * my_item is an index into mybuf[]. Increment it *before* reading mybuf[].
2966: *
2967: * A global parity mask variable could be useful too. We could use it to
2968: * let myread() strip the parity on its own, instead of stripping sign
2969: * bits as it does now.
2970: */
2971:
2972: #define MYBUFLEN 256
2973: static CHAR mybuf[MYBUFLEN]; /* Buffer, including push back */
2974: static int my_count = 0; /* Number of chars still in mybuf */
2975: static int my_item = -1; /* Last index read from mybuf[] */
2976:
2977: /* myread() -- Efficient read of one character from communications line.
2978: *
2979: * Uses a private buffer to minimize the number of expensive read() system
2980: * calls. Essentially performs the equivalent of read() of 1 character, which
2981: * is then returned. By reading all available input from the system buffers
2982: * to the private buffer in one chunk, and then working from this buffer, the
2983: * number of system calls is reduced in any case where more than one character
2984: * arrives during the processing of the previous chunk, for instance high
2985: * baud rates or network type connections where input arrives in packets.
2986: * If the time needed for a read() system call approaches the time for more
2987: * than one character to arrive, then this mechanism automatically compensates
2988: * for that by performing bigger read()s less frequently. If the system load
2989: * is high, the same mechanism compensates for that too.
2990: *
2991: * myread() is a macro that returns the next character from the buffer. If the
2992: * buffer is empty, mygetbuf() is called. See mygetbuf() for possible error
2993: * returns.
2994: *
2995: * This should be efficient enough for any one-character-at-a-time loops.
2996: * For even better efficiency you might use memcpy()/bcopy() or such between
2997: * buffers (since they are often better optimized for copying), but it may not
2998: * be worth it if you have to take an extra pass over the buffer to strip
2999: * parity and check for CTRL-C anyway.
3000: *
3001: * Note that if you have been using myread() from another program module, you
3002: * may have some trouble accessing this macro version and the private variables
3003: * it uses. In that case, just add a function in this module, that invokes the
3004: * macro.
3005: */
3006: #define myread() (--my_count < 0 ? mygetbuf() : 255 & (int)mybuf[++my_item])
3007:
3008: /* Specification: Push back up to one character onto myread()'s queue.
3009: *
3010: * This implementation: Push back characters into mybuf. At least one character
3011: * must have been read through myread() before myunrd() may be used. After
3012: * EOF or read error, again, myunrd() can not be used. Sometimes more than
3013: * one character can be pushed back, but only one character is guaranteed.
3014: * Since a previous myread() must have read its character out of mybuf[],
3015: * that guarantees that there is space for at least one character. If push
3016: * back was really needed after EOF, a small addition could provide that.
3017: *
3018: * myunrd() is currently not called from anywhere inside kermit...
3019: */
3020: #ifdef NOTUSED
3021: myunrd(ch) CHAR ch; {
3022: if (my_item >= 0) {
3023: mybuf[my_item--] = ch;
3024: ++my_count;
3025: }
3026: }
3027: #endif
3028:
3029: /* mygetbuf() -- Fill buffer for myread() and return first character.
3030: *
3031: * This function is what myread() uses when it can't get the next character
3032: * directly from its buffer. First, it calls a system dependent myfillbuf()
3033: * to read at least one new character into the buffer, and then it returns
3034: * the first character just as myread() would have done. This function also
3035: * is responsible for all error conditions that myread() can indicate.
3036: *
3037: * Returns: When OK => a positive character, 0 or greater.
3038: * When EOF => -2.
3039: * When error => -3, error code in errno.
3040: *
3041: * Older myread()s additionally returned -1 to indicate that there was nothing
3042: * to read, upon which the caller would call myread() again until it got
3043: * something. The new myread()/mygetbuf() always gets something. If it
3044: * doesn't, then make it do so! Any program that actually depends on the old
3045: * behaviour will break.
3046: *
3047: * The older version also used to return -2 both for EOF and other errors,
3048: * and used to set errno to 9999 on EOF. The errno stuff is gone, EOF and
3049: * other errors now return different results, although Kermit currently never
3050: * checks to see which it was. It just disconnects in both cases.
3051: *
3052: * Kermit lets the user use the quit key to perform some special commands
3053: * during file transfer. This causes read(), and thus also mygetbuf(), to
3054: * finish without reading anything and return the EINTR error. This should
3055: * be checked by the caller. Mygetbuf() could retry the read() on EINTR,
3056: * but if there is nothing to read, this could delay Kermit's reaction to
3057: * the command, and make Kermit appear unresponsive.
3058: *
3059: * The debug() call should be removed for optimum performance.
3060: */
3061: int
3062: mygetbuf() {
3063: my_count = myfillbuf();
3064: /* debug(F101, "myfillbuf read", "", my_count); */
3065: if (my_count <= 0)
3066: return(my_count < 0 ? -3 : -2);
3067: --my_count;
3068: return(255 & (int)mybuf[my_item = 0]);
3069: }
3070:
3071: /* myfillbuf():
3072: * System-dependent read() into mybuf[], as many characters as possible.
3073: *
3074: * Returns: OK => number of characters read, always more than zero.
3075: * EOF => 0
3076: * Error => -1, error code in errno.
3077: *
3078: * If there is input available in the system's buffers, all of it should be
3079: * read into mybuf[] and the function return immediately. If no input is
3080: * available, it should wait for a character to arrive, and return with that
3081: * one in mybuf[] as soon as possible. It may wait somewhat past the first
3082: * character, but be aware that any such delay lengthens the packet turnaround
3083: * time during kermit file transfers. Should never return with zero characters
3084: * unless EOF or irrecoverable read error.
3085: *
3086: * Correct functioning depends on the correct tty parameters being used.
3087: * Better control of current parameters is required than may have been the
3088: * case in older Kermit releases. For instance, O_NDELAY (or equivalent) can
3089: * no longer be sometimes off and sometimes on like it used to, unless a
3090: * special myfillbuf() is written to handle that. Otherwise the ordinary
3091: * myfillbuf()s may think they have come to EOF.
3092: *
3093: * If your system has a facility to directly perform the functioning of
3094: * myfillbuf(), then use it. If the system can tell you how many characters
3095: * are available in its buffers, then read that amount (but not less than 1).
3096: * If the system can return a special indication when you try to read without
3097: * anything to read, while allowing you to read all there is when there is
3098: * something, you may loop until there is something to read, but probably that
3099: * is not good for the system load.
3100: */
3101:
3102: #ifdef SVORPOSIX
3103: /* This is for System III/V with VMIN>0, VTIME=0 and O_NDELAY off,
3104: * and CLOCAL set any way you like. This way, read() will do exactly
3105: * what is required by myfillbuf(): If there is data in the buffers
3106: * of the O.S., all available data is read into mybuf, up to the size
3107: * of mybuf. If there is none, the first character to arrive is
3108: * awaited and returned.
3109: */
3110: int
3111: myfillbuf() {
3112: #ifdef sxaE50
3113: /* From S. Dezawa at Fujifilm in Japan. I don't know why this is */
3114: /* necessary for the sxa E50, but it is. */
3115: return read(ttyfd, mybuf, 255);
3116: #else
3117: /* sizeof(mybuf) should be MYBUFL == 256 */
3118: return read(ttyfd, mybuf, sizeof(mybuf));
3119: #endif /* sxaE50 */
3120: }
3121:
3122: #else /* not AT&T or POSIX */
3123:
3124: #ifdef aegis
3125: /* This is quoted from the old myread(). The semantics seem to be
3126: * alright, but maybe errno would not need to be set even when
3127: * there is no error? I don't know aegis.
3128: */
3129: int
3130: myfillbuf() {
3131: int count;
3132:
3133: count = ios_$get((short)ttyfd, ios_$cond_opt, mybuf, 256L, st);
3134: errno = EIO;
3135: if (st.all == ios_$get_conditional_failed) /* get at least one */
3136: inbufc = ios_$get((short)ttyfd, 0, mybuf, 1L, st);
3137: if (st.all == ios_$end_of_file)
3138: return(0);
3139: else if (st.all != status_$ok) {
3140: errno = EIO;
3141: return(-1);
3142: }
3143: return(count);
3144: }
3145: #else /* !aegis */
3146:
3147: #ifdef FIONREAD
3148: /* This is for systems with FIONREAD. FIONREAD returns the number
3149: * of characters available for reading. If none are available, wait
3150: * until something arrives, otherwise return all there is.
3151: */
3152: int
3153: myfillbuf() {
3154: PEEKTYPE avail;
3155:
3156: if ((ioctl(ttyfd, FIONREAD, &avail) < 0) || (avail == 0))
3157: avail = 1;
3158:
3159: if (avail > MYBUFLEN)
3160: avail = MYBUFLEN;
3161:
3162: return(read(ttyfd, mybuf, (int) avail));
3163: }
3164:
3165: #else /* !FIONREAD */
3166: /* Add other systems here, between #ifdef and #else, e.g. NETCONN. */
3167: /* When there is no other possibility, read 1 character at a time. */
3168: int
3169: myfillbuf() {
3170: return read(ttyfd, mybuf, 1);
3171: }
3172:
3173: #endif /* !FIONREAD */
3174: #endif /* !aegis */
3175: #endif /* !ATTSV */
3176:
3177: #endif /* MYREAD */
3178:
3179: /* T T F L U I -- Flush tty input buffer */
3180:
3181: int
3182: ttflui() {
3183: int ffd;
3184:
3185: #ifndef SVORPOSIX
3186: int n;
3187: #endif /* SVORPOSIX */
3188: #ifdef NETCONN
3189: if (netconn) return(netflui());
3190: #endif /* NETCONN */
3191:
3192: ffd = xlocal ? ttyfd : 0; /* If not local, use stdin */
3193: debug(F101,"ttflui xlocal","",xlocal);
3194: debug(F101,"ttflui ttyfd","",ttyfd);
3195: debug(F101,"ttflui ffd","",ffd);
3196: if (ffd < 0) return(-1);
3197:
3198: #ifdef MYREAD
3199: my_count = 0; /* Initialize myread() stuff */
3200: my_item = -1;
3201: #endif /* MYREAD */
3202:
3203: #ifdef aegis
3204: sio_$control((short)ffd, sio_$flush_in, true, st);
3205: if (st.all != status_$ok) {
3206: fprintf(stderr, "flush failed: "); error_$print(st);
3207: } else { /* sometimes the flush doesn't work */
3208: for (;;) {
3209: char buf[256];
3210: /* eat all the characters that shouldn't be available */
3211: ios_$get((short)ffd, ios_$cond_opt, buf, 256L, st); /* (void) */
3212: if (st.all == ios_$get_conditional_failed) break;
3213: fprintf(stderr, "flush failed(2): "); error_$print(st);
3214: }
3215: }
3216: #else
3217: #ifdef ATTSV
3218: #ifndef VXVE
3219: ioctl(ffd,TCFLSH,0);
3220: #endif /* VXVE */
3221: #else /* POSIX */
3222: #ifdef POSIX
3223: tcflush(ttyfd,TCIFLUSH);
3224: #else /* Berkeley and others */
3225: #ifdef TIOCFLUSH
3226: #ifdef ANYBSD
3227: n = FREAD; /* Specify read queue */
3228: debug(F101,"ttflui anybsd flush","",ffd);
3229: ioctl(ffd,TIOCFLUSH,&n);
3230: #else
3231: ioctl(ffd,TIOCFLUSH,0);
3232: #endif /* ANYBSD */
3233: #endif /* TIOCFLUSH */
3234: #endif /* POSIX */
3235: #endif /* aegis */
3236: #endif
3237: return(0);
3238: }
3239:
3240: int
3241: ttfluo() { /* Flush output buffer */
3242: #ifdef POSIX
3243: return(tcflush(ttyfd,TCOFLUSH));
3244: #else
3245: return(0); /* (dummy for now) */
3246: #endif /* POSIX */
3247:
3248: }
3249:
3250: /* Interrupt Functions */
3251:
3252: /* Set up terminal interrupts on console terminal */
3253:
3254: #ifdef SVORPOSIX
3255: SIGTYP
3256: esctrp(foo) int foo; { /* trap console escapes (^\) */
3257: conesc = 1;
3258: signal(SIGQUIT,SIG_IGN); /* ignore until trapped */
3259: }
3260: #endif /* SVORPOSIX */
3261:
3262: #ifdef V7
3263: SIGTYP
3264: esctrp(foo) int foo; { /* trap console escapes (^\) */
3265: conesc = 1;
3266: signal(SIGQUIT,SIG_IGN); /* ignore until trapped */
3267: }
3268: #endif
3269:
3270: #ifdef C70
3271: SIGTYP
3272: esctrp(foo) int foo; { /* trap console escapes (^\) */
3273: conesc = 1;
3274: signal(SIGQUIT,SIG_IGN); /* ignore until trapped */
3275: }
3276: #endif
3277:
3278: /* C O N B G T -- Background Test */
3279:
3280: static int jc; /* 0 = no job control */
3281:
3282: VOID
3283: conbgt() {
3284: int x = -1, /* process group or SIGINT test */
3285: y = 0; /* isatty() test */
3286:
3287: /*
3288: Check for background operation, even if not running on real tty, so that
3289: background flag can be set correctly. If background status is detected,
3290: then Kermit will not issue its interactive prompt or most messages.
3291: If your prompt goes away, you can blame (and fix?) this function.
3292: */
3293:
3294: /* Use process-group test if possible. */
3295:
3296: #ifdef POSIX /* We can do it in POSIX */
3297: #define PGROUP_T
3298: #else
3299: #ifdef BSD4 /* and in BSD 4.x. */
3300: #define PGROUP_T
3301: #else
3302: #ifdef HPUXJOBCTL /* and in most HP-UX's */
3303: #define PGROUP_T
3304: #else
3305: #ifdef TIOCGPGRP /* and anyplace that has this ioctl. */
3306: #define PGROUP_T
3307: #endif /* TIOCGPGRP */
3308: #endif /* HPUXJOBCTL */
3309: #endif /* BSD4 */
3310: #endif /* POSIX */
3311:
3312: #ifdef MIPS /* Except if it doesn't work... */
3313: #undef PGROUP_T
3314: #endif /* MIPS */
3315:
3316: #ifdef PGROUP_T
3317: /*
3318: Semi-reliable process-group test. Check whether this process's group is
3319: the same as the controlling terminal's process group. This works if the
3320: getpgrp() call doesn't lie (as it does in the SUNOS System V environment).
3321: */
3322: PID_T mypgrp; /* Kermit's process group */
3323: PID_T ctpgrp; /* The terminal's process group */
3324: #ifndef _POSIX_SOURCE
3325: /*
3326: The getpgrp() prototype is obtained from system header files for POSIX
3327: and Sys V R4 compilations. Other systems, who knows. Some complain about
3328: a duplicate declaration here, others don't, so it's safer to leave it in
3329: if we don't know for certain.
3330: */
3331: #ifndef SVR4
3332: #ifndef PS2AIX10
3333: extern PID_T getpgrp();
3334: #endif /* PS2AIX10 */
3335: #endif /* SVR4 */
3336: #endif /* _POSIX_SOURCE */
3337:
3338: /* Get my process group. */
3339:
3340: #ifdef SVR3 /* Maybe this should be ATTSV? */
3341: /* This function is not described in SVID R2 */
3342: mypgrp = getpgrp();
3343: debug(F101,"ATTSV conbgt process group","",(int) mypgrp);
3344: #else
3345: #ifdef POSIX
3346: mypgrp = getpgrp();
3347: debug(F101,"POSIX conbgt process group","",(int) mypgrp);
3348: #else /* BSD, V7, etc */
3349: mypgrp = getpgrp(0);
3350: debug(F101,"BSD conbgt process group","",(int) mypgrp);
3351: #endif /* POSIX */
3352: #endif /* SVR3 */
3353:
3354: /* Now get controlling tty's process group */
3355: #ifdef POSIX
3356: ctpgrp = tcgetpgrp(1); /* The POSIX way */
3357: debug(F101,"POSIX conbgt terminal process group","",(int) ctpgrp);
3358: #else
3359: ioctl(1, TIOCGPGRP, &ctpgrp); /* Or the BSD way */
3360: debug(F101,"non-POSIX conbgt terminal process group","",(int) ctpgrp);
3361: #endif /* POSIX */
3362:
3363: if ((mypgrp > (PID_T) 0) && (ctpgrp > (PID_T) 0))
3364: x = (mypgrp == ctpgrp) ? 0 : 1; /* If they differ, then background. */
3365: else x = -1; /* If error, remember. */
3366: debug(F101,"conbgt process group test","",x);
3367: #endif /* PGROUP_T */
3368:
3369: /* Try to see if job control is available */
3370:
3371: #ifdef NOJC /* User override */
3372: jc = 0; /* No job control allowed */
3373: debug(F111,"NOJC","jc",jc);
3374: #else
3375: #ifdef SVR4ORPOSIX /* POSIX actually tells us */
3376: debug(F100,"SVR4ORPOSIX jc test...","",0);
3377: #ifdef _SC_JOB_CONTROL
3378: jc = sysconf(_SC_JOB_CONTROL); /* Whatever system says */
3379: debug(F111,"sysconf(_SC_JOB_CONTROL)","jc",jc);
3380: #else
3381: #ifdef _POSIX_JOB_CONTROL
3382: jc = 1; /* By definition */
3383: debug(F111,"_POSIX_JOB_CONTROL is defined","jc",jc);
3384: #else
3385: jc = 0; /* Assume job control allowed */
3386: debug(F111,"SVR4ORPOSIX _SC/POSIX_JOB_CONTROL not defined","jc",jc);
3387: #endif /* _POSIX_JOB_CONTROL */
3388: #endif /* _SC_JOB_CONTROL */
3389: #else
3390: #ifdef BSD4
3391: jc = 1; /* Job control allowed */
3392: debug(F111,"BSD job control","jc",jc);
3393: #else
3394: jc = 0;
3395: debug(F111,"job control catch-all","jc",jc);
3396: #endif /* BSD4 */
3397: #endif /* SVR4ORPOSIX */
3398: #endif /* NOJC */
3399: debug(F101,"conbgt jc","",jc);
3400:
3401: /*
3402: Another background test.
3403: Test if SIGINT (terminal interrupt) is set to SIG_IGN (ignore),
3404: which is done by the shell (sh) if the program is started with '&'.
3405: Unfortunately, this is NOT done by csh or ksh so watch out!
3406: Note, it's safe to set SIGINT to SIG_IGN here, because further down
3407: we always set it to something else.
3408: */
3409: if (x < 0) { /* Didn't get good results above... */
3410:
3411: SIGTYP (*osigint)();
3412:
3413: osigint = signal(SIGINT,SIG_IGN); /* What is SIGINT set to? */
3414: x = (osigint == SIG_IGN) ? 1 : 0; /* SIG_IGN? */
3415: debug(F101,"conbgt osigint","",(int) osigint);
3416: debug(F101,"conbgt signal test","",x);
3417: }
3418:
3419: /* Also check to see if we're running with redirected stdio. */
3420: /* This is not really background operation, but we want to act as though */
3421: /* it were. */
3422:
3423: y = (isatty(0) && isatty(1)) ? 1 : 0;
3424: debug(F101,"conbgt isatty test","",y);
3425:
3426: #ifdef BSD29
3427: /* The process group and/or signal test doesn't work under these... */
3428: backgrd = !y;
3429: #else
3430: #ifdef sxaE50
3431: backgrd = !y;
3432: #else
3433: #ifdef MINIX
3434: backgrd = !y;
3435: #else
3436: backgrd = (x || !y) ? 1 : 0;
3437: #endif /* BSD29 */
3438: #endif /* sxaE50 */
3439: #endif /* MINIX */
3440: debug(F101,"conbgt backgrd","",backgrd);
3441: }
3442:
3443: /* C O N I N T -- Console Interrupt setter */
3444:
3445: /*
3446: First arg is pointer to function to handle SIGTERM & SIGINT (like Ctrl-C).
3447: Second arg is pointer to function to handle SIGTSTP (suspend).
3448: */
3449:
3450: VOID /* Set terminal interrupt traps. */
3451: #ifdef CK_ANSIC
3452: #ifdef apollo
3453: conint(f,s) SIGTYP (*f)(), (*s)();
3454: #else
3455: conint(SIGTYP (*f)(int), SIGTYP (*s)(int))
3456: #endif /* apollo */
3457: #else
3458: conint(f,s) SIGTYP (*f)(), (*s)();
3459: #endif /* CK_ANSIC */
3460: /* conint */ {
3461:
3462: conbgt(); /* Do background test. */
3463:
3464: /* Set the desired handlers for hangup and software termination. */
3465:
3466: signal(SIGHUP,f); /* Hangup */
3467: signal(SIGTERM,f); /* Software termination */
3468:
3469: /* Now handle keyboard stop, quit, and interrupt signals. */
3470: /* Check if invoked in background -- if so signals set to be ignored. */
3471: /* However, if running under a job control shell, don't ignore them. */
3472: /* We won't be getting any, as we aren't in the terminal's process group. */
3473:
3474: debug(F101,"conint backgrd","",backgrd);
3475: debug(F101,"conint jc","",jc);
3476:
3477: if (backgrd && !jc) { /* In background, ignore signals */
3478: debug(F101,"conint background ignoring signals, jc","",jc);
3479: #ifdef SIGTSTP
3480: signal(SIGTSTP,SIG_IGN); /* Keyboard stop */
3481: #endif /* SIGTSTP */
3482: signal(SIGQUIT,SIG_IGN); /* Keyboard quit */
3483: signal(SIGINT,SIG_IGN); /* Keyboard interrupt */
3484: } else { /* Else in foreground or suspended */
3485: debug(F101,"conint foreground catching signals, jc","",jc);
3486: signal(SIGINT,f); /* Catch terminal interrupt */
3487:
3488: #ifdef SIGTSTP /* Keyboard stop (suspend) */
3489: debug(F101,"conint SIGSTSTP","",(int) s);
3490: if (s == NULL) s = SIG_DFL;
3491: #ifdef NOJC /* No job control allowed. */
3492: signal(SIGTSTP,SIG_IGN);
3493: #else /* Job control allowed */
3494: if (jc) /* if available. */
3495: signal(SIGTSTP,s);
3496: else
3497: signal(SIGTSTP,SIG_IGN);
3498: #endif /* NOJC */
3499: #endif /* SIGTSTP */
3500:
3501: #ifdef SVORPOSIX
3502: signal(SIGQUIT,esctrp); /* Quit signal, Sys III/V. */
3503: if (conesc) conesc = 0; /* Clear out pending escapes */
3504: #else
3505: #ifdef V7
3506: signal(SIGQUIT,esctrp); /* V7 like Sys III/V */
3507: if (conesc) conesc = 0;
3508: #else
3509: #ifdef aegis
3510: signal(SIGQUIT,f); /* Apollo, catch it like others. */
3511: #else
3512: signal(SIGQUIT,SIG_IGN); /* Others, ignore like 4D & earlier. */
3513: #endif /* aegis */
3514: #endif /* V7 */
3515: #endif /* SVORPOSIX */
3516: }
3517: }
3518:
3519:
3520: /* C O N N O I -- Reset console terminal interrupts */
3521:
3522: SIGTYP /* Dummy function to ignore signals */
3523: #ifdef CK_ANSIC
3524: sig_ign(int foo)
3525: #else
3526: sig_ign(foo) int foo;
3527: #endif /* CK_ANSIC */
3528: /* sig_IGN */ { /* Just like the real one, but has */
3529: } /* different address. */
3530:
3531: VOID
3532: connoi() { /* Console-no-interrupts */
3533:
3534: debug(F100,"connoi","",0);
3535: #ifdef SIGTSTP
3536: signal(SIGTSTP,SIG_DFL);
3537: #endif /* SIGTSTP */
3538: /* Note the locally defined replacement for SIG_IGN that is used here */
3539: /* for the SIGINT setting. This is done so that the Sys V background */
3540: /* test -- (signal(SIGINT,SIG_IGN) == SIG_IGN) -- can work. If we use */
3541: /* the real SIG_IGN here, then conint will always decide that this */
3542: /* program is running in the background! */
3543:
3544: signal(SIGINT,sig_ign); /* <--- note! */
3545:
3546: signal(SIGHUP,SIG_DFL);
3547: signal(SIGQUIT,SIG_IGN);
3548: signal(SIGTERM,SIG_IGN);
3549: }
3550:
3551: /* I N I T R A W Q -- Set up to read /dev/kmem for character count. */
3552:
3553: #ifdef V7
3554: /*
3555: Used in Version 7 to simulate Berkeley's FIONREAD ioctl call. This
3556: eliminates blocking on a read, because we can read /dev/kmem to get the
3557: number of characters available for raw input. If your system can't
3558: or you won't let the world read /dev/kmem then you must figure out a
3559: different way to do the counting of characters available, or else replace
3560: this by a dummy function that always returns 0.
3561: */
3562: /*
3563: * Call this routine as: initrawq(tty)
3564: * where tty is the file descriptor of a terminal. It will return
3565: * (as a char *) the kernel-mode memory address of the rawq character
3566: * count, which may then be read. It has the side-effect of flushing
3567: * input on the terminal.
3568: */
3569: /*
3570: * John Mackin, Physiology Dept., University of Sydney (Australia)
3571: * ...!decvax!mulga!physiol.su.oz!john
3572: *
3573: * Permission is hereby granted to do anything with this code, as
3574: * long as this comment is retained unmodified and no commercial
3575: * advantage is gained.
3576: */
3577: #ifndef MINIX
3578: #ifndef COHERENT
3579: #include <a.out.h>
3580: #include <sys/proc.h>
3581: #endif /* COHERENT */
3582: #endif /* MINIX */
3583:
3584: #ifdef COHERENT
3585: #include <l.out.h>
3586: #include <sys/proc.h>
3587: #endif /* COHERENT */
3588:
3589: char *
3590: initrawq(tty) int tty; {
3591: #ifdef MINIX
3592: return(0);
3593: #else
3594: #ifdef UTS24
3595: return(0);
3596: #else
3597: #ifdef BSD29
3598: return(0);
3599: #else
3600: long lseek();
3601: static struct nlist nl[] = {
3602: {PROCNAME},
3603: {NPROCNAME},
3604: {""}
3605: };
3606: static struct proc *pp;
3607: char *qaddr, *p, c;
3608: int m;
3609: PID_T pid, me;
3610: NPTYPE xproc; /* Its type is defined in makefile. */
3611: int catch();
3612:
3613: me = getpid();
3614: if ((m = open("/dev/kmem", 0)) < 0) err("kmem");
3615: nlist(BOOTNAME, nl);
3616: if (nl[0].n_type == 0) err("proc array");
3617:
3618: if (nl[1].n_type == 0) err("nproc");
3619:
3620: lseek(m, (long)(nl[1].n_value), 0);
3621: read (m, &xproc, sizeof(xproc));
3622: saval = signal(SIGALRM, catch);
3623: if ((pid = fork()) == 0) {
3624: while(1)
3625: read(tty, &c, 1);
3626: }
3627: alarm(2);
3628:
3629: if(setjmp(jjbuf) == 0) {
3630: while(1)
3631: read(tty, &c, 1);
3632: }
3633: signal(SIGALRM, SIG_DFL);
3634:
3635: #ifdef DIRECT
3636: pp = (struct proc *) nl[0].n_value;
3637: #else
3638: if (lseek(m, (long)(nl[0].n_value), 0) < 0L) err("seek");
3639: if (read(m, &pp, sizeof(pp)) != sizeof(pp)) err("no read of proc ptr");
3640: #endif
3641: lseek(m, (long)(nl[1].n_value), 0);
3642: read(m, &xproc, sizeof(xproc));
3643:
3644: if (lseek(m, (long)pp, 0) < 0L) err("Can't seek to proc");
3645: if ((p = malloc(xproc * sizeof(struct proc))) == NULL) err("malloc");
3646: if (read(m,p,xproc * sizeof(struct proc)) != xproc*sizeof(struct proc))
3647: err("read proc table");
3648: for (pp = (struct proc *)p; xproc > 0; --xproc, ++pp) {
3649: if (pp -> p_pid == (short) pid) goto iout;
3650: }
3651: err("no such proc");
3652:
3653: iout:
3654: close(m);
3655: qaddr = (char *)(pp -> p_wchan);
3656: free (p);
3657: kill(pid, SIGKILL);
3658: wait((WAIT_T)0); /* Destroy the ZOMBIEs! */
3659: return (qaddr);
3660: #endif
3661: #endif
3662: #endif
3663: }
3664:
3665: /* More V7-support functions... */
3666:
3667: static VOID
3668: err(s) char *s; {
3669: char buf[200];
3670:
3671: sprintf(buf, "fatal error in initrawq: %s", s);
3672: perror(buf);
3673: doexit(1,-1);
3674: }
3675:
3676: static VOID
3677: catch(foo) int foo; {
3678: longjmp(jjbuf, -1);
3679: }
3680:
3681:
3682: /* G E N B R K -- Simulate a modem break. */
3683:
3684: #ifdef MINIX
3685: #define BSPEED B110
3686: #else
3687: #define BSPEED B150
3688: #endif /* MINIX */
3689:
3690: VOID
3691: genbrk(fn,msec) int fn, msec; {
3692: struct sgttyb ttbuf;
3693: int ret, sospeed, x, y;
3694:
3695: ret = ioctl(fn, TIOCGETP, &ttbuf);
3696: sospeed = ttbuf.sg_ospeed;
3697: ttbuf.sg_ospeed = BSPEED;
3698: ret = ioctl(fn, TIOCSETP, &ttbuf);
3699: y = (int)strlen(brnuls);
3700: x = ( BSPEED * 100 ) / msec;
3701: if (x > y) x = y;
3702: ret = write(fn, brnuls, (( BSPEED * 100 ) / msec ));
3703: ttbuf.sg_ospeed = sospeed;
3704: ret = ioctl(fn, TIOCSETP, &ttbuf);
3705: ret = write(fn, "@", 1);
3706: return;
3707: }
3708: #endif /* V7 */
3709:
3710: /* T T C H K -- Tell how many characters are waiting in tty input buffer */
3711:
3712: /* Some callers of this want to know whether there is something to read
3713: * either in the system buffers or in our private buffers (and mostly don't
3714: * care how many characters, just whether it's more than zero or not), while
3715: * some others would be better off with the number of characters in our
3716: * private buffers only.
3717: *
3718: * Some systems can say how many characters there are in the system buffers.
3719: * Others can not. For those that can't, the number in the private buffers
3720: * will have to do (or should we put the tty into O_NDELAY-mode and try to
3721: * read one character?). If the system can tell whether there is zero or
3722: * more than zero characters, we can return 1 in the latter case even if the
3723: * private buffer is empty. (That is good for sliding windows.)
3724: */
3725: int
3726: ttchk() {
3727: int x;
3728: PEEKTYPE n = 0;
3729:
3730: #ifdef NETCONN
3731: if (netconn) return(nettchk());
3732: #endif /* NETCONN */
3733:
3734: #ifdef FIONREAD
3735: x = ioctl(ttyfd, FIONREAD, &n); /* Berkeley and maybe some others */
3736: debug(F101,"ttchk","",n);
3737: if (x < 0) n = 0;
3738: #else
3739: #ifdef V7
3740: #ifdef MINIX
3741: return(0);
3742: #else
3743: lseek(kmem[TTY], (long) qaddr[TTY], 0); /* 7th Edition Unix */
3744: x = read(kmem[TTY], &n, sizeof(int));
3745: if (x != sizeof(int)) n = 0;
3746: #endif /* MINIX */
3747: #else
3748: #ifdef PROVX1
3749: x = ioctl(ttyfd, TIOCQCNT, &ttbuf); /* Pro/3xx Venix V.1 */
3750: n = ttbuf.sg_ispeed & 0377;
3751: if (x < 0) n = 0;
3752: #else
3753: #ifdef RDCHK
3754: /* Last resort for systems without FIONREAD or equivalent, but with
3755: * something like rdchk(), like XENIX.
3756: */
3757: if (my_count == 0 && rdchk(ttyfd) > 0) n = 1;
3758: #endif /* RDCHK */
3759: #endif /* PROVX1 */
3760: #endif /* V7 */
3761: #endif /* FIONREAD */
3762:
3763: #ifdef MYREAD
3764: /* For myread() users, add the contents of myread()'s private buffer.
3765: * Sometimes, this is all there is to construct a result of ttchk() on.
3766: */
3767: if (my_count > 0) /* Sys III, Sys V, Apollo Aegis, etc */
3768: n += my_count;
3769: #endif /* MYREAD */
3770:
3771: debug(F101,"ttchk","",n);
3772: return(n);
3773: }
3774:
3775: /* T T X I N -- Get n characters from tty input buffer */
3776:
3777: /* Returns number of characters actually gotten, or -1 on failure */
3778:
3779: /* Intended for use only when it is known that n characters are actually */
3780: /* Available in the input buffer. */
3781:
3782: int
3783: ttxin(n,buf) int n; CHAR *buf; {
3784: register int x, c;
3785:
3786: ttpmsk = (ttprty) ? 0177 : 0377; /* Parity stripping mask. */
3787: debug(F101,"ttxin n","",n);
3788: #ifdef SUNX25
3789: if (netconn && (ttnet == NET_SX25)) /* X.25 connection */
3790: return(x25xin(n,buf));
3791: #endif /* SUNX25 */
3792:
3793: #ifdef MYREAD
3794: for( x = 0; (x > -1) && (x < n) && (c = myread()) >= 0; )
3795: buf[x++] = c & ttpmsk;
3796: #else
3797: x = read(ttyfd,buf,n);
3798: for (c = 0; c < n; c++) buf[c] &= ttpmsk;
3799: debug(F101," x","",x);
3800: #endif /* MYREAD */
3801: if (x > 0) buf[x] = '\0';
3802: if (x < 0) x = -1;
3803: return(x);
3804: }
3805:
3806: /* T T O L -- Write string s, length n, to communication device. */
3807: /*
3808: Returns:
3809: >= 0 on success, number of characters actually written.
3810: -1 on failure.
3811: */
3812: #define TTOLMAXT 5
3813: int
3814: ttol(s,n) int n; CHAR *s; {
3815: int x, len, tries;
3816:
3817: if (ttyfd < 0) return(-1); /* Not open? */
3818: debug(F101,"ttol n","",n);
3819: tries = TTOLMAXT; /* Allow up to this many tries */
3820: len = n; /* Remember original length */
3821:
3822: while (n > 0 && tries-- > 0) { /* Be persistent */
3823: debug(F101,"ttol try","",TTOLMAXT - tries);
3824: x = write(ttyfd,s,n); /* Write string to device */
3825: if (x == n) { /* Worked? */
3826: debug(F101,"ttol ok","",x); /* OK */
3827: return(len); /* Done */
3828: } else if (x < 0) { /* No, got error? */
3829: debug(F101,"ttol failed","",errno);
3830: return(-1);
3831: } else { /* No error, so partial success */
3832: debug(F101,"ttol partial","",x);
3833: s += x; /* Point to part not written yet */
3834: n -= x; /* Adjust length */
3835: if (x > 0) msleep(100); /* Wait 100 msec */
3836: } /* Go back and try again */
3837: }
3838: return(n < 1 ? len : -1); /* Too many tries */
3839: }
3840:
3841:
3842:
3843: /* T T O C -- Output a character to the communication line */
3844:
3845: /*
3846: This function should only be used for interactive, character-mode operations,
3847: like terminal connection, script execution, dialer i/o, where the overhead
3848: of the signals and alarms does not create a bottleneck.
3849: */
3850: int
3851: #ifdef CK_ANSIC
3852: ttoc(char c)
3853: #else
3854: ttoc(c) char c;
3855: #endif /* CK_ANSIC */
3856: /* ttoc */ {
3857: c &= 0xff;
3858: /* debug(F101,"ttoc","",(CHAR) c); */
3859: if (ttyfd < 0) return(-1); /* Check for not open. */
3860: saval = signal(SIGALRM,timerh); /* Enable timer interrupt */
3861: alarm(2); /* for 2 seconds. */
3862: if (setjmp(sjbuf)) { /* Timer went off? */
3863: ttimoff(); /* Yes, turn off the alarm. */
3864: conoc('\07'); /* Ring the bell. */
3865: debug(F100,"ttoc timed out","",0); /* Log a message. */
3866: if (ttflow == FLO_XONX) {
3867: debug(F100,"ttoc flow","",ttflow); /* Maybe we're xoff'd */
3868: #ifdef POSIX
3869: debug(F100,"ttoc tcflow","",0); /* POSIX way to unstick. */
3870: tcflow(ttyfd,TCOON);
3871: #else
3872: #ifdef BSD4 /* Berkeley way to do it. */
3873: #ifdef TIOCSTART
3874: debug(F100,"ttoc TIOCSTART","",0);
3875: ioctl(ttyfd, TIOCSTART, 0);
3876: #endif /* TIOCSTART */
3877: #endif /* BSD4 */
3878: #endif /* POSIX */
3879: }
3880: return(-1); /* Return failure code. */
3881: } else {
3882: if (write(ttyfd,&c,1) < 1) { /* Try to write the character. */
3883: ttimoff(); /* If error, turn off timer, */
3884: conoc('\07'); /* ring the bell, */
3885: debug(F101,"ttoc error","",errno); /* log the error, */
3886: return(-1); /* and return the error code. */
3887: }
3888: }
3889: ttimoff(); /* Success, turn off timer. */
3890: return(0);
3891: }
3892:
3893: /* T T I N L -- Read a record (up to break character) from comm line. */
3894: /*
3895: Reads up to "max" characters from the communication line, terminating on:
3896:
3897: (a) the packet length field if the "turn" argument is zero, or
3898: (b) on the packet-end character (eol) if the "turn" argument is nonzero
3899:
3900: and returns the number of characters read upon success, or if "max" was
3901: exceeded or the timeout interval expired before (a) or (b), returns -1.
3902:
3903: The characters that were input are copied into "dest" with their parity bits
3904: stripped if parity was selected. Returns the number of characters read.
3905: Characters after the eol are available upon the next call to this function.
3906:
3907: The idea is to minimize the number of system calls per packet, and also to
3908: minimize timeouts. This function is the inner loop of the program and must
3909: be as efficient as possible. The current strategy is to use myread().
3910:
3911: WARNING: this function calls parchk(), which is defined in another module.
3912: Normally, ckutio.c does not depend on code from any other module, but there
3913: is an exception in this case because all the other ck?tio.c modules also
3914: need to call parchk(), so it's better to have it defined in a common place.
3915: */
3916: #ifdef CTRLC
3917: #undef CTRLC
3918: #endif /* CTRLC */
3919: #define CTRLC '\03'
3920: /*
3921: We have four different declarations here because:
3922: (a) to allow Kermit to be built without the automatic parity sensing feature
3923: (b) one of each type for ANSI C, one for non-ANSI.
3924: */
3925: int
3926: #ifdef PARSENSE
3927: #ifdef CK_ANSIC
3928: ttinl(CHAR *dest, int max,int timo, CHAR eol, CHAR start, int turn)
3929: #else
3930: ttinl(dest,max,timo,eol,start,turn) int max,timo,turn; CHAR *dest, eol, start;
3931: #endif /* CK_ANSIC */
3932: #else /* not PARSENSE */
3933: #ifdef CK_ANSIC
3934: ttinl(CHAR *dest, int max,int timo, CHAR eol)
3935: #else
3936: ttinl(dest,max,timo,eol) int max,timo; CHAR *dest, eol;
3937: #endif /* __SDTC__ */
3938: #endif /* PARSENSE */
3939: /* ttinl */ {
3940:
3941: #ifndef MYREAD
3942: CHAR ch;
3943: #endif /* MYREAD */
3944: #ifdef PARSENSE
3945: int pktlen = -1;
3946: int lplen = 0;
3947: int havelen = 0;
3948: #endif /* PARSENSE */
3949:
3950: if (ttyfd < 0) return(-1); /* Not open. */
3951:
3952: debug(F101,"ttinl max","",max);
3953: debug(F101,"ttinl timo","",timo);
3954:
3955: *dest = '\0'; /* Clear destination buffer */
3956: if (timo < 0) timo = 0; /* Safety */
3957: if (timo) { /* Don't time out if timo == 0 */
3958: saval = signal(SIGALRM,timerh); /* Enable timer interrupt */
3959: alarm(timo); /* Set it. */
3960: }
3961: if (setjmp(sjbuf)) { /* Timer went off? */
3962: debug(F100,"ttinl timout","",0); /* Get here on timeout. */
3963: debug(F110," with",(char *) dest,0);
3964: ttimoff(); /* Turn off timer */
3965: return(-1); /* and return error code. */
3966: } else {
3967: register int i, m, n; /* local variables */
3968: int ccn = 0;
3969: #ifdef PARSENSE
3970: int flag = 0;
3971:
3972: debug(F000,"ttinl start","",start);
3973: flag = 0; /* Start of packet flag */
3974: #endif /* PARSENSE */
3975:
3976: ttpmsk = m = (ttprty) ? 0177 : 0377; /* Set parity stripping mask. */
3977:
3978: #ifdef SUNX25
3979: if (netconn && (ttnet == NET_SX25))
3980: #ifdef PARSENSE
3981: return(x25inl(dest,max,timo,eol,start));
3982: #else
3983: return(x25inl(dest,max,timo,eol));
3984: #endif /* PARSENSE */
3985: #endif /* SUNX25 */
3986:
3987: /* Now read into destination, stripping parity and looking for the */
3988: /* the packet terminator, and also for two Ctrl-C's typed in a row. */
3989:
3990: i = 0; /* Destination index */
3991: debug(F101,"ttinl eol","",eol);
3992:
3993: #ifdef MYREAD
3994: while (i < max-1) {
3995: /* debug(F101,"ttinl i","",i); */
3996: if ((n = myread()) < 0) {
3997: debug(F101,"ttinl myread failure, n","",n);
3998: debug(F101,"ttinl myread errno,","",errno);
3999: /* Don't let EINTR break packets. */
4000: if (n == -3 && errno == EINTR && i > 0) {
4001: debug(F101,"ttinl myread i","",i);
4002: continue;
4003: }
4004: break;
4005: }
4006: #else
4007: while ((i < max-1) && (n = read(ttyfd, &ch, 1)) > 0) {
4008: n = ch;
4009: #endif /* MYREAD */
4010:
4011: /* debug(F101,"ttinl char","", (n & ttpmsk)); */
4012:
4013: #ifdef PARSENSE
4014: /*
4015: Figure out what the length is supposed to be in case the packet
4016: has no terminator (as with Honeywell GCOS-8 Kermit).
4017: */
4018: #ifndef xunchar
4019: #define xunchar(ch) (((ch) - 32 ) & 0xFF ) /* Character to number */
4020: #endif /* xunchar */
4021: if ((flag == 0) && ((n & 0x7f) == start)) flag = 1;
4022: if (flag) dest[i++] = n & ttpmsk;
4023: /*
4024: If we have not been instructed to wait for a turnaround character, we
4025: can go by the packet length field. If turn != 0, we must wait for the
4026: end of line (eol) character before returning.
4027: */
4028: if (i == 2) {
4029: pktlen = xunchar(dest[1]);
4030: havelen = (pktlen > 1);
4031: debug(F101,"ttinl length","",pktlen);
4032: } else if (i == 5 && pktlen == 0) {
4033: lplen = xunchar(dest[4]);
4034: } else if (i == 6 && pktlen == 0) {
4035: pktlen = lplen * 95 + xunchar(dest[5]) + 5;
4036: havelen = 1;
4037: debug(F101,"ttinl length","",pktlen);
4038: }
4039: #else
4040: dest[i++] = n & ttpmsk;
4041: #endif /* PARSENSE */
4042: if ((n & 0x7f) == CTRLC) { /* Check for ^C^C */
4043: if (++ccn > 1) { /* If we got 2 in a row, bail out. */
4044: if (timo) { /* Clear timer. */
4045: ttimoff();
4046: }
4047: fprintf(stderr,"^C...\r\n"); /* Echo Ctrl-C */
4048: return(-2);
4049: }
4050: } else ccn = 0; /* Not ^C, so reset ^C counter, */
4051:
4052: #ifdef PARSENSE
4053: if (flag == 0) {
4054: debug(F101,"ttinl skipping","",n);
4055: continue;
4056: }
4057: #endif /* PARSENSE */
4058:
4059: /* Check for end of packet */
4060:
4061: if (((n & 0x7f) == eol)
4062: #ifdef PARSENSE
4063: || (!turn && havelen && (i > pktlen+1))
4064: #endif /* PARSENSE */
4065: ) {
4066: #ifndef PARSENSE
4067: debug(F101,"ttinl got eol","",eol);
4068: dest[i] = '\0'; /* Yes, terminate the string, */
4069: /* debug(F101,"ttinl i","",i); */
4070: #else
4071: if ((n & 0x7f) != eol) {
4072: debug(F101,"ttinl EOP length","",pktlen);
4073: debug(F101,"ttinl i","",i);
4074: } else debug(F101,"ttinl got eol","",eol);
4075: dest[i] = '\0'; /* Terminate the string, */
4076:
4077: /* Here's where we actually check and adjust the parity. */
4078: /* The major flaw here is if parity is NONE (ttprty = 0) and the packets */
4079: /* really do have no parity, then parchk() is called for every packet. */
4080: /* In practice, this doesn't really harm efficiency noticably, but it would */
4081: /* be better if ttinl() had a way of knowing to stop doing this once a */
4082: /* particular file transfer had been started and checked. */
4083: if (ttprty == 0) {
4084: if ((ttprty = parchk(dest,start,i)) > 0) {
4085: int j;
4086: debug(F101,"ttinl senses parity","",ttprty);
4087: debug(F110,"ttinl packet before",dest,0);
4088: ttpmsk = 0x7f;
4089: for (j = 0; j < i; j++)
4090: dest[j] &= 0x7f; /* Strip parity from packet */
4091: debug(F110,"ttinl packet after ",dest,0);
4092: } else debug(F101,"parchk","",ttprty);
4093: }
4094: #endif /* PARSENSE */
4095: if (timo) { /* Turn off timer. */
4096: ttimoff();
4097: }
4098: debug(F111,"ttinl got", dest,i);
4099: return(i);
4100: }
4101: } /* end of while() */
4102: ttimoff();
4103: return(-1);
4104: }
4105: }
4106:
4107: /* T T I N C -- Read a character from the communication line */
4108: /*
4109: On success, returns the character that was read, >= 0.
4110: On failure, returns -1 or other negative myread error code.
4111: */
4112: int
4113: ttinc(timo) int timo; {
4114:
4115: int n = 0;
4116: #ifndef MYREAD
4117: CHAR ch = 0;
4118: #endif /* MYREAD */
4119:
4120: if (ttyfd < 0) return(-1); /* Not open. */
4121: if (timo <= 0) { /* Untimed. */
4122: #ifdef MYREAD
4123: /* comm line failure returns -1 thru myread, so no &= 0377 */
4124: n = myread(); /* Wait for a character... */
4125: /* debug(F101,"ttinc n","",n); */
4126: return(n < 0 ? n : n & ttpmsk);
4127: #else
4128: while ((n = read(ttyfd,&ch,1)) == 0) /* Wait for a character. */
4129: /* Shouldn't have to loop in ver 5A. */
4130: #ifdef NETCONN
4131: if (netconn) { /* Special handling for net */
4132: netclos();
4133: netconn = 0;
4134: errno = ENOTCONN;
4135: return(-2);
4136: }
4137: #endif /* NETCONN */
4138: ;
4139: /* debug(F000,"ttinc","",ch); */
4140: return( (n < 1) ? -3 : (ch & ttpmsk) );
4141: #endif /* MYREAD */
4142: } else {
4143: saval = signal(SIGALRM,timerh); /* Timed, set up timer. */
4144: alarm(timo);
4145: if (setjmp(sjbuf)) {
4146: n = -1;
4147: } else {
4148: #ifdef MYREAD
4149: n = myread(); /* If managing own buffer... */
4150: debug(F101,"ttinc myread","",n);
4151: #else
4152: n = read(ttyfd,&ch,1); /* Otherwise call the system. */
4153: debug(F101,"ttinc read","",n);
4154: if (n > 0)
4155: n = ch & 255;
4156: else
4157: n = (n < 0) ? -3 : -2; /* Special return codes */
4158: #endif /* MYREAD */
4159: }
4160: ttimoff(); /* Turn off timer */
4161: #ifdef NETCONN
4162: if (netconn) {
4163: if (n == -2) { /* read() returns 0 */
4164: netclos(); /* on network read failure */
4165: netconn = 0;
4166: errno = ENOTCONN;
4167: }
4168: }
4169: #endif /* NETCONN */
4170: return( (n < 0) ? n : (n & ttpmsk) ); /* Return masked char or neg. */
4171: }
4172: }
4173:
4174: /* S N D B R K -- Send a BREAK signal of the given duration */
4175:
4176: static int
4177: #ifdef CK_ANSIC
4178: sndbrk(int msec) { /* Argument is milliseconds */
4179: #else
4180: sndbrk(msec) int msec; {
4181: #endif /* CK_ANSIC */
4182: #ifndef POSIX
4183: int x, n;
4184: #endif /* POSIX */
4185:
4186: #ifdef ANYBSD
4187: #define BSDBREAK
4188: #endif /* ANYBSD */
4189:
4190: #ifdef COHERENT
4191: #define BSDBREAK
4192: #endif /* COHERENT */
4193:
4194: #ifdef PROVX1
4195: char spd;
4196: #endif /* PROVX1 */
4197:
4198: debug(F101,"ttsndb ttyfd","",ttyfd);
4199: if (ttyfd < 0) return(-1); /* Not open. */
4200:
4201: #ifdef NETCONN
4202: if (netconn) /* Send network BREAK */
4203: return(netbreak());
4204: #endif /* NETCONN */
4205:
4206: if (msec < 1 || msec > 5000) return(-1); /* Bad argument */
4207:
4208: #ifdef POSIX /* Easy in POSIX */
4209: return(tcsendbreak(ttyfd,msec / 375));
4210: #else
4211: #ifdef PROVX1
4212: gtty(ttyfd,&ttbuf); /* Get current tty flags */
4213: spd = ttbuf.sg_ospeed; /* Save speed */
4214: ttbuf.sg_ospeed = B50; /* Change to 50 baud */
4215: stty(ttyfd,&ttbuf); /* ... */
4216: n = (int)strlen(brnuls); /* Send the right number of nulls */
4217: x = msec / 91;
4218: if (x > n) x = n;
4219: write(ttyfd,brnuls,n);
4220: ttbuf.sg_ospeed = spd; /* Restore speed */
4221: stty(ttyfd,&ttbuf); /* ... */
4222: return(0);
4223: #else
4224: #ifdef aegis
4225: sio_$control((short)ttyfd, sio_$send_break, msec, st);
4226: return(0);
4227: #else
4228: #ifdef ATTSV
4229: /*
4230: No way to send a long BREAK in Sys V, so send a bunch of regular ones.
4231: (Actually, Sys V R4 is *supposed* to have the POSIX tcsendbreak() function,
4232: but there's no way for this code to know for sure.)
4233: */
4234: x = msec / 275;
4235: for (n = 0; n < x; n++) {
4236: if (ioctl(ttyfd,TCSBRK,(char *)0) < 0) {
4237: perror("Can't send BREAK");
4238: return(-1);
4239: }
4240: }
4241: return(0);
4242: #else
4243: #ifdef BSDBREAK
4244: n = FWRITE; /* Flush output queue. */
4245: /* Watch out for int vs long problems in &n arg! */
4246: ioctl(ttyfd,TIOCFLUSH,&n); /* Ignore any errors.. */
4247: if (ioctl(ttyfd,TIOCSBRK,(char *)0) < 0) { /* Turn on BREAK */
4248: perror("Can't send BREAK");
4249: return(-1);
4250: }
4251: x = msleep(msec); /* Sleep for so many milliseconds */
4252: if (ioctl(ttyfd,TIOCCBRK,(char *)0) < 0) { /* Turn off BREAK */
4253: perror("BREAK stuck!!!");
4254: doexit(BAD_EXIT,-1); /* Get out, closing the line. */
4255: /* with bad exit status */
4256: }
4257: return(x);
4258: #else
4259: #ifdef V7
4260: return(genbrk(ttyfd,250)); /* Simulate a BREAK */
4261: #endif /* V7 */
4262: #endif /* BSDBREAK */
4263: #endif /* ATTSV */
4264: #endif /* aegis */
4265: #endif /* PROVX1 */
4266: #endif /* POSIX */
4267: }
4268:
4269: /* T T S N D B -- Send a BREAK signal */
4270:
4271: int
4272: ttsndb() {
4273: return(sndbrk(275));
4274: }
4275:
4276: /* T T S N D L B -- Send a Long BREAK signal */
4277:
4278: int
4279: ttsndlb() {
4280: return(sndbrk(1500));
4281: }
4282:
4283: /* M S L E E P -- Millisecond version of sleep(). */
4284:
4285: /*
4286: Call with number of milliseconds (thousandths of seconds) to sleep.
4287: Intended only for small intervals. For big ones, just use sleep().
4288: Highly system-dependent.
4289: Returns 0 always, even if it didn't work.
4290: */
4291:
4292: /* Define MSLFTIME for systems that must use an ftime() loop. */
4293: #ifdef ANYBSD /* For pre-4.2 BSD versions */
4294: #ifndef BSD42
4295: #define MSLFTIME
4296: #endif /* BSD42 */
4297: #endif /* ANYBSD */
4298: #ifdef TOWER1 /* NCR Tower OS 1.0 */
4299: #define MSLFTIME
4300: #endif /* TOWER1 */
4301: #ifdef COHERENT /* Coherent */
4302: #ifndef _I386 /* not used in the 386 version (4.0) */
4303: #define MSLFTIME
4304: #endif /* _I386 */
4305: #endif /* COHERENT */
4306:
4307: int
4308: msleep(m) int m; {
4309:
4310: #ifndef USLEEP
4311: #ifdef SUNOS4 /* Systems that have usleep() */
4312: #define USLEEP
4313: #endif /* SUNOS4 */
4314: #ifdef SUN4S5
4315: #define USLEEP
4316: #endif /* SUN4S5 */
4317: #ifdef NEXT
4318: #define USLEEP
4319: #endif /* NEXT*/
4320: #endif /* USLEEP */
4321:
4322: #ifdef AIXRS
4323: /* RS/6000 can do select() */
4324: #define BSD4
4325: #endif /* AIXRS */
4326:
4327: #ifdef USLEEP
4328: /*
4329: "This routine is implemented using setitimer(2); it requires eight
4330: system calls...". In other words, it might take 5 minutes to sleep
4331: for 100 milliseconds...
4332: */
4333: if (m >= 1000) { /* Catch big arguments. */
4334: sleep(m/1000);
4335: m = m % 1000;
4336: if (m < 10) return(0);
4337: }
4338: usleep((unsigned int)(m * 1000));
4339: return(0);
4340: #else
4341: #ifdef aegis
4342: time_$clock_t dur;
4343:
4344: dur.c2.high16 = 0;
4345: dur.c2.low32 = 250 * m; /* one millisecond = 250 four microsecond ticks */
4346: time_$wait(time_$relative, dur, st);
4347: return(0);
4348: #else
4349: #ifdef PROVX1
4350: if (m <= 0) return(0);
4351: sleep(-((m * 60 + 500) / 1000));
4352: return(0);
4353: #else
4354: #ifdef NAP
4355: nap((long)m);
4356: return(0);
4357: #else
4358: #ifdef BSD42
4359: /* BSD 4.2 & above can do it with select()... */
4360: int t1;
4361: if (m <= 0) return(0);
4362: if (m >= 1000) { /* Catch big arguments. */
4363: sleep(m/1000);
4364: m = m % 1000;
4365: if (m < 10) return(0);
4366: }
4367: if (gettimeofday(&tv, &tz) < 0) return(-1); /* Get current time. */
4368: t1 = tv.tv_sec; /* Seconds */
4369: tv.tv_sec = 0; /* Use select() */
4370: tv.tv_usec = m * 1000L;
4371: select( 0, (int *)0, (int *)0, (int *)0, &tv );
4372: return(0);
4373: #ifdef AIXRS
4374: /* Don't pretend we're BSD any more! */
4375: #undef BSD4
4376: #endif /* AIXRS */
4377:
4378: #else
4379: #ifdef ATTSV
4380: extern long times(); /* Or #include <times.h> ? */
4381: long t1, t2, tarray[4];
4382: int t3;
4383:
4384: #ifdef COMMENT
4385: /* This better be picked up in ckcdeb.h... */
4386: char *getenv();
4387: #endif /* COMMENT */
4388: char *cp = getenv("HZ");
4389: int CLOCK_TICK;
4390: int hertz;
4391:
4392: if (cp && (hertz = atoi(cp))) {
4393: CLOCK_TICK = 1000 / hertz;
4394: } else { /* probably single user mode */
4395: #ifdef HZ
4396: CLOCK_TICK = 1000 / HZ;
4397: #else
4398: static warned = 0;
4399: /* HZ always exists in, for instance, SCO Xenix, so you don't have to
4400: * make special #ifdefs for XENIX here, like in ver 4F. Also, if you
4401: * have Xenix, you have should have nap(), so the best is to use -DNAP
4402: * in the makefile. Most systems have HZ.
4403: */
4404: CLOCK_TICK = 17; /* 1/60 sec */
4405: if (!warned) {
4406: printf("warning: environment variable HZ bad... using HZ=%d\r\n",
4407: 1000 / CLOCK_TICK);
4408: warned = 1;
4409: }
4410: #endif /* !HZ */
4411: }
4412:
4413: if (m <= 0) return(0);
4414: if (m >= 1000) { /* Catch big arguments. */
4415: sleep(m/1000);
4416: m = m % 1000;
4417: if (m < 10) return(0);
4418: }
4419: if ((t1 = times(tarray)) < 0) return(-1);
4420: while (1) {
4421: if ((t2 = times(tarray)) < 0) return(-1);
4422: t3 = ((int)(t2 - t1)) * CLOCK_TICK;
4423: if (t3 > m) return(t3);
4424: }
4425: #else /* Not ATTSV */
4426: #ifdef MSLFTIME /* Use ftime() loop... */
4427: int t1, t3 = 0;
4428: if (m <= 0) return(0);
4429: if (m >= 1000) { /* Catch big arguments. */
4430: sleep(m/1000);
4431: m = m % 1000;
4432: if (m < 10) return(0);
4433: }
4434: if (ftime(&ftp) < 0) return(-1); /* Get base time. */
4435: t1 = ((ftp.time & 0xff) * 1000) + ftp.millitm;
4436: while (1) {
4437: ftime(&ftp); /* Get current time and compare. */
4438: t3 = (((ftp.time & 0xff) * 1000) + ftp.millitm) - t1;
4439: if (t3 > m) return(0);
4440: }
4441: #else
4442: /* This includes true POSIX, which has no way to do this. */
4443: if (m >= 1000) { /* Catch big arguments. */
4444: sleep(m/1000);
4445: m = m % 1000;
4446: if (m < 10) return(0);
4447: }
4448: if (m > 0) while (m > 0) m--; /* Just a dumb busy loop */
4449: return(0);
4450: #endif /* MLSFTIME */
4451: #endif /* ATTSV */
4452: #endif /* BSD42 */
4453: #endif /* NAP */
4454: #endif /* PROVX1 */
4455: #endif /* aegis */
4456: #endif /* USLEEP */
4457: }
4458:
4459: /* R T I M E R -- Reset elapsed time counter */
4460:
4461: VOID
4462: rtimer() {
4463: tcount = time( (time_t *) 0 );
4464: }
4465:
4466:
4467: /* G T I M E R -- Get current value of elapsed time counter in seconds */
4468:
4469: int
4470: gtimer() {
4471: int x;
4472: x = (int) (time( (time_t *) 0 ) - tcount);
4473: debug(F101,"gtimer","",x);
4474: return( (x < 0) ? 0 : x );
4475: }
4476:
4477:
4478: /* Z T I M E -- Return date/time string */
4479:
4480: VOID
4481: ztime(s) char **s; {
4482:
4483: #undef ZTIMEV7 /* Which systems need to use */
4484: #ifdef COHERENT /* old UNIX Version 7 way... */
4485: #define ZTIMEV7
4486: #endif /* COHERENT */
4487: #ifdef TOWER1
4488: #define ZTIMEV7
4489: #endif /* TOWER1 */
4490: #ifdef ANYBSD
4491: #ifndef BSD42
4492: #define ZTIMEV7
4493: #endif /* BSD42 */
4494: #endif /* ANYBSD */
4495: #ifdef V7
4496: #ifndef MINIX
4497: #define ZTIMEV7
4498: #endif /* MINIX */
4499: #endif /* V7 */
4500: #ifdef POSIX
4501: #define ZTIMEV7
4502: #endif /* POSIX */
4503:
4504: #ifdef ATTSV /* AT&T way */
4505: /* extern long time(); */ /* Theoretically these should */
4506: char *ctime(); /* already been dcl'd in <time.h> */
4507: long clock_storage;
4508: clock_storage = time( (long *) 0 );
4509: *s = ctime( &clock_storage );
4510: #else
4511: #ifdef PROVX1 /* Venix 1.0 way */
4512: int utime[2];
4513: time(utime);
4514: *s = ctime(utime);
4515: #else
4516: #ifdef BSD42 /* 4.2BSD way */
4517: char *asctime();
4518: struct tm *localtime();
4519: struct tm *tp;
4520: gettimeofday(&tv, &tz);
4521: time(&tv.tv_sec);
4522: tp = localtime(&tv.tv_sec);
4523: *s = asctime(tp);
4524: #else
4525: #ifdef MINIX /* MINIX way */
4526: #ifdef COMMENT
4527: extern long time(); /* Already got these from <time.h> */
4528: extern char *ctime();
4529: #endif /* COMMENT */
4530: time_t utime[2];
4531: time(utime);
4532: *s = ctime(utime);
4533: #else
4534: #ifdef ZTIMEV7 /* The regular way */
4535: char *asctime();
4536: struct tm *localtime();
4537: struct tm *tp;
4538: long xclock;
4539: time(&xclock);
4540: tp = localtime(&xclock);
4541: *s = asctime(tp);
4542: #else /* Catch-all for others... */
4543: *s = "Ddd Mmm 00 00:00:00 0000\n" /* Return dummy in asctime() format */
4544: #endif /* ZTIMEV7 */
4545: #endif /* MINIX */
4546: #endif /* BSD42 */
4547: #endif /* PROVX1 */
4548: #endif /* SVORPOSIX */
4549: }
4550:
4551: /* C O N G M -- Get console terminal modes. */
4552:
4553: /*
4554: Saves initial console mode, and establishes variables for switching
4555: between current (presumably normal) mode and other modes.
4556: Should be called when program starts, but only after establishing
4557: whether program is in the foreground or background.
4558: Returns 1 if it got the modes OK, 0 if it did nothing, -1 on error.
4559: */
4560: int
4561: congm() {
4562: int fd;
4563: if (backgrd || !isatty(0)) { /* If in background. */
4564: cgmf = -1; /* Don't bother, modes are garbage. */
4565: return(-1);
4566: }
4567: if (cgmf > 0) return(0); /* Already did this. */
4568: debug(F100,"congm getting modes","",0); /* Need to do it. */
4569: #ifdef aegis
4570: ios_$inq_type_uid(ios_$stdin, conuid, st);
4571: if (st.all != status_$ok) {
4572: fprintf(stderr, "problem getting stdin objtype: ");
4573: error_$print(st);
4574: }
4575: concrp = (conuid == mbx_$uid);
4576: conbufn = 0;
4577: #endif /* aegis */
4578:
4579: if ((fd = open(CTTNAM,2)) < 0) { /* Open controlling terminal */
4580: fprintf(stderr,"Error opening %s\n", CTTNAM);
4581: perror("congm");
4582: return(-1);
4583: }
4584: #ifdef ATTSV
4585: if (ioctl(fd,TCGETA,&ccold) < 0) return(-1);
4586: if (ioctl(fd,TCGETA,&cccbrk) < 0) return(-1);
4587: if (ioctl(fd,TCGETA,&ccraw) < 0) return(-1);
4588: #ifdef VXVE
4589: cccbrk.c_line = 0; /* STTY line 0 for CDC VX/VE */
4590: if (ioctl(fd,TCSETA,&cccbrk) < 0) return(-1);
4591: ccraw.c_line = 0; /* STTY line 0 for CDC VX/VE */
4592: if (ioctl(fd,TCSETA,&ccraw) < 0) return(-1);
4593: #endif /* VXVE */
4594: #else
4595: #ifdef POSIX
4596: if (tcgetattr(fd,&ccold) < 0) return(-1);
4597: if (tcgetattr(fd,&cccbrk) < 0) return(-1);
4598: if (tcgetattr(fd,&ccraw) < 0) return(-1);
4599: #else
4600: if (gtty(fd,&ccold) < 0) return(-1);
4601: if (gtty(fd,&cccbrk) < 0) return(-1);
4602: if (gtty(fd,&ccraw) < 0) return(-1);
4603: #endif /* POSIX */
4604: #endif /* ATTSV */
4605: #ifdef sony_news /* Sony NEWS */
4606: if (ioctl(fd,TIOCKGET,&km_con) < 0) { /* Get console Kanji mode */
4607: perror("congm error getting Kanji mode");
4608: debug(F101,"congm error getting Kanji mode","",0);
4609: km_con = -1; /* Make sure this stays undefined. */
4610: return(-1);
4611: }
4612: #endif /* sony_news */
4613: close(fd);
4614: cgmf = 1; /* Flag that we got them. */
4615: return(1);
4616: }
4617:
4618:
4619: /* C O N C B -- Put console in cbreak mode. */
4620:
4621: /* Returns 0 if ok, -1 if not */
4622:
4623: int
4624: #ifdef CK_ANSIC
4625: concb(char esc)
4626: #else
4627: concb(esc) char esc;
4628: #endif /* CK_ANSIC */
4629: /* concb */ {
4630: int x;
4631: debug(F101,"concb backgrd","",backgrd);
4632: if (!isatty(0)) return(0); /* Only for real ttys */
4633: debug(F100,"concb isatty","",0);
4634: if (backgrd) return(0); /* Do nothing if in background. */
4635: escchr = esc; /* Make this available to other fns */
4636: ckxech = 1; /* Program can echo characters */
4637: #ifdef aegis
4638: conbufn = 0;
4639: if (concrp) return(write(1, "\035\002", 2));
4640: if (conuid == input_pad_$uid) {pad_$raw(ios_$stdin, st); return(0);}
4641: #endif
4642: #ifndef SVORPOSIX /* BSD, V7, etc */
4643: cccbrk.sg_flags |= CBREAK; /* Set to character wakeup, */
4644: cccbrk.sg_flags &= ~ECHO; /* no echo. */
4645: x = stty(0,&cccbrk);
4646: #else /* Sys V and POSIX */
4647: cccbrk.c_lflag &= ~(ICANON|ECHO);
4648: cccbrk.c_cc[0] = 003; /* interrupt char is control-c */
4649: cccbrk.c_cc[1] = escchr; /* escape during packet modes */
4650: cccbrk.c_cc[4] = 1;
4651: #ifdef ZILOG
4652: cccbrk.c_cc[5] = 0;
4653: #else
4654: cccbrk.c_cc[5] = 1;
4655: #endif /* ZILOG */
4656: #ifdef ATTSV /* Set new modes */
4657: x = ioctl(0,TCSETAW,&cccbrk); /* the Sys V way */
4658: #else /* POSIX */ /* or the POSIX way */
4659: x = tcsetattr(0,TCSADRAIN,&cccbrk);
4660: #endif /* ATTSV */
4661: #endif /* SVORPOSIX */
4662:
4663: #ifndef aegis
4664: #ifndef NOSETBUF
4665: if (x > -1) setbuf(stdout,NULL); /* Make console unbuffered. */
4666: #endif /* NOSETBUF */
4667: #endif /* aegis */
4668:
4669: #ifdef V7
4670: #ifndef MINIX
4671: if (kmem[CON] < 0) {
4672: qaddr[CON] = initrawq(0);
4673: if((kmem[CON] = open("/dev/kmem", 0)) < 0) {
4674: fprintf(stderr, "Can't read /dev/kmem in concb.\n");
4675: perror("/dev/kmem");
4676: exit(1);
4677: }
4678: }
4679: #endif /* MINIX */
4680: #endif /* V7 */
4681: debug(F101,"concb returns","",x);
4682: return(x);
4683: }
4684:
4685: /* C O N B I N -- Put console in binary mode */
4686:
4687: /* Returns 0 if ok, -1 if not */
4688:
4689: int
4690: #ifdef CK_ANSIC
4691: conbin(char esc)
4692: #else
4693: conbin(esc) char esc;
4694: #endif /* CK_ANSIC */
4695: /* conbin */ {
4696: if (!isatty(0)) return(0); /* only for real ttys */
4697: congm(); /* Get modes if necessary. */
4698: debug(F100,"conbin","",0);
4699: escchr = esc; /* Make this available to other fns */
4700: ckxech = 1; /* Program can echo characters */
4701: #ifdef aegis
4702: conbufn = 0;
4703: if (concrp) return(write(1, "\035\002", 2));
4704: if (conuid == input_pad_$uid)
4705: pad_$raw(ios_$stdin, st);
4706: return(0)
4707: #endif /* aegis */
4708:
4709: #ifdef SVORPOSIX
4710: ccraw.c_lflag &= ~(ISIG|ICANON|ECHO);
4711: ccraw.c_iflag |= (BRKINT|IGNPAR);
4712: #ifdef ATTSV
4713: ccraw.c_iflag &= ~(IGNBRK|INLCR|IGNCR|ICRNL|IUCLC|IXON|IXANY|IXOFF
4714: |INPCK|ISTRIP);
4715: #else /* POSIX */
4716: ccraw.c_iflag &= ~(IGNBRK|INLCR|IGNCR|ICRNL|IXON|IXOFF|INPCK|ISTRIP);
4717: #endif /* ATTSV */
4718: ccraw.c_oflag &= ~OPOST;
4719: #ifdef ATT7300
4720: ccraw.c_cflag = CLOCAL | B9600 | CS8 | CREAD | HUPCL;
4721: #endif /* ATT7300 */
4722: /*** Kermit used to put the console in 8-bit raw mode, but some users have
4723: *** pointed out that this should not be done, since some sites actually
4724: *** use terminals with parity settings on their Unix systems, and if we
4725: *** override the current settings and stop doing parity, then their terminals
4726: *** will display blotches for characters whose parity is wrong. Therefore,
4727: *** the following two lines are commented out (Larry Afrin, Clemson U):
4728: ***
4729: *** ccraw.c_cflag &= ~(PARENB|CSIZE);
4730: *** ccraw.c_cflag |= (CS8|CREAD);
4731: ***
4732: *** Sys III/V sites that have trouble with this can restore these lines.
4733: ***/
4734: ccraw.c_cc[0] = 003; /* Interrupt char is Ctrl-C */
4735: ccraw.c_cc[1] = escchr; /* Escape during packet mode */
4736: ccraw.c_cc[4] = 1;
4737:
4738: #ifdef ZILOG
4739: ccraw.c_cc[5] = 0;
4740: #else
4741: ccraw.c_cc[5] = 1;
4742: #endif /* ZILOG */
4743:
4744: #ifdef ATTSV
4745: return(ioctl(0,TCSETAW,&ccraw)); /* Set new modes. */
4746: #else
4747: return(tcsetattr(0,TCSADRAIN,&ccraw));
4748: #endif /* ATTSV */
4749:
4750: #else /* Berkeley, etc. */
4751: ccraw.sg_flags |= (RAW|TANDEM); /* Set rawmode, XON/XOFF (ha) */
4752: ccraw.sg_flags &= ~(ECHO|CRMOD); /* Set char wakeup, no echo */
4753: return(stty(0,&ccraw));
4754: #endif /* SVORPOSIX */
4755: }
4756:
4757:
4758: /* C O N R E S -- Restore the console terminal */
4759:
4760: int
4761: conres() {
4762: debug(F101,"conres cgmf","",cgmf);
4763: if (cgmf < 1) return(0); /* Do nothing if modes unchanged */
4764: if (!isatty(0)) return(0); /* only for real ttys */
4765: debug(F100,"conres isatty ok","",0);
4766: ckxech = 0; /* System should echo chars */
4767:
4768: #ifdef aegis
4769: conbufn = 0;
4770: if (concrp) return(write(1, "\035\001", 2));
4771: if (conuid == input_pad_$uid)
4772: pad_$cooked(ios_$stdin, st);
4773: return(0);
4774: #endif /* aegis */
4775:
4776: #ifdef ATTSV
4777: debug(F100,"conres restoring ioctl","",0);
4778: return(ioctl(0,TCSETAW,&ccold));
4779: #else
4780: #ifdef POSIX
4781: debug(F100,"conres restoring tcsetattr","",0);
4782: return(tcsetattr(0,TCSADRAIN,&ccold));
4783: #else /* BSD, V7, and friends */
4784: msleep(300);
4785: debug(F100,"conres restoring stty","",0);
4786: return(stty(0,&ccold));
4787: #endif /* POSIX */
4788: #endif /* ATTSV */
4789: #ifdef sony_news /* Sony NEWS */
4790: return(ioctl(0,TIOCKSET,&km_con)); /* Restore console Kanji mode */
4791: #endif /* sony_news */
4792: }
4793:
4794: /* C O N O C -- Output a character to the console terminal */
4795:
4796: int
4797: #ifdef CK_ANSIC
4798: conoc(char c)
4799: #else
4800: conoc(c) char c;
4801: #endif /* CK_ANSIC */
4802: /* conoc */ {
4803: return(write(1,&c,1));
4804: }
4805:
4806: /* C O N X O -- Write x characters to the console terminal */
4807:
4808: int
4809: conxo(x,s) int x; char *s; {
4810: return(write(1,s,x));
4811: }
4812:
4813: /* C O N O L -- Write a line to the console terminal */
4814:
4815: int
4816: conol(s) char *s; {
4817: int len;
4818: len = (int)strlen(s);
4819: return(write(1,s,len));
4820: }
4821:
4822: /* C O N O L A -- Write an array of lines to the console terminal */
4823:
4824: int
4825: conola(s) char *s[]; {
4826: int i;
4827: for (i=0 ; *s[i] ; i++) if (conol(s[i]) < 0) return(-1);;
4828: return(0);
4829: }
4830:
4831: /* C O N O L L -- Output a string followed by CRLF */
4832:
4833: int
4834: conoll(s) char *s; {
4835: conol(s);
4836: return(write(1,"\r\n",2));
4837: }
4838:
4839: /* C O N C H K -- Return how many characters available at console */
4840:
4841: int
4842: conchk() {
4843: int x; PEEKTYPE n;
4844:
4845: if (!isatty(0)) return(0);
4846: #ifdef PROVX1
4847: x = ioctl(0, TIOCQCNT, &ttbuf);
4848: n = ttbuf.sg_ispeed & 0377;
4849: return((x < 0) ? 0 : n);
4850: #else
4851: #ifdef aegis
4852: if (conbufn > 0) return(conbufn); /* use old count if nonzero */
4853:
4854: /* read in more characters */
4855: conbufn = ios_$get(ios_$stdin,
4856: ios_$cond_opt, conbuf, (long)sizeof(conbuf), st);
4857: if (st.all != status_$ok) conbufn = 0;
4858: conbufp = conbuf;
4859: return(conbufn);
4860: #else
4861: #ifdef V7
4862: #ifdef MINIX
4863: return(0);
4864: #else
4865: lseek(kmem[CON], (long) qaddr[CON], 0);
4866: x = read(kmem[CON], &n, sizeof(int));
4867: return((x == sizeof(int))? n: 0);
4868: #endif /* MINIX */
4869: #else
4870: #ifdef SVORPOSIX
4871: if (conesc) { /* Escape typed */
4872: conesc = 0;
4873: signal(SIGQUIT,esctrp); /* Restore escape */
4874: return(1);
4875: }
4876: return(0);
4877: #else
4878: #ifdef C70
4879: if (conesc) { /* Escape typed */
4880: conesc = 0;
4881: signal(SIGQUIT,esctrp); /* Restore escape */
4882: return(1);
4883: }
4884: return(0);
4885: #else
4886: #ifdef FIONREAD
4887: x = ioctl(0, FIONREAD, &n); /* BSD and maybe some others */
4888: debug(F101,"conchk","",n);
4889: return((x < 0) ? 0 : n);
4890: #else
4891: return(0); /* Others can't do. */
4892: #endif
4893: #endif
4894: #endif
4895: #endif
4896: #endif
4897: #endif
4898: }
4899:
4900: /* C O N I N C -- Get a character from the console */
4901:
4902: int
4903: coninc(timo) int timo; {
4904: int n = 0; CHAR ch;
4905: #ifdef aegis
4906: fflush(stdout);
4907: if (conchk() > 0) {
4908: --conbufn;
4909: return(*conbufp++ & 0377);
4910: }
4911: #endif /* aegis */
4912:
4913: if (timo <= 0 ) { /* Untimed. */
4914: n = read(0, &ch, 1); /* Read a character. */
4915: ch &= 0377;
4916: if (n > 0) /* Return the character if read ok */
4917: return(ch);
4918: else /* otherwise... */
4919: #ifdef SVORPOSIX
4920: #ifndef CIE /* CIE Regulus has no such symbol */
4921: if (n < 0 && errno == EINTR) /* If read was interrupted by QUIT, */
4922: return(escchr); /* user entered escape character. */
4923: else /* Can't be ^c, sigint never returns */
4924: #endif /* CIE */
4925: #endif /* SVORPOSIX */
4926: {
4927: debug(F101, "coninc(0) errno","",errno);
4928: return(-1); /* Return -1 as error indication */
4929: }
4930: }
4931: saval = signal(SIGALRM,timerh); /* Timed read, so set up timer */
4932: alarm(timo);
4933: if (setjmp(sjbuf)) n = -2;
4934: else {
4935: n = read(0, &ch, 1);
4936: ch &= 0377;
4937: }
4938: ttimoff(); /* Turn off timer */
4939: if (n > 0) return(ch);
4940: else
4941: #ifdef SVORPOSIX
4942: #ifndef CIE /* CIE Regulus has no such symbol */
4943: if (n == -1 && errno == EINTR) /* If read interrupted by QUIT, */
4944: return(escchr); /* user entered escape character, */
4945: else /* can't be ^c, sigint never returns */
4946: #endif /* CIE */
4947: #endif /* SVORPOSIX */
4948: return(-1);
4949: }
4950:
4951: /* C O N G K S -- Console Get Keyboard Scancode */
4952:
4953: #ifndef congks
4954: /*
4955: This function needs to be filled in with the various system-dependent
4956: system calls used by SUNOS, NeXT OS, Xenix, Aviion, etc, to read a full
4957: keyboard scan code. For now, it's a dummy.
4958: */
4959: int
4960: congks(timo) int timo; {
4961: return(coninc(timo));
4962: }
4963: #endif /* congks */
4964:
4965: #ifdef ATT7300
4966:
4967: /* A T T D I A L -- Dial up the remote system using internal modem
4968: * Purpose: to open and dial a number on the internal modem available on the
4969: * ATT7300 UNIX PC. Written by Joe Doupnik. Superceeds version written by
4970: * Richard E. Hill, Dickinson, TX. which employed dial(3c).
4971: * Uses information in <sys/phone.h> and our status int attmodem.
4972: */
4973: attdial(ttname,speed,telnbr) char *ttname,*telnbr; long speed; {
4974: char *telnum;
4975: int ttclos();
4976:
4977: attmodem &= ~ISMODEM; /* modem not in use yet */
4978: /* Ensure O_NDELAY is set, else i/o traffic hangs */
4979: /* We turn this flag off once the dial is complete */
4980: fcntl(ttyfd, F_SETFL, fcntl(ttyfd, F_GETFL, 0) | O_NDELAY);
4981:
4982: /* Condition line, check availability & DATA mode, turn on speaker */
4983: if (ioctl(ttyfd,PIOCOFFHOOK, &dialer) == -1) {
4984: printf("cannot access phone\n");
4985: ttclos(0);
4986: return (-2);
4987: }
4988: ioctl(ttyfd,PIOCGETP,&dialer); /* get phone dialer parameters */
4989:
4990: if (dialer.c_lineparam & VOICE) { /* phone must be in DATA mode */
4991: printf(" Should not dial with modem in VOICE mode.\n");
4992: printf(" Exit Kermit, switch to DATA and retry call.\n");
4993: ttclos(0);
4994: return (-2);
4995: }
4996: #ifdef ATTTONED /* Old way, tone dialing only. */
4997: dialer.c_lineparam = DATA | DTMF; /* Dial with tones, */
4998: dialer.c_lineparam &= ~PULSE; /* not with pulses. */
4999: #else
5000: /* Leave current pulse/tone state alone. */
5001: /* But what about DATA? Add it back if you have trouble. */
5002: /* sys/phone says you get DATA automatically by opening device RDWR */
5003: #endif
5004: dialer.c_waitdialtone = 5; /* wait 5 sec for dialtone */
5005: #ifdef COMMENT
5006: dialer.c_feedback = SPEAKERON|NORMSPK|RINGON; /* control speaker */
5007: #else
5008: /* sys/phone says RINGON used only for incoming voice calls */
5009: dialer.c_feedback &= ~(SOFTSPK|LOUDSPK);
5010: dialer.c_feedback |= SPEAKERON|NORMSPK;
5011: #endif
5012: dialer.c_waitflash = 500; /* 0.5 sec flash hook */
5013: if(ioctl(ttyfd,PIOCSETP,&dialer) == -1) { /* set phone parameters */
5014: printf("Cannot set modem characteristics\n");
5015: ttclos(0);
5016: return (-2);
5017: }
5018: ioctl(ttyfd,PIOCRECONN,0); /* Turns on speaker for pulse */
5019:
5020: #ifdef COMMENT
5021: fprintf(stderr,"Phone line status. line_par:%o dialtone_wait:%o \
5022: line_status:%o feedback:%o\n",
5023: dialer.c_lineparam, dialer.c_waitdialtone,
5024: dialer.c_linestatus, dialer.c_feedback);
5025: #endif
5026:
5027: attmodem |= ISMODEM; /* modem is now in-use */
5028: sleep(1);
5029: for (telnum = telnbr; *telnum != '\0'; telnum++) /* dial number */
5030: #ifdef ATTTONED
5031: /* Tone dialing only */
5032: if (ioctl(ttyfd,PIOCDIAL,telnum) != 0) {
5033: perror("Error in dialing");
5034: ttclos(0);
5035: return(-2);
5036: }
5037: #else /* Allow Pulse or Tone dialing */
5038: switch (*telnum) {
5039: case 't': case 'T': case '%': /* Tone dialing requested */
5040: dialer.c_lineparam |= DTMF;
5041: dialer.c_lineparam &= ~PULSE;
5042: if (ioctl(ttyfd,PIOCSETP,&dialer) == -1) {
5043: printf("Cannot set modem to tone dialing\n");
5044: ttclos(0);
5045: return(-2);
5046: }
5047: break;
5048: case 'd': case 'D': case 'p': case 'P': case '^':
5049: dialer.c_lineparam |= PULSE;
5050: dialer.c_lineparam &= ~DTMF;
5051: if (ioctl(ttyfd,PIOCSETP,&dialer) == -1) {
5052: printf("Cannot set modem to pulse dialing\n");
5053: ttclos(0);
5054: return(-2);
5055: }
5056: break;
5057: default:
5058: if (ioctl(ttyfd,PIOCDIAL,telnum) != 0) {
5059: perror("Dialing error");
5060: ttclos(0);
5061: return(-2);
5062: }
5063: break;
5064: }
5065: #endif
5066:
5067: ioctl(ttyfd,PIOCDIAL,"@"); /* terminator for data call */
5068: do { /* wait for modems to Connect */
5069: if (ioctl(ttyfd,PIOCGETP,&dialer) != 0) { /* get params */
5070: perror("Cannot get modems to connect");
5071: ttclos(0);
5072: return(-2);
5073: }
5074: } while ((dialer.c_linestatus & MODEMCONNECTED) == 0);
5075: /* Turn off O_NDELAY flag now. */
5076: fcntl(ttyfd, F_SETFL, fcntl(ttyfd, F_GETFL, 0) & ~O_NDELAY);
5077: signal(SIGHUP, ttclos); /* hangup on loss of carrier */
5078: return(0); /* return success */
5079: }
5080:
5081: /*
5082: Offgetty, ongetty functions. These function get the 'getty(1m)' off
5083: and restore it to the indicated line. Shell's return codes are:
5084: 0: Can't do it. Probably a user logged on.
5085: 1: No need. No getty on that line.
5086: 2: Done, you should restore the getty when you're done.
5087: DOGETY System(3), however, returns them as 0, 256, 512, respectively.
5088: Thanks to Kevin O'Gorman, Anarm Software Systems.
5089:
5090: getoff.sh looks like: geton.sh looks like:
5091: setgetty $1 0 setgetty $1 1
5092: err=$? exit $?
5093: sleep 2
5094: exit $err
5095: */
5096:
5097: /* O F F G E T T Y -- Turn off getty(1m) for the communications tty line
5098: * and get status so it can be restarted after the line is hung up.
5099: */
5100: int
5101: offgetty(ttname) char *ttname; {
5102: char temp[30];
5103: while (*ttname != '\0') ttname++; /* seek terminator of path */
5104: ttname -= 3; /* get last 3 chars of name */
5105: sprintf(temp,"/usr/bin/getoff.sh %s",ttname);
5106: return(zsyscmd(temp));
5107: }
5108:
5109: /* O N G E T T Y -- Turn on getty(1m) for the communications tty line */
5110:
5111: int
5112: ongetty(ttname) char *ttname; {
5113: char temp[30];
5114: while (*ttname != '\0') ttname++; /* comms tty path name */
5115: ttname -= 3;
5116: sprintf(temp,"/usr/bin/geton.sh %s",ttname);
5117: return(zsyscmd(temp));
5118: }
5119: #endif /* ATT7300 */
5120:
5121: /* T T S C A R R -- Set ttcarr variable, controlling carrier handling.
5122: *
5123: * 0 = Off: Always ignore carrier. E.g. you can connect without carrier.
5124: * 1 = On: Heed carrier, except during dialing. Carrier loss gives disconnect.
5125: * 2 = Auto: For "modem direct": The same as "Off".
5126: * For real modem types: Heed carrier during connect, but ignore
5127: * it anytime else. Compatible with pre-5A C-Kermit versions.
5128: *
5129: * As you can see, this setting does not affect dialing, which always ignores
5130: * carrier (unless there is some special exception for some modem type). It
5131: * does affect ttopen() if it is set before ttopen() is used. This setting
5132: * takes effect on the next call to ttopen()/ttpkt()/ttvt(). And they are
5133: * (or should be) always called before any communications is tried, which
5134: * means that, practically speaking, the effect is immediate.
5135: *
5136: * Of course, nothing of this applies to remote mode (xlocal = 0).
5137: *
5138: * Someone has yet to uncover how to manipulate the carrier in the BSD
5139: * environment (or any non-termio using environment). Until that time, this
5140: * will simply be a no-op for BSD.
5141: *
5142: * Note that in previous versions, the carrier was most often left unchanged
5143: * in ttpkt()/ttvt() unless they were called with DIALING or CONNECT. This
5144: * has changed. Now it is controlled by ttcarr in conjunction with these
5145: * modes.
5146: */
5147: int
5148: ttscarr(carrier) int carrier; {
5149: ttcarr = carrier;
5150: debug(F101, "ttscarr","",ttcarr);
5151: return(ttcarr);
5152: }
5153:
5154: /* C A R R C T L -- Set tty modes for carrier treatment.
5155: *
5156: * Sets the appropriate bits in a termio or sgttyb struct for carrier control
5157: * (actually, there are no bits in sgttyb for that), or performs any other
5158: * operations needed to control this on the current system. The function does
5159: * not do the actual TCSETA or stty, since often we want to set other bits too
5160: * first. Don't call this function when xlocal is 0, or the tty is not opened.
5161: *
5162: * We don't know how to do anything like carrier control on non-ATTSV systems,
5163: * except, apparently, ultrix. See above. It is also known that this doesn't
5164: * have much effect on a Xenix system. For Xenix, one should switch back and
5165: * forth between the upper and lower case device files. Maybe later.
5166: * Presently, Xenix will stick to the mode it was opened with.
5167: *
5168: * carrier: 0 = ignore carrier, 1 = require carrier.
5169: * The current state is saved in curcarr, and checked to save labour.
5170: */
5171: #ifdef SVORPOSIX
5172: int
5173: #ifdef ATTSV
5174: carrctl(ttpar, carrier) struct termio *ttpar; int carrier;
5175: #else /* POSIX */
5176: carrctl(ttpar, carrier) struct termios *ttpar; int carrier;
5177: #endif /* ATTSV */
5178: /* carrctl */ {
5179: debug(F101, "carrctl","",carrier);
5180: if (carrier)
5181: ttpar->c_cflag &= ~CLOCAL;
5182: else
5183: ttpar->c_cflag |= CLOCAL;
5184: return(0);
5185: }
5186: #else /* Berkeley, V7, et al... */
5187: int
5188: carrctl(ttpar, carrier) struct sgttyb *ttpar; int carrier; {
5189: #ifdef ultrix
5190: int temp = 0;
5191: #endif /* ultrix */
5192: debug(F101, "carrctl","",carrier);
5193: if (carrier == curcarr)
5194: return(0);
5195: curcarr = carrier;
5196: #ifdef ultrix
5197: if (carrier) {
5198: ioctl(ttyfd, TIOCMODEM, &temp);
5199: ioctl(ttyfd, TIOCHPCL, 0);
5200: } else {
5201: /* (According to the manuals, TIOCNCAR should be preferred */
5202: /* over TIOCNMODEM...) */
5203: ioctl(ttyfd, TIOCNMODEM, &temp);
5204: }
5205: #endif /* ultrix */
5206: return(0);
5207: }
5208: #endif /* SVORPOSIX */
5209:
5210:
5211: /* T T G M D M -- Get modem signals */
5212: /*
5213: Looks for RS-232 modem signals, and returns those that are on in as its
5214: return value, in a bit mask composed of the BM_xxx values defined in ckcdeb.h.
5215: Returns:
5216: -3 Not implemented
5217: -2 if the communication device does not have modem control (e.g. telnet)
5218: -1 on error.
5219: >= 0 on success, with a bit mask containing the modem signals that are on.
5220: */
5221:
5222: /*
5223: Define the symbol K_MDMCTL if we have Sys V R3 / 4.3 BSD style
5224: modem control, namely the TIOCMGET ioctl.
5225: */
5226:
5227: #ifdef BSD43
5228: #define K_MDMCTL
5229: #endif
5230:
5231: #ifdef SUNOS4
5232: #define K_MDMCTL
5233: #endif
5234:
5235: #ifdef TIOCMGET
5236: #define K_MDMCTL
5237: #endif
5238:
5239: int
5240: ttgmdm() {
5241:
5242: #ifdef HPUX /* HPUX has its own way */
5243:
5244: /*
5245: NOTE: I don't have an HPUX man page, and so I'm only guessing at the
5246: right names for these symbols. Somebody with HPUX please let me know
5247: what corrections are needed.
5248: */
5249:
5250: int x, y, z;
5251:
5252: if (netconn) return(-2); /* No modem signals for network */
5253: if (xlocal) /* Get modem signals */
5254: x = ioctl(ttyfd,MCGETA,&y);
5255: else
5256: x = ioctl(0,MCGETA,&y);
5257: if (x < 0) return(-1);
5258: debug(F101,"ttgmdm","",y);
5259:
5260: z = 0; /* Initialize return value */
5261:
5262: /* Now set bits for each modem signal that is reported to be on. */
5263:
5264: #ifdef MCTS
5265: /* Clear To Send */
5266: if (y & MCTS) z |= BM_CTS;
5267: #endif
5268: #ifdef MDSR
5269: /* Data Set Ready */
5270: if (y & MDSR) z |= BM_DSR;
5271: #endif
5272: #ifdef MDCD
5273: /* Carrier */
5274: if (y & MDCD) z |= BM_DCD;
5275: #endif
5276: #ifdef MRNG
5277: /* Ring Indicate */
5278: if (y & MRNG) z |= BM_RNG;
5279: #endif
5280: #ifdef MDTR
5281: /* Data Terminal Ready */
5282: if (y & MDTR) z |= BM_DTR;
5283: #endif
5284: #ifdef MRTS
5285: /* Request To Send */
5286: if (y & MRTS) z |= BM_RTS;
5287: #endif
5288: return(z);
5289:
5290: #else /* ! HPUX */
5291:
5292: #ifdef K_MDMCTL
5293: /*
5294: Note, <sys/ttycom> might have already been included by by <sys/ioctl.h>.
5295: Hence the following ifndef on a symbol which is defined there.
5296: */
5297: #ifndef TIOCMGET
5298: #include <sys/ttycom.h>
5299: #endif /* TIOCMGET */
5300:
5301: int x, y, z;
5302:
5303: if (netconn) return(-2); /* Network, no modem signals. */
5304: if (xlocal)
5305: x = ioctl(ttyfd,TIOCMGET,&y); /* Get modem signals. */
5306: else
5307: x = ioctl(0,TIOCMGET,&y);
5308: if (x < 0) return(-1);
5309: debug(F101,"ttgmdm","",y);
5310:
5311: z = 0; /* Initialize return value. */
5312: #ifdef TIOCM_CTS
5313: /* Clear To Send */
5314: if (y & TIOCM_CTS) z |= BM_CTS;
5315: #endif
5316: #ifdef TIOCM_DSR
5317: /* Data Set Ready */
5318: if (y & TIOCM_DSR) z |= BM_DSR;
5319: #endif
5320: #ifdef TIOCM_CAR
5321: /* Carrier */
5322: if (y & TIOCM_CAR) z |= BM_DCD;
5323: #endif
5324: #ifdef TIOCM_RNG
5325: /* Ring Indicate */
5326: if (y & TIOCM_RNG) z |= BM_RNG;
5327: #endif
5328: #ifdef TIOCM_DTR
5329: /* Data Terminal Ready */
5330: if (y & TIOCM_DTR) z |= BM_DTR;
5331: #endif
5332: #ifdef TIOCM_RTS
5333: /* Request To Send */
5334: if (y & TIOCM_RTS) z |= BM_RTS;
5335: #endif
5336: return(z);
5337: #else
5338: if (netconn) return(-2);
5339: return(-3);
5340:
5341: #endif /* K_MDMCTL */
5342: #endif /* HPUX */
5343: }
5344:
5345: /* P S U S P E N D -- Put this process in the background. */
5346:
5347: /*
5348: Call with flag nonzero if suspending is allowed, zero if not allowed.
5349: Returns 0 on apparent success, -1 on failure (flag was zero, or
5350: kill() returned an error code.
5351: */
5352: int
5353: psuspend(flag) int flag; {
5354:
5355: #ifdef RTU
5356: extern int rtu_bug;
5357: #endif /* RTU */
5358:
5359: if (flag == 0) return(-1);
5360:
5361: #ifdef NOJC
5362: return(-1);
5363: #else
5364: #ifdef SIGTSTP
5365: /*
5366: The big question here is whether job control is *really* supported.
5367: There's no way Kermit can know for sure. The fact that SIGTSTP is
5368: defined does not guarantee the Unix kernel supports it, and the fact
5369: that the Unix kernel supports it doesn't guarantee that the user's
5370: shell (or other process that invoked Kermit) supports it.
5371: */
5372: #ifdef RTU
5373: rtu_bug = 1;
5374: #endif /* RTU */
5375: if (kill(0,SIGSTOP) < 0
5376: #ifdef OXOS
5377: /*
5378: Because "kill(myself,SIGSTOP)" can't be caught, blocked, or ignored..."
5379: */
5380: && kill(getpid(),SIGSTOP) < 0
5381: #else
5382: #ifdef MIPS
5383: /* Let's try this for MIPS too. */
5384: && kill(getpid(),SIGSTOP) < 0
5385: #endif /* MIPS */
5386: #endif /* OXOS */
5387: ) { /* If job control, suspend the job */
5388: perror("suspend");
5389: debug(F101,"psuspend error","",errno);
5390: return(-1);
5391: }
5392: debug(F100,"psuspend ok","",0);
5393: return(0);
5394: #else
5395: return(-1);
5396: #endif /* SIGTSTP */
5397: #endif /* NOJC */
5398: }
5399:
5400: /*
5401: setuid package, by Kristoffer Eriksson, with contributions from Dean
5402: Long and fdc.
5403: */
5404:
5405: #ifndef _POSIX_SOURCE
5406: #ifndef SUNOS4
5407: #ifndef NEXT
5408: #ifndef PS2AIX10
5409: extern UID_T getuid(), geteuid(), getreuid();
5410: extern GID_T getgid(), getegid(), getregid();
5411: #endif /* PS2AIX10 */
5412: #endif /* NEXT */
5413: #endif /* SUNOS4 */
5414: #endif /* _POSIX_SOURCE */
5415:
5416: /*
5417: Subject: Set-user-id
5418: To: [email protected] (Frank da Cruz)
5419: Date: Sat, 21 Apr 90 4:48:25 MES
5420: From: Kristoffer Eriksson <[email protected]>
5421:
5422: This is a set of functions to be used in programs that may be run set-user-id
5423: and/or set-group-id. They handle both the case where the program is not run
5424: with such privileges (nothing special happens then), and the case where one
5425: or both of these set-id modes are used. The program is made to run with the
5426: user's real user and group ids most of the time, except for when more
5427: privileges are needed. Don't set-user-id to "root".
5428:
5429: This works on System V and POSIX. In BSD, it depends on the
5430: "saved-set-user-id" feature.
5431: */
5432:
5433: #define UID_ROOT 0 /* Root user and group ids */
5434: #define GID_ROOT 0
5435:
5436: /*
5437: The following construction automatically defines the symbol SETREUID for
5438: Unix versions based on Berkeley Unix 4.2 or later. If this symbol is
5439: defined, then this program will use getreuid() and getregid() calls in
5440: preference to getuid() and getgid(), which in Berkeley-based Unixes do
5441: not allow arbitrary switching back and forth of real & effective uid.
5442: This construction also allows -DSETREUID to be put on the cc command line
5443: for any system that has and wants to use setre[ug]id(). It also prevents
5444: automatic definition of SETREUID if -DNOSETREU is included on the cc
5445: command line (or otherwise defined).
5446: */
5447: #ifdef FT18 /* None of this for Fortune. */
5448: #define NOSETREU
5449: #endif /* FT18 */
5450:
5451: #ifdef ANYBSD
5452: #ifndef BSD29
5453: #ifndef BSD41
5454: #ifndef SETREUID
5455: #ifndef NOSETREU
5456: #define SETREUID
5457: #endif /* NOSETREU */
5458: #endif /* SETREUID */
5459: #endif /* !BSD41 */
5460: #endif /* !BSD29 */
5461: #endif /* ANYBSD */
5462:
5463: /* Variables for user and group IDs. */
5464:
5465: static UID_T realuid = (UID_T) -1, privuid = (UID_T) -1;
5466: static GID_T realgid = (GID_T) -1, privgid = (GID_T) -1;
5467:
5468:
5469: /* P R I V _ I N I -- Initialize privileges package */
5470:
5471: /* Called as early as possible in a set-uid or set-gid program to store the
5472: * set-to uid and/or gid and step down to the users real uid and gid. The
5473: * stored id's can be temporarily restored (allowed in System V) during
5474: * operations that require the privilege. Most of the time, the program
5475: * should execute in unpriviliged state, to not impose any security threat.
5476: *
5477: * Note: Don't forget that access() always uses the real id:s to determine
5478: * file access, even with privileges restored.
5479: *
5480: * Returns an error mask, with error values or:ed together:
5481: * 1 if setuid() fails,
5482: * 2 if setgid() fails, and
5483: * 4 if the program is set-user-id to "root", which can't be handled.
5484: *
5485: * Only the return value 0 indicates real success. In case of failure,
5486: * those privileges that could be reduced have been, at least, but the
5487: * program should be aborted none-the-less.
5488: *
5489: * Also note that these functions do not expect the uid or gid to change
5490: * without their knowing. It may work if it is only done temporarily, but
5491: * you're on your own.
5492: */
5493: int
5494: priv_ini() {
5495: int err = 0;
5496:
5497: /* Save real ID:s. */
5498: realuid = getuid();
5499: realgid = getgid();
5500:
5501: /* Save current effective ID:s, those set to at program exec. */
5502: privuid = geteuid();
5503: privgid = getegid();
5504:
5505: /* If running set-uid, go down to real uid, otherwise remember that
5506: * no privileged uid is available.
5507: *
5508: * Exceptions:
5509: *
5510: * 1) If the real uid is already "root" and the set-uid uid (the
5511: * initial effective uid) is not "root", then we would have trouble
5512: * if we went "down" to "root" here, and then temporarily back to the
5513: * set-uid uid (not "root") and then again tried to become "root". I
5514: * think the "saved set-uid" is lost when changing uid from effective
5515: * uid "root", which changes all uid, not only the effective uid. But
5516: * in this situation, we can simply go to "root" and stay there all
5517: * the time. That should give sufficient privilege (understatement!),
5518: * and give the right uids for subprocesses.
5519: *
5520: * 2) If the set-uid (the initial effective uid) is "root", and we
5521: * change uid to the real uid, we can't change it back to "root" when
5522: * we need the privilege, for the same reason as in 1). Thus, we can't
5523: * handle programs that are set-user-id to "root" at all. The program
5524: * should be aborted. Use some other uid. "root" is probably to
5525: * privileged for such things, anyway. (The uid is reverted to the
5526: * real uid until abortion.)
5527: *
5528: * These two exceptions have the effect that the "root" uid will never
5529: * be one of the two uids that are being switched between, which also
5530: * means we don't have to check for such cases in the switching
5531: * functions.
5532: *
5533: * Note that exception 1) is handled by these routines (by constantly
5534: * running with uid "root", while exception 2) is a serious error, and
5535: * is not provided for at all in the switching functions.
5536: */
5537: if (realuid == privuid)
5538: privuid = (UID_T) -1; /* Not running set-user-id. */
5539:
5540: /* If running set-gid, go down to real gid, otherwise remember that
5541: * no privileged gid is available.
5542: *
5543: * There are no exception like there is for the user id, since there
5544: * is no group id that is privileged in the manner of uid "root".
5545: * There could be equivalent problems for group changing if the
5546: * program sometimes ran with uid "root" and sometimes not, but
5547: * that is already avoided as explained above.
5548: *
5549: * Thus we can expect always to be able to switch to the "saved set-
5550: * gid" when we want, and back to the real gid again. You may also
5551: * draw the conclusion that set-gid provides for fewer hassles than
5552: * set-uid.
5553: */
5554:
5555: if (realgid == privgid) /* If not running set-user-id, */
5556: privgid = (GID_T) -1; /* remember it this way. */
5557:
5558: err = priv_off(); /* Turn off setuid privilege. */
5559:
5560: if (privuid == UID_ROOT) /* If setuid to root, */
5561: err |= 4; /* return this error. */
5562:
5563: if (realuid == UID_ROOT) /* If real id is root, */
5564: privuid = (UID_T) -1; /* stay root at all times. */
5565:
5566: return(err);
5567: }
5568:
5569:
5570: /* Macros for hiding the differences in UID/GID setting between various Unix
5571: * systems. These macros should always be called with both the privileged ID
5572: * and the non-privileged ID. The one in the second argument, will become the
5573: * effective ID. The one in the first argument will be retained for later
5574: * retrieval.
5575: */
5576: #ifdef SETREUID
5577: #ifdef SAVEDUID
5578: /* On BSD systems with the saved-UID feature, we just juggle the effective
5579: * UID back and forth, and leave the real UID at its true value. The kernel
5580: * allows switching to both the current real UID, the effective UID, and the
5581: * UID which the program is set-UID to. The saved set-UID always holds the
5582: * privileged UID for us, and the real UID will always be the non-privileged,
5583: * and we can freely choose one of them for the effective UID at any time.
5584: */
5585: #define switchuid(hidden,active) setreuid( (UID_T) -1, active)
5586: #define switchgid(hidden,active) setregid( (GID_T) -1, active)
5587:
5588: #else /* SETREUID,!SAVEDUID */
5589:
5590: /* On systems with setreXid() but without the saved-UID feature, notably
5591: * BSD 4.2, we swap the real and effective UIDs each time. It's
5592: * the effective UID that we are interrested in, but we have to retain the
5593: * unused UID somewhere to enable us to restore it later, and that we do this
5594: * in the real UID. The kernel only allows switching to either the current
5595: * real or the effective UID, unless you're "root".
5596: */
5597: #define switchuid(hidden,active) setreuid(hidden,active)
5598: #define switchgid(hidden,active) setregid(hidden,active)
5599: #endif
5600:
5601: #else /* !SETREUID, !SAVEDUID */
5602:
5603: /* On System V and POSIX, the only thing we can change is the effective UID
5604: * (unless the current effective UID is "root", but initsuid() avoids that for
5605: * us). The kernel allows switching to the current real UID or to the saved
5606: * set-UID. These are always set to the non-privileged UID and the privileged
5607: * UID, respectively, and we only change the effective UID. This breaks if
5608: * the current effective UID is "root", though, because for "root" setuid/gid
5609: * becomes more powerful, which is why initsuid() treats "root" specially.
5610: * Note: That special treatment maybe could be ignored for BSD? Note: For
5611: * systems that don't fit any of these three cases, we simply can't support
5612: * set-UID.
5613: */
5614: #define switchuid(hidden,active) setuid(active)
5615: #define switchgid(hidden,active) setgid(active)
5616: #endif /* SETREUID */
5617:
5618:
5619: /* P R I V _ O N -- Turn on the setuid and/or setgid */
5620:
5621: /* Go to the privileged uid (gid) that the program is set-user-id
5622: * (set-group-id) to, unless the program is running unprivileged.
5623: * If setuid() fails, return value will be 1. If getuid() fails it
5624: * will be 2. Return immediately after first failure, and the function
5625: * tries to restore any partial work done. Returns 0 on success.
5626: * Group id is changed first, since it is less serious than user id.
5627: */
5628: int
5629: priv_on() {
5630: if (privgid != (GID_T) -1)
5631: if (switchgid(realgid,privgid))
5632: return(2);
5633:
5634: if (privuid != (UID_T) -1)
5635: if (switchuid(realuid,privuid)) {
5636: if (privgid != (GID_T) -1)
5637: switchgid(privgid,realgid);
5638: return(1);
5639: }
5640: return(0);
5641: }
5642:
5643: /* P R I V _ O F F -- Turn on the real uid and gid */
5644:
5645: /* Return to the unprivileged uid (gid) after an temporary visit to
5646: * privileged status, unless the program is running without set-user-id
5647: * (set-group-id). Returns 1 for failure in setuid() and 2 for failure
5648: * in setgid() or:ed together. The functions tries to return both uid
5649: * and gid to unprivileged state, regardless of errors. Returns 0 on
5650: * success.
5651: */
5652: int
5653: priv_off() {
5654: int err = 0;
5655:
5656: if (privuid != (UID_T) -1)
5657: if (switchuid(privuid,realuid))
5658: err |= 1;
5659:
5660: if (privgid != (GID_T) -1)
5661: if (switchgid(privgid,realgid))
5662: err |= 2;
5663:
5664: return(err);
5665: }
5666:
5667: /* Turn off privilege permanently. No going back. This is necessary before
5668: * a fork() on BSD43 machines that don't save the setUID or setGID, because
5669: * we swap the real and effective ids, and we don't want to let the forked
5670: * process swap them again and get the privilege back. It will work on other
5671: * machines too, such that you can rely on its effect always being the same,
5672: * for instance, even when you're in priv_on() state when this is called.
5673: * (Well, that part about "permanent" is on System V only true if you follow
5674: * this with a call to exec(), but that's what we want it for anyway.)
5675: * Added by Dean Long -- [email protected]
5676: */
5677: int
5678: priv_can() {
5679:
5680: #ifdef SETREUID
5681: int err = 0;
5682: if (privuid != (UID_T) -1)
5683: if (setreuid(realuid,realuid))
5684: err |= 1;
5685:
5686: if (privgid != (GID_T) -1)
5687: if (setregid(realgid,realgid))
5688: err |= 2;
5689:
5690: return(err);
5691:
5692: #else
5693: /* Easy way of using setuid()/setgid() instead of setreuid()/setregid().*/
5694: return(priv_off());
5695:
5696: #endif /* SETREUID */
5697: }
5698:
5699: /* P R I V _ O P N -- For opening protected files or devices. */
5700:
5701: int
5702: priv_opn(name, modes) char *name; int modes; {
5703: int x;
5704: priv_on(); /* Turn privileges on */
5705: x = open(name, modes); /* Try to open the device */
5706: priv_off(); /* Turn privileges off */
5707: return(x); /* Return open's return code */
5708: }
5709:
5710: /* P R I V _ C H K -- Check privileges. */
5711:
5712: /* Try to turn them off. If turning them off did not succeed, cancel them */
5713:
5714: int
5715: priv_chk() {
5716: int x, y = 0;
5717: x = priv_off(); /* Turn off privs. */
5718: if (x != 0 || getuid() == privuid || geteuid() == privuid)
5719: y = priv_can();
5720: if (x != 0 || getgid() == privgid || getegid() == privgid)
5721: y = y | priv_can();
5722: return(y);
5723: }
5724:
5725: UID_T
5726: real_uid() {
5727: return(realuid);
5728: }
5729:
5730: VOID
5731: ttimoff() { /* Turn off any timer interrupts */
5732: alarm(0);
5733: if (saval)
5734: signal(SIGALRM,saval);
5735: else
5736: signal(SIGALRM,SIG_DFL);
5737: saval = NULL;
5738: }
5739:
5740: #ifdef UTEK
5741: /* Turn on or off hardware flow control under UTek */
5742: VOID
5743: hardflow(flow) int flow; {
5744: int x;
5745: x = LDODTR | LDOCTS;
5746: if (flow == FLO_HARD) { /* Use hardware flow control */
5747: if (lmodef) {
5748: x = ioctl(ttyfd,TIOCLBIS,&x);
5749: if (x < 0) {
5750: debug(F100,"hardflow TIOCLBIS error","",0);
5751: } else {
5752: lmodef++;
5753: debug(F100,"hardflow TIOCLBIS ok","",0);
5754: }
5755: }
5756: } else {
5757: if (lmodef) {
5758: x = ioctl(ttyfd,TIOCLBIC,&x);
5759: if (x < 0) {
5760: debug(F100,"hardflow TIOCLBIC error","",0);
5761: } else {
5762: lmodef++;
5763: debug(F100,"hardflow TIOCLBIC ok","",0);
5764: }
5765: }
5766: }
5767: }
5768: #endif /* UTEK */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.