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