1 #define CKUTIO_C
2
3 #ifdef aegis
4 char *ckxv = "Aegis Communications support, 9.0.329, 18 September 2020";
5 #else
6 #ifdef Plan9
7 char *ckxv = "Plan 9 Communications support, 9.0.329, 18 September 2020";
8 #else
9 char *ckxv = "UNIX Communications support, 9.0.329, 18 September 2020";
10 #endif /* Plan9 */
11 #endif /* aegis */
12
13 /* C K U T I O */
14
15 /* C-Kermit interrupt, communications control and I/O functions for UNIX */
16
17 /*
18 Author: Frank da Cruz (fdc@columbia.edu),
19 The Kermit Project, Bronx, NY.
20
21 Copyright (C) 1985, 2020,
22 Trustees of Columbia University in the City of New York.
23 All rights reserved. See the C-Kermit COPYING.TXT file or the
24 copyright text in the ckcmai.c module for disclaimer and permissions.
25 */
26
27 /*
28 NOTE TO CONTRIBUTORS: This file, and all the other C-Kermit files, must be
29 compatible with C preprocessors that support only #ifdef, #else, #endif,
30 #define, and #undef. Please do not use #if, logical operators, or other
31 preprocessor features in any of the portable C-Kermit modules. You can,
32 of course, use these constructions in platform-specific modules when they
33 are supported by all compilers/preprocessors that could be used on that
34 platform.
35 */
36
37 extern int nettype; /* Defined in ckcmai.c */
38 extern int duplex;
39
40 /* Includes */
41
42 #include "ckcsym.h" /* This must go first */
43 #include "ckcdeb.h" /* This must go second */
44
45 #ifdef OSF13
46 #ifdef CK_ANSIC
47 #ifdef _NO_PROTO
48 #undef _NO_PROTO
49 #endif /* _NO_PROTO */
50 #endif /* CK_ANSIC */
51 #endif /* OSF13 */
52
53 #ifndef HPUXPRE65
54 #include <errno.h> /* Error number symbols */
55 #else
56 #ifndef ERRNO_INCLUDED
57 #include <errno.h> /* Error number symbols */
58 #endif /* ERRNO_INCLUDED */
59 #endif /* HPUXPRE65 */
60
61 #ifdef __386BSD__
62 #define ENOTCONN 57
63 #else
64 #ifdef __bsdi__
65 #define ENOTCONN 57
66 #else
67 #ifdef __FreeBSD__
68 #define ENOTCONN 57
69 #endif /* __FreeBSD__ */
70 #endif /* __bsdi__ */
71 #endif /* __386BSD__ */
72
73 #ifdef SCO_OSR504
74 #define NBBY 8
75 #endif /* SCO_OSR504 */
76
77 #ifdef Plan9
78 #define SELECT
79 #include <sys/time.h>
80 #include <select.h>
81 #define FD_SETSIZE (3 * sizeof(long) * 8)
82 static struct timeval tv;
83 #endif /* Plan9 */
84
85 #ifdef CLIX
86 #include <sys/time.h>
87 #endif /* CLIX */
88
89 #include "ckcnet.h" /* Symbols for network types. */
90 #ifdef CK_SSL
91 #include "ck_ssl.h"
92 #endif /* CK_SSL */
93
94 /*
95 The directory-related includes are here because we need to test some
96 file-system-related symbols to find out which system we're being compiled
97 under. For example, MAXNAMLEN is defined in BSD4.2 but not 4.1.
98 */
99 #ifdef SDIRENT /* Directory bits... */
100 #define DIRENT
101 #endif /* SDIRENT */
102
103 #ifdef XNDIR
104 #include <sys/ndir.h>
105 #else /* !XNDIR */
106 #ifdef NDIR
107 #include <ndir.h>
108 #else /* !NDIR, !XNDIR */
109 #ifdef RTU
110 #include "/usr/lib/ndir.h"
111 #else /* !RTU, !NDIR, !XNDIR */
112 #ifdef DIRENT
113 #ifdef SDIRENT
114 #include <sys/dirent.h>
115 #else
116 #include <dirent.h>
117 #endif /* SDIRENT */
118 #else /* !RTU, !NDIR, !XNDIR, !DIRENT, i.e. all others */
119 #include <sys/dir.h>
120 #endif /* DIRENT */
121 #endif /* RTU */
122 #endif /* NDIR */
123 #endif /* XNDIR */
124
125 #ifdef QNX
126 #include <sys/dev.h>
127 #endif /* QNX */
128
129 #ifdef HPUX5
130 #ifndef TCPSOCKET
131 /* I don't know why this is needed here since we never reference bzero(). */
132 /* But without it C-Kermit won't link in an HP-UX 5.xx non-TCP build. */
133 void
bzero(s,n)134 bzero(s,n) char *s; int n; {
135 extern char * memset();
136 memset(s,0,n);
137 }
138 #endif /* TCPSOCKET */
139 #endif /* HPUX5 */
140
141 /* Definition of HZ, used in msleep() */
142
143 #ifdef MIPS
144 #define HZ ( 1000 / CLOCK_TICK )
145 #else /* MIPS */
146 #ifdef ATTSV
147 #ifndef NAP
148 #ifdef TRS16
149 #define HZ ( 1000 / CLOCK_TICK )
150 #endif /* TRS16 */
151 #ifdef NAPHACK
152 #define nap(x) (void)syscall(3112, (x))
153 #define NAP
154 #endif /* NAPHACK */
155 #endif /* NAP */
156 #endif /* ATTSV */
157 #endif /* MIPS */
158
159 #ifdef M_UNIX
160 #undef NGROUPS_MAX /* Prevent multiple definition warnings */
161 #endif /* M_UNIX */
162
163 /*
164 NOTE: HP-UX 8.0 has a <sys/poll.h>, but there is no corresponding
165 library routine, so _poll comes up undefined at link time.
166 */
167 #ifdef CK_POLL
168 #ifndef AIXRS /* IBM AIX needs special handling */
169 #include <poll.h> /* "standard" (SVID) i/o multiplexing, etc */
170 #else /* AIXRS */
171 #ifdef SVR4 /* AIX 3.2 is like SVID... */
172 #include <poll.h>
173 #else /* But AIX 3.1 is not ... */
174 #include <sys/poll.h> /* The include file is in include/sys */
175 #define events reqevents /* And it does not map IBM-specific member */
176 #define revents rtnevents /* names to the System V equivalents */
177 #endif /* SVR4 */
178 #endif /* AIXRS */
179 #endif /* CK_POLL */
180
181 #include <signal.h> /* Signals */
182
183 /* For setjmp and longjmp */
184
185 #ifndef ZILOG
186 #include <setjmp.h>
187 #else
188 #include <setret.h>
189 #endif /* ZILOG */
190
191 /*
192 The following test differentiates between 4.1 BSD and 4.2 & later.
193 If you have a 4.1BSD system with the DIRENT library, this test could
194 mistakenly diagnose 4.2BSD and then later enable the use of system calls
195 that aren't defined. If indeed there are such systems, we can use some
196 other way of testing for 4.1BSD, or add yet another compile-time switch.
197 */
198 #ifdef BSD4
199 #ifdef MAXNAMLEN
200 #ifndef FT21 /* Except for Fortune. */
201 #ifndef FT18
202 #ifndef BELLV10 /* And Bell Labs Research UNIX V10 */
203 #define BSD42
204 #endif /* BELLV10 */
205 #endif /* FT18 */
206 #endif /* FT21 */
207 #endif /* MAXNAMLEN */
208 #endif /* BSD4 */
209
210 #ifdef SUNOS41 /* From Christian Corti */
211 #define BSD44ORPOSIX /* Uni Stuttgart */
212 #define SVORPOSIX /* February 2010 */
213 #include <termios.h>
214 #include <sys/ioctl.h>
215 #include <unistd.h>
216 #include <limits.h>
217 #endif /* SUNOS41 */
218
219 #ifdef SNI542
220 #include <sys/filio.h> /* 299 for FIONREAD */
221 #endif /* SNI542 */
222
223 /*
224 Minix 2.0 support added by Terry McConnell,
225 Syracuse University <tmc@barnyard.syr.edu>
226 No more sgtty interface, posix compliant.
227 */
228 #ifdef MINIX2
229 #define _MINIX /* Needed for some Minix header files */
230 #define BSD44ORPOSIX
231 #define SVORPOSIX
232 #ifndef MINIX3
233 #define DCLTIMEVAL
234 #endif /* MINIX3 */
235 #define NOFILEH
236 #include <sys/types.h>
237 #include <sys/ioctl.h>
238 #include <termios.h>
239 #include <limits.h>
240 #undef TIOCGETC /* defined in sys/ioctl.h, but not really supported */
241 #define TANDEM 0
242 #endif /* MINIX2 */
243
244 /*
245 MINIX 1.0 support added by Charles Hedrick,
246 Rutgers University <hedrick@aramis.rutgers.edu>.
247 MINIX also has V7 enabled.
248 */
249 #ifdef MINIX
250 #define TANDEM 0
251 #define MYREAD
252 #define NOSYSIOCTLH
253 #include <limits.h>
254 #endif /* MINIX */
255
256 #ifdef CK_REDIR /* <sys/wait.h> needed only for REDIRECT command. */
257 /*
258 If anybody can figure out how to make this work with NeXTSTEP, be
259 my guest! (NeXTBlah/NeXTBlah/bsd/sys/wait.h does not define WEXITSTATUS)
260 */
261 #ifndef CK_WAIT_H /* If wait.h not already included... */
262 #ifdef OSF /* force OSF to select POSIX wait */
263 #ifdef _BSD /* instead of BSD (see ckcdeb.h) */
264 #define CK_OSF_BSD
265 #undef _BSD
266 #endif /* _BSD */
267 #endif /* OSF */
268 #include <sys/wait.h> /* Include it */
269 #ifdef OSF
270 #ifdef CK_OSF_BSD
271 #define _BSD /* Restore it */
272 #undef CK_OSF_BSD
273 #endif /* CK_OSF_BSD */
274 #endif /* OSF */
275 #endif /* CK_WAIT_H */
276 #endif /* CK_REDIR */
277
278 #include "ckuver.h" /* Version herald */
279 char *ckxsys = HERALD;
280
281 #ifdef CK_UTSNAME
282 #include <sys/utsname.h>
283
284 #ifdef TRU64 /* Tru64 UNIX 4.0 and later */
285 /* Verified on Tru64 4.0F - might break on 4.0E or earlier */
286 #include <sys/sysinfo.h> /* (don't know about OSF/1 or DU) */
287 #include <machine/hal_sysinfo.h>
288 #endif /* TRU64 */
289
290 #ifdef SOLARIS25 /* Solaris 2.5 and later */
291 #include <sys/systeminfo.h> /* (don't know about earlier ones) */
292 #endif /* SOLARIS25 */
293
294 #ifdef UW7
295 #ifndef SYS_NMLN
296 #define SYS_NMLN 257
297 #endif /* NMLN */
298 #endif /* UW7 */
299 #ifdef HPUX9PLUS
300 static int hpis800 = 0;
301 #endif /* HPUX9PLUS */
302 #ifdef SYS_NMLN
303 #define CK_SYSNMLN SYS_NMLN
304 #else
305 #ifdef _SYS_NMLN
306 #define CK_SYSNMLN _SYS_NMLN
307 #else
308 #ifdef UTSLEN
309 #define CK_SYSNMLN UTSLEN
310 #else
311 #define CK_SYSNMLN 31
312 #endif /* UTSLEN */
313 #endif /* _SYS_NMLN */
314 #endif /* SYS_NMLN */
315 char unm_mch[CK_SYSNMLN+1] = { '\0', '\0' };
316 char unm_mod[CK_SYSNMLN+1] = { '\0', '\0' };
317 char unm_nam[CK_SYSNMLN+1] = { '\0', '\0' };
318 char unm_rel[CK_SYSNMLN+1] = { '\0', '\0' };
319 char unm_ver[CK_SYSNMLN+1] = { '\0', '\0' };
320 #endif /* CK_UTSNAME */
321
322 #ifdef CIE
323 #include <stat.h> /* For chasing symlinks, etc. */
324 #else
325 #include <sys/stat.h>
326 #endif /* CIE */
327
328 #ifdef QNX /* 299 */
329 #ifndef IXANY
330 #define IXANY 0
331 #endif /* IXANY */
332 #endif /* QNX */
333
334 /* UUCP lockfile material... */
335
336 #ifndef NOUUCP
337 #ifdef USETTYLOCK
338 #ifdef HAVE_LOCKDEV /* Red Hat baudboy/lockdev */
339 /*
340 Watch out: baudboy.h references open() without making sure it has been
341 declared, resulting in warnings on at least Red Hat 7.3. It's declared in
342 fcntl.h, but we don't include that until later. In this case only, we
343 include it here, and then the second include is harmless because in Red Hat
344 Linux (the only place where you find baudboy.h) fcntl.h is protected from
345 multiple inclusion by _FCNTL_H. - fdc, 10 May 2004.
346
347 NOTE: Although Linux /usr/sbin/lockdev obviates the need for setuid or
348 setgid bits to access the lockfile, C-Kermit will still need them to access
349 the serial port itself unless the port is open for world read/write.
350 Normally setgid uucp does the trick.
351
352 Extra: HAVE_LOCKDEV has been added als openSuSE >= 11.3 doesn't use baudboy
353 but ttylock. - jb, 26 Jul 2010
354 */
355 #include <fcntl.h> /* This has to come before baudboy */
356 #ifdef HAVE_BAUDBOY /* Red Hat baudboy/lockdev */
357 #include <baudboy.h>
358 #else /* !HAVE_BAUDBOY */ /* openSuSE lock via ttylock */
359 #include <ttylock.h>
360 #endif /* HAVE_BAUDBOY */
361 #define LOCK_DIR "/var/lock" /* (even though we don't care) */
362
363 #else /* !HAVE_LOCKDEV */
364
365 #ifdef USE_UU_LOCK
366 #ifdef __FreeBSD__
367 #include <libutil.h> /* FreeBSD */
368 #else
369 #include <util.h> /* OpenBSD */
370 #endif /* HAVE_LOCKDEV */
371 #endif /* __FreeBSD */
372 #endif /* USE_UU_LOCK */
373 #else /* USETTYLOCK */
374
375 /* Name of UUCP tty device lockfile */
376
377 #ifdef LINUXFSSTND
378 #ifndef HDBUUCP
379 #define HDBUUCP
380 #endif /* HDBUUCP */
381 #endif /* LINUXFSSTND */
382
383 #ifdef ACUCNTRL
384 #define LCKDIR
385 #endif /* ACUCNTRL */
386
387 /*
388 PIDSTRING means use ASCII string to represent pid in lockfile.
389 */
390 #ifndef PIDSTRING
391 #ifdef HDBUUCP
392 #define PIDSTRING
393 #else
394 #ifdef BSD44
395 #define PIDSTRING
396 #else
397 #ifdef RTAIX
398 #define PIDSTRING
399 #else
400 #ifdef AIXRS
401 #define PIDSTRING
402 #else
403 #ifdef COHERENT
404 #define PIDSTRING
405 #endif /* COHERENT */
406 #endif /* AIXRS */
407 #endif /* RTAIX */
408 #endif /* BSD44 */
409 #endif /* HDBUUCP */
410 #endif /* PIDSTRING */
411
412 /* Now the PIDSTRING exceptions... */
413
414 #ifdef PIDSTRING
415 #ifdef HPUX
416 #undef PIDSTRING
417 #endif /* HPUX */
418 #endif /* PIDSTRING */
419
420 #ifdef __bsdi__ /* BSDI (at least thru 1.1) */
421 #ifdef PIDSTRING
422 #undef PIDSTRING
423 #endif /* PIDSTRING */
424 #endif /* __bsdi__ */
425
426 #ifdef OSF32 /* Digital UNIX (OSF/1) 3.2 */
427 #ifdef PIDSTRING
428 #undef PIDSTRING
429 #endif /* PIDSTRING */
430 #endif /* OSF32 */
431
432 /*
433 LOCK_DIR is the name of the lockfile directory.
434 If LOCK_DIR is already defined (e.g. on command line), we don't change it.
435 */
436
437 #ifndef LOCK_DIR
438 #ifdef MACOSX
439 #define LOCK_DIR "/var/spool/lock"
440 #endif /* MACOSX */
441 #endif/* LOCK_DIR */
442
443 #ifndef LOCK_DIR
444 #ifdef BSD44
445 #ifdef __386BSD__
446 #define LOCK_DIR "/var/spool/lock"
447 #else
448 #ifdef __FreeBSD__
449 #define LOCK_DIR "/var/spool/lock"
450 #else
451 #ifdef __NetBSD__
452 #define LOCK_DIR "/var/spool/lock"
453 #else
454 #ifdef __OpenBSD__
455 #define LOCK_DIR "/var/spool/lock"
456 #else
457 /* So which ones is this for? */
458 /* Probably original 4.4BSD on Vangogh */
459 /* Plus who knows about Mac OS X... It doesn't even have a cu program */
460 #define LOCK_DIR "/var/spool/uucp"
461 #endif /* __OpenBSD__ */
462 #endif /* __NetBSD__ */
463 #endif /* __FreeBSD__ */
464 #endif /* __386BSD__ */
465 #else
466 #ifdef DGUX430
467 #define LOCK_DIR "/var/spool/locks"
468 #else
469 #ifdef HPUX10
470 #define LOCK_DIR "/var/spool/locks"
471 #else
472 #ifdef RTAIX /* IBM RT PC AIX 2.2.1 */
473 #define LOCK_DIR "/etc/locks"
474 #else
475 #ifdef AIXRS
476 #define LOCK_DIR "/etc/locks"
477 #else
478 #ifdef ISIII
479 #define LOCK_DIR "/etc/locks"
480 #else
481 #ifdef HDBUUCP
482 #ifdef M_SYS5
483 #define LOCK_DIR "/usr/spool/uucp"
484 #else
485 #ifdef M_UNIX
486 #define LOCK_DIR "/usr/spool/uucp"
487 #else
488 #ifdef SVR4
489 #define LOCK_DIR "/var/spool/locks"
490 #else
491 #ifdef SUNOS4
492 #define LOCK_DIR "/var/spool/locks"
493 #else
494 #ifdef LINUXFSSTND
495 #define LOCK_DIR "/var/lock";
496 #else
497 #define LOCK_DIR "/usr/spool/locks"
498 #endif /* LINUXFSSTND */
499 #endif /* SUNOS4 */
500 #endif /* SVR4 */
501 #endif /* M_UNIX */
502 #endif /* M_SYS5 */
503 #else
504 #ifdef LCKDIR
505 #define LOCK_DIR "/usr/spool/uucp/LCK"
506 #else
507 #ifdef COHERENT
508 #define LOCK_DIR "/usr/spool/uucp"
509 #else
510 #define LOCK_DIR "/usr/spool/uucp"
511 #endif /* COHERENT */
512 #endif /* LCKDIR */
513 #endif /* HDBUUCP */
514 #endif /* ISIII */
515 #endif /* AIXRS */
516 #endif /* RTAIX */
517 #endif /* HPUX10 */
518 #endif /* DGUX430 */
519 #endif /* BSD44 */
520 #endif /* !LOCK_DIR (outside ifndef) */
521
522 #ifdef OSF2 /* OSF/1 2.0 or later */
523 #ifdef LOCK_DIR /* (maybe 1.x too, who knows...) */
524 #undef LOCK_DIR
525 #define LOCK_DIR "/var/spool/locks"
526 #endif /* LOCK_DIR */
527 #endif /* OSF2 */
528
529 #ifdef COMMENT
530 /* Sorry no more lockf() -- we lock first and THEN open the device. */
531 #ifdef SVR4
532 #ifndef BSD44
533 #ifndef LOCKF
534 #define LOCKF /* Use lockf() on tty device in SVR4 */
535 #endif /* LOCKF */
536 #endif /* BSD44 */
537 #endif /* SVR4 */
538 #endif /* COMMENT */
539
540 #ifdef NOLOCKF /* But NOLOCKF cancels LOCKF */
541 #ifdef LOCKF
542 #undef LOCKF
543 #endif /* LOCKF */
544 #endif /* NOLOCKF */
545
546 /* More about this below... */
547
548 #endif /* USETTYLOCK */
549 #endif /* NOUUCP */
550
551 /*
552 MYREAD means use our internally defined nonblocking buffered read routine.
553 */
554 #ifdef ATTSV
555 #define MYREAD
556 #endif /* ATTSV */
557
558 #ifdef ATT7300
559 #ifndef MYREAD
560 #define MYREAD
561 #endif /* MYREAD */
562 /* bits for attmodem: internal modem in use, restart getty */
563 #define ISMODEM 1
564 #define DOGETY 512
565 #endif /* ATT7300 */
566
567 #ifdef BSD42
568 #define MYREAD
569 #endif /* BSD42 */
570
571 #ifdef POSIX
572 #define MYREAD
573 #endif /* POSIX */
574 #ifdef __bsdi__
575 #ifndef O_NDELAY
576 #define O_NDELAY O_NONBLOCK
577 #endif /* O_NDELAY */
578 #endif /* __bsdi__ */
579
580 /*
581 Variables available to outside world:
582
583 dftty -- Pointer to default tty name string, like "/dev/tty".
584 dfloc -- 0 if dftty is console, 1 if external line.
585 dfprty -- Default parity
586 dfflow -- Default flow control
587 ckxech -- Flag for who echoes console typein:
588 1 - The program (system echo is turned off)
589 0 - The system (or front end, or terminal).
590 functions that want to do their own echoing should check this flag
591 before doing so.
592
593 flfnam -- Name of lock file, including its path, e.g.,
594 "/usr/spool/uucp/LCK..cul0" or "/etc/locks/tty77"
595 lkflfn -- Name of link to lock file, including its paths
596 haslock -- Flag set if this kermit established a uucp lock.
597 lockpid -- PID of other process that has desired line open, as string.
598 backgrd -- Flag indicating program executing in background ( & on
599 end of shell command). Used to ignore INT and QUIT signals.
600 rtu_bug -- Set by stptrap(). RTU treats ^Z as EOF (but only when we handle
601 SIGTSTP)
602
603 Functions for assigned communication line (either external or console tty):
604
605 sysinit() -- System dependent program initialization
606 syscleanup() -- System dependent program shutdown
607 ttopen(ttname,local,mdmtyp,timo) -- Open the named tty for exclusive access.
608 ttclos() -- Close & reset the tty, releasing any access lock.
609 ttsspd(cps) -- Set the transmission speed of the tty.
610 ttgspd() -- Get (read) the the transmission speed of the tty.
611 ttpkt(speed,flow,parity) -- Put the tty in packet mode and set the speed.
612 ttvt(speed,flow) -- Put the tty in virtual terminal mode.
613 or in DIALING or CONNECTED modem control state.
614 ttres() -- Restore original tty modes.
615 ttscarr(carrier) -- Set carrier control mode, on/off/auto.
616 ttinl(dest,max,timo) -- Timed read line from the tty.
617 ttinc(timo) -- Timed read character from tty.
618 myread() -- Raw mode bulk buffer read, gives subsequent
619 chars one at a time and simulates FIONREAD.
620 myunrd(c) -- Places c back in buffer to be read (one only)
621 ttchk() -- See how many characters in tty input buffer.
622 ttxin(n,buf) -- Read n characters from tty (untimed).
623 ttol(string,length) -- Write a string to the tty.
624 ttoc(c) -- Write a character to the tty.
625 ttflui() -- Flush tty input buffer.
626 ttsndb() -- Send BREAK signal.
627 ttsndlb() -- Send Long BREAK signal.
628
629 ttlock(ttname) -- "Lock" tty device against uucp collisions.
630 ttunlck() -- Unlock tty device.
631
632 For ATT7300/Unix PC, System V:
633 attdial(ttname,speed,telnbr) -- dials ATT7300/Unix PC internal modem
634 offgetty(ttname) -- Turns off getty(1m) for comms line
635 ongetty(ttname) -- Restores getty() to comms line
636 */
637
638 /*
639 Functions for console terminal:
640
641 congm() -- Get console terminal modes.
642 concb(esc) -- Put the console in single-character wakeup mode with no echo.
643 conbin(esc) -- Put the console in binary (raw) mode.
644 conres() -- Restore the console to mode obtained by congm().
645 conoc(c) -- Unbuffered output, one character to console.
646 conol(s) -- Unbuffered output, null-terminated string to the console.
647 conola(s) -- Unbuffered output, array of strings to the console.
648 conxo(n,s) -- Unbuffered output, n characters to the console.
649 conchk() -- Check if characters available at console (bsd 4.2).
650 Check if escape char (^\) typed at console (System III/V).
651 coninc(timo) -- Timed get a character from the console.
652 congks(timo) -- Timed get keyboard scan code.
653 conint() -- Enable terminal interrupts on the console if not background.
654 connoi() -- Disable terminal interrupts on the console if not background.
655
656 Time functions
657
658 msleep(m) -- Millisecond sleep
659 ztime(&s) -- Return pointer to date/time string
660 rtimer() -- Reset timer
661 gtimer() -- Get elapsed time since last call to rtimer()
662 */
663
664 /* Conditional Includes */
665
666 /* Whether to include <sys/file.h> */
667
668 #ifdef RTU /* RTU doesn't */
669 #define NOFILEH
670 #endif /* RTU */
671
672 #ifdef CIE /* CIE does. */
673 #undef NOFILEH
674 #endif /* CIE */
675
676 #ifdef BSD41 /* 4.1 BSD doesn't */
677 #define NOFILEH
678 #endif /* BSD41 */
679
680 #ifdef is68k /* Integrated Solutions 68000 UNIX */
681 #define NOFILEH /* e.g. on Plexux P60 and Sun-1 */
682 #endif /* is68k */
683
684 #ifdef MINIX /* MINIX */
685 #define NOFILEH
686 #endif /* MINIX */
687
688 #ifdef COHERENT /* Coherent */
689 #define NOFILEH
690 #endif /* COHERENT */
691
692 #ifndef NOFILEH /* Now include if selected. */
693 #include <sys/file.h>
694 #endif /* NOFILEH */
695
696 /* POSIX */
697
698 #ifdef BSD44ORPOSIX /* POSIX uses termios.h */
699 #define TERMIOS
700 #ifdef __bsdi__
701 #ifdef POSIX
702 #undef _POSIX_SOURCE /* Get extra stuff from termios.h */
703 #endif /* POSIX */
704 #endif /* __bsdi__ */
705 #include <termios.h>
706 #ifdef LINUX
707 #include <sys/ioctl.h>
708 #endif /* LINUX */
709 #ifdef QNX16
710 #include <ioctl.h>
711 #else
712 #ifdef QNX6
713 #include <ioctl.h>
714 #endif /* QNX6 */
715 #endif /* QNX16 */
716 #ifdef __bsdi__
717 #ifdef POSIX
718 #define _POSIX_SOURCE
719 #endif /* POSIX */
720 #endif /* __bsdi__ */
721 #ifndef BSD44 /* Really POSIX */
722 #ifndef CK_QNX32 /* was CK_QNX32 */
723 #define NOSYSIOCTLH /* No ioctl's allowed. */
724 #undef ultrix /* Turn off any ultrix features. */
725 #endif /* CK_QNX32 */
726 #endif /* BSD44 */
727 #endif /* POSIX */
728
729 /* System III, System V */
730
731 #ifdef ATTSV
732 #ifndef BSD44
733 #ifndef POSIX
734 #include <termio.h>
735 #endif /* POSIX */
736 #endif /* BSD44 */
737 #ifdef TERMIOX
738 /* Need this for termiox structure, RTS/CTS and DTR/CD flow control */
739 #include <termiox.h>
740 struct termiox rctsx;
741 #else
742 #ifdef STERMIOX
743 #ifdef SCO_OSR504
744 /* Sorry, this is truly disgusting but it's SCO's fault. */
745 #ifndef _SVID3
746 #define _CK_SVID3_X
747 #define _SVID3
748 #endif /* _SVID3 */
749 #endif /* SCO_OSR504 */
750 #include <sys/termiox.h>
751 struct termiox rctsx;
752 #ifdef CK_SVID3_X
753 #undef _SVID3
754 #undef CK_SVID3_X
755 #endif /* CK_SVID3_X */
756 #endif /* STERMIOX */
757 #endif /* TERMIOX */
758 #endif /* ATTSV */
759
760 #ifdef COHERENT /* Use termio.h, not sgtty.h for Coherent */
761 #include <termio.h>
762 #endif /* COHERENT */
763
764 #ifdef MINIX /* MINIX uses ioctl's */
765 #define NOSYSIOCTLH /* but has no <sys/ioctl.h> */
766 #endif /* MINIX */
767
768 /* Others */
769
770 #ifndef NOSYSIOCTLH /* Others use ioctl() */
771 #ifdef SUN4S5
772 /*
773 This is to get rid of cpp warning messages that occur because all of
774 these symbols are defined by both termios.h and ioctl.h on the SUN.
775 */
776 #undef ECHO
777 #undef NL0
778 #undef NL1
779 #undef TAB0
780 #undef TAB1
781 #undef TAB2
782 #undef XTABS
783 #undef CR0
784 #undef CR1
785 #undef CR2
786 #undef CR3
787 #undef FF0
788 #undef FF1
789 #undef BS0
790 #undef BS1
791 #undef TOSTOP
792 #undef FLUSHO
793 #undef PENDIN
794 #undef NOFLSH
795 #endif /* SUN4S5 */
796 #include <sys/ioctl.h>
797 #endif /* NOSYSIOCTLH */
798 /*
799 We really, really, REALLY want FIONREAD, because it is the only way to find
800 out not just *if* stuff is waiting to be read, but how much, which is
801 critical to our sliding-window and streaming procedures, not to mention
802 efficiency of CONNECT, etc.
803 */
804 #ifdef BELLV10
805 #include <sys/filio.h> /* For FIONREAD */
806 #ifdef FIONREAD
807 #define MYREAD
808 #endif /* MYREAD */
809 #endif /* BELLV10 */
810
811 #ifndef FIONREAD
812 /* It wasn't found in ioctl.h or term*.h - try these places: */
813 #ifdef UNIXWARE
814 #include <sys/filio.h>
815 #else
816 #ifdef SOLARIS
817 #include <sys/filio.h>
818 #endif /* SOLARIS */
819 #endif /* UNIXWARE */
820 #endif /* FIONREAD */
821
822 #ifdef XENIX /* Was M_UNIX but XENIX implies M_UNIX and applies to XENIX too */
823 /*
824 <sys/socket.h> included above via "ckcnet.h" defines FIONREAD as
825 something. Due to this, in_chk() uses the FIONREAD instead of RDCHK
826 and the hot keys during file transfer (X to cancel file etc) do not
827 work because FIONREAD doesn't work even though it is defined.
828
829 NOTE: This might also be true elsewhere.
830 */
831 #ifdef FIONREAD
832 #undef FIONREAD
833 #endif /* FIONREAD */
834 #endif /* XENIX */
835
836 #ifdef CK_SCOV5 /* Ditto for SCO OpenServer 5.0 */
837 #ifndef SCO_OSR507 /* 299 */
838 #ifdef FIONREAD
839 #undef FIONREAD
840 #endif /* FIONREAD */
841 #endif /* SCO_OSR507 */
842 #endif /* CK_SCOV5 */
843
844 #ifdef SCO_OSR507 /* 299 */
845 #ifdef RDCHK
846 #undef RDCHK
847 #endif /* RDCHK */
848 #endif /* SCO_OSR507 */
849
850 /* Whether to include <fcntl.h> */
851
852 #ifndef is68k /* Only a few don't have this one. */
853 #ifndef BSD41
854 #ifndef FT21
855 #ifndef FT18
856 #ifndef COHERENT
857 #include <fcntl.h>
858 #endif /* COHERENT */
859 #endif /* FT18 */
860 #endif /* FT21 */
861 #endif /* BSD41 */
862 #endif /* not is68k */
863
864 #ifdef COHERENT
865 #ifdef _I386
866 #include <fcntl.h>
867 #else
868 #include <sys/fcntl.h>
869 #endif /* _I386 */
870 #endif /* COHERENT */
871
872 #ifdef ATT7300 /* Unix PC, internal modem dialer */
873 #include <sys/phone.h>
874 #endif /* ATT7300 */
875
876 #ifdef HPUX /* HP-UX variations. */
877 #define HPUXJOBCTL
878 #include <sys/modem.h> /* HP-UX modem signals */
879 #ifdef hp9000s500 /* Model 500 */
880 #undef HPUXJOBCTL
881 #endif /* hp9000s500 */
882 #ifdef HPUXPRE65
883 #undef HPUXJOBCTL
884 typedef long mflag;
885 #endif /* HPUXPRE65 */
886 #ifdef HPUXJOBCTL
887 #include <sys/bsdtty.h> /* HP-UX Berkeley tty support */
888 #endif /* HPUXJOBCTL */
889 #endif /* HPUX */
890
891 /*
892 Which time.h files to include... See ckcdeb.h for defaults.
893 Note that 0, 1, 2, or all 3 of these can be included according to
894 the symbol definitions.
895 */
896 #ifndef NOTIMEH
897 #ifdef TIMEH
898 #include <time.h>
899 #endif /* TIMEH */
900 #endif /* NOTIMEH */
901
902 #ifndef NOSYSTIMEH
903 #ifdef SYSTIMEH
904 #include <sys/time.h>
905 #endif /* SYSTIMEH */
906 #endif /* NOSYSTIMEH */
907
908 #ifndef NOSYSTIMEBH
909 #ifdef SYSTIMEBH
910 #include <sys/timeb.h>
911 #endif /* SYSTIMEBH */
912 #endif /* NOSYSTIMEBH */
913
914 #ifndef NODCLTIMEVAL
915 #ifdef DCLTIMEVAL
916 /*
917 In certain POSIX builds (like Unixware 7), <[sys/]time.h> refuses to
918 define the structs we need to access the higher speeds, so we have to
919 do it ourselves.
920 */
921 struct timeval {
922 long tv_sec;
923 long tv_usec;
924 };
925 struct timezone {
926 int tz_minuteswest;
927 int tz_dsttime;
928 };
929 #endif /* DCLTIMEVAL */
930 #endif /* NODCLTIMEVAL */
931
932 #ifdef __linux__
933 /* THIS IS OBSOLETE since about Linux 0.92 */
934 #ifdef OLINUXHISPEED
935 #include <linux/serial.h>
936 #endif /* OLINUXHISPEED */
937 #ifdef __alpha__ /* Linux on DEC Alpha */
938 #ifndef __GLIBC__ /* But not with glibc */
939 #include <asm/termios.h>
940 #endif /* __GLIBC__ */
941 #endif /* __alpha__ */
942 #endif /* __linux__ */
943
944 #ifdef NOIEXTEN /* This is broken on some systems */
945 #undef IEXTEN /* like Convex/OS 9.1 */
946 #endif /* NOIEXTEN */
947 #ifndef IEXTEN /* Turn off ^O/^V processing. */
948 #define IEXTEN 0 /* Needed, at least, on BSDI. */
949 #endif /* IEXTEN */
950 /*
951 Pick up definitions needed for select() if we don't have them already.
952 Normally they come from <sys/types.h> but some systems get them from
953 <sys/select.h>... Rather than hardwire all of them into the source, we
954 include it if SELECT_H is defined in compile-time CFLAGS.
955 */
956 #ifndef SCO_OSR504
957 #ifdef SELECT_H
958 #include <sys/select.h>
959 #endif /* SELECT_H */
960 #endif /* SCO_OSR504 */
961
962 #ifdef aegis
963 #include "/sys/ins/base.ins.c"
964 #include "/sys/ins/error.ins.c"
965 #include "/sys/ins/ios.ins.c"
966 #include "/sys/ins/sio.ins.c"
967 #include "/sys/ins/pad.ins.c"
968 #include "/sys/ins/time.ins.c"
969 #include "/sys/ins/pfm.ins.c"
970 #include "/sys/ins/pgm.ins.c"
971 #include "/sys/ins/ec2.ins.c"
972 #include "/sys/ins/type_uids.ins.c"
973 #include <default_acl.h>
974 #undef TIOCEXCL
975 #undef FIONREAD
976 #endif /* aegis */
977
978 #ifdef sxaE50 /* PFU Compact A SX/A TISP V10/L50 */
979 #undef FIONREAD
980 #endif /* sxaE50 */
981
982 /* The following #defines are catch-alls for those systems */
983 /* that didn't have or couldn't find <file.h>... */
984
985 #ifndef FREAD
986 #define FREAD 0x01
987 #endif /* FREAD */
988
989 #ifndef FWRITE
990 #define FWRITE 0x10
991 #endif /* FWRITE */
992
993 #ifndef O_RDONLY
994 #define O_RDONLY 000
995 #endif /* O_RDONLY */
996
997 /* This is for ancient Unixes that don't have these tty symbols defined. */
998
999 #ifndef PENDIN
1000 #define PENDIN ICANON
1001 #endif /* PENDIN */
1002 #ifndef FLUSHO
1003 #define FLUSHO ICANON
1004 #endif /* FLUSHO */
1005 #ifndef EXTPROC
1006 #define EXTPROC ICANON
1007 #endif /* EXTPROC */
1008
1009 #ifdef SVORPOSIX
1010 /*
1011 Modem signals are also forbidden in the POSIX world. But some POSIX-based
1012 platforms let us at them anyway if we know where to look.
1013 */
1014 #ifndef NEEDMDMDEFS
1015 /* Doesn't work for Linux */
1016 #ifdef UNIXWARE7
1017 #define NEEDMDMDEFS
1018 #endif /* UNIXWARE7 */
1019 #endif /* NEEDMDMDEFS */
1020
1021 #ifdef NEEDMDMDEFS
1022 #ifndef TIOCMGET
1023 #define TIOCMGET (('t'<<8)|29)
1024 #endif /* TIOCMGET */
1025
1026 #ifndef TIOCM_DTR
1027 #define TIOCM_DTR 0x0002
1028 #endif /* TIOCM_DTR */
1029 #ifndef TIOCM_RTS
1030 #define TIOCM_RTS 0x0004
1031 #endif /* TIOCM_RTS */
1032 #ifndef TIOCM_CTS
1033 #define TIOCM_CTS 0x0020
1034 #endif /* TIOCM_CTS */
1035 #ifndef TIOCM_CAR
1036 #define TIOCM_CAR 0x0040
1037 #endif /* TIOCM_CAR */
1038 #ifndef TIOCM_RNG
1039 #define TIOCM_RNG 0x0080
1040 #endif /* TIOCM_RNG */
1041 #ifndef TIOCM_DSR
1042 #define TIOCM_DSR 0x0100
1043 #endif /* TIOCM_DSR */
1044 #endif /* NEEDMDMDEFS */
1045 #endif /* SVORPOSIX */
1046
1047 /* Declarations */
1048
1049 #ifdef OXOS
1050 #undef TCGETA
1051 #undef TCSETA
1052 #undef TCSETAW
1053 #undef TCSETAF
1054 #define TCGETA TCGETS
1055 #define TCSETA TCSETS
1056 #define TCSETAW TCSETSW
1057 #define TCSETAF TCSETSF
1058 #define termio termios
1059 #endif /* OXOS */
1060
1061 #ifdef SVORPOSIX /* AT&T Sys V or POSIX */
1062 #ifdef UNIXWAREPOSIX /* UnixWare 7 POSIX build */
1063 /*
1064 In Unixware POSIX builds, <[sys/]time.h> refuses to define the
1065 structs we need to access the higher speeds, so we have to do it
1066 ourselves.
1067 */
1068 struct timeval {
1069 long tv_sec;
1070 long tv_usec;
1071 };
1072 struct timezone {
1073 int tz_minuteswest;
1074 int tz_dsttime;
1075 };
1076 #endif /* UNIXWAREPOSIX */
1077 #endif /* SVORPOSIX */
1078
1079 #ifdef __GNUC__
1080 #ifdef XENIX
1081 /*
1082 Because Xenix <time.h> doesn't declare time() if we're using gcc.
1083 */
1084 time_t time();
1085 #endif /* XENIX */
1086 #endif /* __GNUC__ */
1087
1088 /* Special stuff for V7 input buffer peeking */
1089
1090 #ifdef V7
1091 int kmem[2] = { -1, -1};
1092 char *initrawq(), *qaddr[2]={0,0};
1093 #define CON 0
1094 #define TTY 1
1095 #endif /* V7 */
1096
1097 /* dftty is the device name of the default device for file transfer */
1098 /* dfloc is 0 if dftty is the user's console terminal, 1 if an external line */
1099
1100 #ifdef BEOS
1101 char * dftty = NULL;
1102 char * dfmdm = "none";
1103 int dfloc = 0; /* that goes in local mode by default */
1104 #else
1105 #ifndef DFTTY
1106 #ifdef PROVX1
1107 char *dftty = "/dev/com1.dout"; /* Only example so far of a system */
1108 char *dfmdm = "none";
1109 int dfloc = 1; /* that goes in local mode by default */
1110 #else
1111 char *dftty = CTTNAM; /* Remote by default, use normal */
1112 char *dfmdm = "none";
1113 int dfloc = 0; /* controlling terminal name. */
1114 #endif /* PROVX1 */
1115 #else
1116 char *dftty = DFTTY; /* Default location specified on */
1117 char *dfmdm = "none"; /* command line. */
1118 int dfloc = 1; /* controlling terminal name. */
1119 #endif /* DFTTY */
1120 #endif /* BEOS */
1121
1122 #define CON_RES 0 /* Console state is "reset" */
1123 #define CON_CB 1 /* Console state is CBREAK */
1124 #define CON_BIN 2 /* Console state is binary */
1125 static int constate = CON_RES;
1126
1127 #define CONI_RES 0 /* Console interrupts are "reset" */
1128 #define CONI_INT 1 /* Console intterupts are set */
1129 #define CONI_NOI 2 /* Console intterupts are disabled */
1130 static int conistate = CONI_RES;
1131
1132 #ifdef CK_SMALL
1133 #define CONBUFSIZ 15
1134 #else
1135 #define CONBUFSIZ 255
1136 #endif /* CK_SMALL */
1137 static char conbuf[CONBUFSIZ]; /* Console readahead buffer */
1138 static int conbufn = 0; /* Chars in readahead buffer */
1139 static char *conbufp = conbuf; /* Next char in readahead buffer */
1140
1141 char cttnam[DEVNAMLEN+1] = { '\0', '\0' }; /* Determined at runtime */
1142
1143 #ifdef RTU
1144 int rtu_bug = 0; /* set to 1 when returning from SIGTSTP */
1145 #endif /* RTU */
1146
1147 int dfprty = DEFPAR; /* Default parity (0 = none) */
1148 int ttprty = 0; /* The parity that is in use. */
1149 static int ttpmsk = 0xff; /* Parity stripping mask. */
1150 int ttmdm = 0; /* Modem in use. */
1151 int ttcarr = CAR_AUT; /* Carrier handling mode. */
1152 int dfflow = FLO_NONE; /* Default flow control is NONE */
1153 int backgrd = 0; /* Assume in foreground (no '&' ) */
1154 #ifdef F_SETFL
1155 int iniflags = -1; /* fcntl flags for ttyfd */
1156 #endif /* F_SETFL */
1157 int fdflag = 0; /* Flag for redirected stdio */
1158 int ttfdflg = 0; /* Open File descriptor was given */
1159 int tvtflg = 0; /* Flag that ttvt has been called */
1160 long ttspeed = -1L; /* For saving speed */
1161 int ttflow = -9; /* For saving flow */
1162 int ttld = -1; /* Line discipline */
1163
1164 #ifdef sony_news
1165 static int km_con = -1; /* Kanji mode for console tty */
1166 static int km_ext = -1; /* Kanji mode for external device */
1167 #endif /* sony_news */
1168
1169 #ifdef PARSENSE
1170 static int needpchk = 1; /* Need parity check */
1171 #else
1172 static int needpchk = 0;
1173 #endif /* PARSENSE */
1174
1175 extern int stopbits; /* Stop bits */
1176 #ifdef HWPARITY
1177 /*
1178 Unfortunately we must do this with global variables rather than through the
1179 tt...() APIs to avoid changing the APIs and the many modules that use them.
1180 If hwparity != 0, this indicates 8 data bits + parity, rather than 7 data
1181 bits + parity or 8 data bits and no parity, and overrides the regular parity
1182 variable, which is communicated to this module thru ttpkt(), and represented
1183 locally by the ttprty variable.
1184 */
1185 extern int hwparity; /* Hardware parity */
1186 #endif /* HWPARITY */
1187
1188 #ifdef TCPSOCKET
1189 #ifdef TCP_NODELAY
1190 static int nodelay_sav = -1;
1191 #endif /* TCP_NODELAY */
1192 #endif /* TCPSOCKET */
1193
1194 static int sigint_ign = 0; /* SIGINT is ignored */
1195
1196 /*
1197 Having this module rely on external globals is bad, but fixing this
1198 requires overhaul of the ck*tio.c modules for all the different operating
1199 systems supported by C-Kermit. Left for a future release.
1200 */
1201 extern int ttnproto; /* Defined in ckcnet.c */
1202 extern int ttnet; /* Defined in ckcnet.c */
1203 extern int nopush, xfrcan, xfrchr, xfrnum; /* Defined in ckcmai.c */
1204 extern int xsuspend, wasclosed;
1205 extern int inserver, local;
1206
1207 int ckxech = 0; /* 0 if system normally echoes console characters, else 1 */
1208
1209 int ckmaxfiles = 0; /* Max number of open files */
1210
1211 #ifdef CK_ENCRYPTION /* Kerberos */
1212 #include "ckuath.h"
1213 extern int me_encrypt, u_encrypt;
1214 #endif /* CK_ENCRYPTION */
1215
1216 /* Declarations of variables global within this module */
1217
1218 #ifdef TTLEBUF /* See ckcnet.h */
1219 int ttpush = -1;
1220 #define LEBUFSIZ 4096
1221 static CHAR le_buf[LEBUFSIZ];
1222 static int le_start = 0, le_end = 0, le_data = 0;
1223 #endif /* TTLEBUF */
1224
1225 #define MSGBUF_SIZE 1024 /* For debugging */
1226 static char msgbuf[MSGBUF_SIZE];
1227
1228 static int gotsigs = 0;
1229
1230 static time_t tcount = (time_t)0; /* Elapsed time counter */
1231
1232 static SIGTYP (*saval)() = NULL; /* For saving alarm() handler */
1233 static SIGTYP (*savquit)() = NULL; /* and other signal handlers */
1234 #ifdef SIGUSR1
1235 static SIGTYP (*savusr1)() = NULL;
1236 #endif /* SIGUSR1 */
1237 #ifdef SIGUSR2
1238 static SIGTYP (*savusr2)() = NULL;
1239 #endif /* SIGUSR2 */
1240 #ifdef SIGPIPE
1241 static SIGTYP (*savpipe)() = NULL;
1242 #endif /* SIGPIPE */
1243 #ifdef SIGDANGER
1244 static SIGTYP (*savdanger)() = NULL;
1245 #endif /* SIGDANGER */
1246
1247 #ifndef NOJC
1248 static SIGTYP (*jchdlr)() = NULL; /* For checking suspend handler */
1249 #endif /* NOJC */
1250 static int jcshell = -1; /* And flag for result */
1251
1252 /*
1253 BREAKNULS is defined for systems that simulate sending a BREAK signal
1254 by sending a bunch of NUL characters at low speed.
1255 */
1256 #ifdef PROVX1
1257 #ifndef BREAKNULS
1258 #define BREAKNULS
1259 #endif /* BREAKNULS */
1260 #endif /* PROVX1 */
1261
1262 #ifdef V7
1263 #ifndef BREAKNULS
1264 #define BREAKNULS
1265 #endif /* BREAKNULS */
1266 #endif /* V7 */
1267
1268 #ifdef BREAKNULS
1269 static char /* A string of nulls */
1270 *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";
1271 #endif /* BREAKNULS */
1272
1273 #ifdef CK_POSIX_SIG /* Longjump buffers */
1274 static sigjmp_buf sjbuf; /* POSIX signal handling */
1275 #else
1276 static jmp_buf sjbuf;
1277 #endif /* CK_POSIX_SIG */
1278
1279 #ifdef V7
1280 static jmp_buf jjbuf;
1281 #endif /* V7 */
1282
1283 /* static */ /* (Not static any more) */
1284 int ttyfd = -1; /* TTY file descriptor */
1285
1286 int ttpipe = 0; /* NETCMD: Use pipe instead of ttyfd */
1287 int ttpty = 0; /* NETPTY: Use pty instead of ttfyd */
1288
1289 #ifdef NETPTY /* These are in ckupty.c */
1290 extern PID_T pty_fork_pid;
1291 extern int pty_master_fd, pty_slave_fd;
1292 #endif /* NETPTY */
1293
1294 #ifdef NETCMD
1295 #ifdef NETCONN
1296 static int pipe0[2], pipe1[2]; /* Pipes for net i/o */
1297 #endif /* NETCONN */
1298 static PID_T ttpid = 0; /* Process ID for fork */
1299 static int fdin, fdout; /* File descriptors for pipe */
1300 static FILE * ttout = NULL; /* File pointer for output pipe */
1301 #ifdef DCLFDOPEN
1302 /* fdopen() needs declaring because it's not declared in <stdio.h> */
1303 _PROTOTYP( FILE * fdopen, (int, char *) );
1304 #endif /* DCLFDOPEN */
1305 #endif /* NETCMD */
1306
1307 extern int pexitstat, quiet;
1308
1309 #ifdef Plan9
1310 int ttyctlfd = -1; /* TTY control channel - What? UNIX doesn't have one? */
1311 int consctlfd = -1; /* Console control channel */
1312 int noisefd = -1; /* tone channel */
1313 static int ttylastspeed = -1; /* So we can lie about the speed */
1314 #endif /* Plan9 */
1315
1316 int telnetfd = 0; /* File descriptor is for telnet */
1317 #ifdef NETCONN
1318 int x25fd = 0; /* File descriptor is for X.25 */
1319 #endif /* NETCONN */
1320
1321 char lockpid[16] = { '\0', '\0' }; /* PID stored in lockfile, as string */
1322
1323 static int lkf = 0, /* Line lock flag */
1324 cgmf = 0, /* Flag that console modes saved */
1325 xlocal = 0, /* Flag for tty local or remote */
1326 curcarr = 0; /* Carrier mode: require/ignore. */
1327
1328 static int netconn = 0; /* 1 if network connection active */
1329
1330 static char escchr; /* Escape or attn character */
1331
1332 #ifdef CK_SCO32V4
1333 #include <sys/time.h>
1334 #endif /* CK_SCO32V4 */
1335
1336 #ifdef HAVE_TV
1337 static struct timeval tv; /* For getting time, from sys/time.h */
1338 #endif /* HAVE_TV */
1339 #ifdef HAVE_TZ
1340 static struct timezone tz;
1341 #endif /* HAVE_TZ */
1342
1343 #ifdef OSF
1344 static struct timeb ftp; /* And from sys/timeb.h */
1345 #endif /* OSF */
1346
1347 #ifdef BSD29
1348 static long xclock; /* For getting time from sys/time.h */
1349 static struct timeb ftp; /* And from sys/timeb.h */
1350 #endif /* BSD29 */
1351
1352 #ifdef BSD41
1353 static long xclock; /* For getting time from sys/time.h */
1354 static struct timeb ftp; /* And from sys/timeb.h */
1355 #endif /* BSD41 */
1356
1357 #ifdef BELLV10
1358 static long xclock; /* For getting time from sys/time.h */
1359 static struct timeb ftp; /* And from sys/timeb.h */
1360 #endif /* BELLV10 */
1361
1362 #ifdef FT21
1363 static long xclock; /* For getting time from sys/time.h */
1364 static struct timeb ftp; /* And from sys/timeb.h */
1365 #endif /* FT21 */
1366
1367 #ifdef TOWER1
1368 static long xclock; /* For getting time from sys/time.h */
1369 static struct timeb ftp; /* And from sys/timeb.h */
1370 #endif /* TOWER1 */
1371
1372 #ifdef COHERENT
1373 static long xclock; /* For getting time from sys/time.h */
1374 static struct timeb ftp; /* And from sys/timeb.h */
1375 #endif /* COHERENT */
1376
1377 #ifdef V7
1378 static long xclock;
1379 #endif /* V7 */
1380
1381 /* sgtty/termio information... */
1382
1383 #ifdef BSD44ORPOSIX /* POSIX or BSD44 */
1384 static struct termios
1385 ttold, ttraw, tttvt, ttcur,
1386 ccold, ccraw, cccbrk;
1387 #else /* BSD, V7, etc */
1388
1389 #ifdef COHERENT /* Hack alert... */
1390 #define ATTSV
1391 #endif /* COHERENT */
1392
1393 #ifdef ATTSV
1394 static struct termio ttold = {0}; /* Init'd for word alignment, */
1395 static struct termio ttraw = {0}; /* which is important for some */
1396 static struct termio tttvt = {0}; /* systems, like Zilog... */
1397 static struct termio ttcur = {0};
1398 static struct termio ccold = {0};
1399 static struct termio ccraw = {0};
1400 static struct termio cccbrk = {0};
1401 #else
1402 static struct sgttyb /* sgtty info... */
1403 ttold, ttraw, tttvt, ttcur, /* for communication line */
1404 ccold, ccraw, cccbrk; /* and for console */
1405 #ifdef BELLV10
1406 static struct ttydevb /* Device info... */
1407 tdold, tdcur; /* for communication device */
1408 #endif /* BELLV10 */
1409 #ifdef TIOCGETC
1410 static struct tchars tchold, tchnoi;
1411
1412 static int tcharf;
1413 #endif /* TIOCGETC */
1414 #ifdef TIOCGLTC
1415 static struct ltchars ltchold, ltchnoi;
1416 static int ltcharf;
1417 #endif /* TIOCGLTC */
1418 int lmodef = 0; /* Local modes */
1419 int lmode = 0;
1420 #endif /* ATTSV */
1421 #endif /* BSD44ORPOSIX */
1422
1423 #ifdef COMMENT
1424 /* It picks up the speeds but they don't work */
1425 #ifdef UNIXWARE /* For higher serial speeds */
1426 #ifdef UW7 /* in Unixware 7.0 */
1427 #include <sys/asyc.h> /* This picks up 57600 and 115200 */
1428 #endif /* UW7 */
1429 #endif /* UNIXWARE */
1430 #endif /* COMMENT */
1431
1432 #ifdef PROVX1
1433 static struct sgttyb ttbuf;
1434 #endif /* PROVX1 */
1435
1436 #ifdef ultrix
1437 /* do we really need this? */
1438 static struct sgttyb vanilla;
1439 #endif /* ultrix */
1440
1441 #ifdef ATT7300
1442 static int attmodem = 0; /* ATT7300 internal-modem status */
1443 struct updata dialer = {0}; /* Condition dialer for data call */
1444 #endif /* ATT7300 */
1445
1446 #ifndef NOUUCP
1447 #define FLFNAML 128
1448 #ifndef USETTYLOCK
1449 #ifdef RTAIX
1450 char lkflfn[FLFNAML] = { '\0', '\0' }; /* and possible link to it */
1451 #endif /* RTAIX */
1452 char lock2[FLFNAML] = { '\0', '\0' }; /* Name of second lockfile */
1453 #endif /* USETTYLOCK */
1454 #else
1455 #define FLFNAML 7
1456 #endif /* NOUUCP */
1457 char flfnam[FLFNAML+1] = { '\0', '\0' }; /* UUCP lock file path name */
1458
1459 int haslock = 0; /* =1 if this kermit locked uucp */
1460
1461 #ifndef OXOS
1462 #ifdef SVORPOSIX
1463 static int conesc = 0; /* set to 1 if esc char (^\) typed */
1464 #else
1465 #ifdef V7
1466 static int conesc = 0;
1467 #else
1468 #ifdef C70
1469 static int conesc = 0;
1470 #endif /* C70 */
1471 #endif /* V7 */
1472 #endif /* SVORPOSIX */
1473 #endif /* OXOS */
1474
1475 /* Local copy of comm device name or network host */
1476 static char ttnmsv[DEVNAMLEN+1] = { '\0', '\0' };
1477 #ifdef USETTYLOCK
1478 static char lockname[DEVNAMLEN+1]; /* Ditto, the part after "/dev/". */
1479 #endif /* USETTYLOCK */
1480
1481 #ifdef aegis
1482 static status_$t st; /* error status return value */
1483 static short concrp = 0; /* true if console is CRP pad */
1484 static uid_$t ttyuid; /* tty type uid */
1485 static uid_$t conuid; /* stdout type uid */
1486
1487 /* APOLLO Aegis main()
1488 * establish acl usage and cleanup handling
1489 * this makes sure that CRP pads
1490 * get restored to a usable mode
1491 */
main(argc,argv)1492 main(argc,argv) int argc; char **argv; {
1493 status_$t status;
1494 pfm_$cleanup_rec dirty;
1495
1496 PID_T pid = getpid();
1497
1498 /* acl usage according to invoking environment */
1499 default_acl(USE_DEFENV);
1500
1501 /* establish a cleanup continuation */
1502 status = pfm_$cleanup(dirty);
1503 if (status.all != pfm_$cleanup_set) {
1504 /* only handle faults for the original process */
1505 if (pid == getpid() && status.all > pgm_$max_severity) {
1506 /* blew up in main process */
1507 status_$t quo;
1508 pfm_$cleanup_rec clean;
1509
1510 /* restore the console in any case */
1511 conres();
1512
1513 /* attempt a clean exit */
1514 debug(F101, "cleanup fault status", "", status.all);
1515
1516 /* doexit(), then send status to continuation */
1517 quo = pfm_$cleanup(clean);
1518 if (quo.all == pfm_$cleanup_set)
1519 doexit(pgm_$program_faulted,-1);
1520 else if (quo.all > pgm_$max_severity)
1521 pfm_$signal(quo); /* blew up in doexit() */
1522 }
1523 /* send to the original continuation */
1524 pfm_$signal(status);
1525 /*NOTREACHED*/
1526 }
1527 return(ckcmai(argc, argv));
1528 }
1529 #endif /* aegis */
1530
1531 /* ANSI-style prototypes for internal functions. */
1532 /* Functions used outside this module are prototyped in ckcker.h. */
1533
1534 #ifdef apollo
1535 _PROTOTYP( SIGTYP timerh, () );
1536 _PROTOTYP( SIGTYP cctrap, () );
1537 _PROTOTYP( SIGTYP esctrp, () );
1538 _PROTOTYP( SIGTYP sig_ign, () );
1539 #else
1540 _PROTOTYP( SIGTYP timerh, (int) );
1541 _PROTOTYP( SIGTYP cctrap, (int) );
1542 _PROTOTYP( SIGTYP esctrp, (int) );
1543 #endif /* apollo */
1544 _PROTOTYP( int do_open, (char *) );
1545 _PROTOTYP( static int in_chk, (int, int) );
1546 _PROTOTYP( static int ttrpid, (char *) );
1547 _PROTOTYP( static int ttchkpid, (char *) );
1548 _PROTOTYP( static int ttlock, (char *) );
1549 _PROTOTYP( static int ttunlck, (void) );
1550 _PROTOTYP( static VOID sigchld_handler, (int) );
1551 _PROTOTYP( int mygetbuf, (void) );
1552 _PROTOTYP( int myfillbuf, (void) );
1553 _PROTOTYP( VOID conbgt, (int) );
1554 #ifdef ACUCNTRL
1555 _PROTOTYP( VOID acucntrl, (char *, char *) );
1556 #endif /* ACUCNTRL */
1557
1558 #ifdef BSD44ORPOSIX
1559 _PROTOTYP( int carrctl, (struct termios *, int) );
1560 #else
1561 #ifdef ATTSV
1562 _PROTOTYP( int carrctl, (struct termio *, int) );
1563 #else
1564 _PROTOTYP( int carrctl, (struct sgttyb *, int) );
1565 #endif /* ATTSV */
1566 #endif /* BSD44ORPOSIX */
1567
1568 #ifdef ATT7300
1569 _PROTOTYP( int attdial, (char *, long, char *) );
1570 _PROTOTYP( int offgetty, (char *) );
1571 _PROTOTYP( int ongetty, (char *) );
1572 #endif /* ATT7300 */
1573
1574 #ifdef BEOSORBEBOX
1575 #ifdef SELECT
1576 /* BeOS is not capable of using SELECT on anything but sockets */
1577 #undef SELECT
1578 #endif /* SELECT */
1579 #include <kernel/OS.h>
1580 /* #ifdef BE_DR_7 */
1581 static double time_started = 0.0;
1582 struct ALARM_STRUCT {
1583 thread_id thread;
1584 int time;
1585 };
1586 static thread_id alarm_thread = -1;
1587 static struct ALARM_STRUCT alarm_struct;
1588 _PROTOTYP( long do_alarm, (void *) );
1589 _PROTOTYP( unsigned int alarm, (unsigned int) );
1590 _PROTOTYP( void alarm_expired, (void) );
1591 /* #endif */ /* BE_DR_7 */
1592 #endif /* BEOSORBEBOX */
1593
1594 #ifndef xunchar
1595 #define xunchar(ch) (((ch) - 32 ) & 0xFF ) /* Character to number */
1596 #endif /* xunchar */
1597
1598 #ifdef CK_ANSIC
1599 static char *
xxlast(char * s,char c)1600 xxlast(char *s, char c)
1601 #else
1602 static char *
1603 xxlast(s,c) char *s; char c;
1604 #endif /* CK_ANSIC */
1605 /* xxlast */ { /* Last occurrence of character c in string s. */
1606 int i;
1607 for (i = (int)strlen(s); i > 0; i--)
1608 if (s[i-1] == c ) return(s + (i - 1));
1609 return(NULL);
1610 }
1611
1612 /* Timeout handler for communication line input functions */
1613
1614 /*ARGSUSED*/
1615 SIGTYP
timerh(foo)1616 timerh(foo) int foo; {
1617 ttimoff();
1618 #ifdef BEOSORBEBOX
1619 /* #ifdef BE_DR_7 */
1620 alarm_expired();
1621 /* #endif */ /* BE_DR_7 */
1622 #endif /* BEOSORBEBOX */
1623 #ifdef CK_POSIX_SIG
1624 siglongjmp(sjbuf,1);
1625 #else
1626 longjmp(sjbuf,1);
1627 #endif /* CK_POSIX_SIG */
1628 }
1629
1630 /*ARGSUSED*/
1631 SIGTYP
xtimerh(foo)1632 xtimerh(foo) int foo; { /* Like timerh() but does */
1633 #ifdef BEOSORBEBOX /* not reset the timer itself */
1634 /* #ifdef BE_DR_7 */
1635 alarm_expired();
1636 /* #endif */ /* BE_DR_7 */
1637 #endif /* BEOSORBEBOX */
1638 #ifdef CK_POSIX_SIG
1639 siglongjmp(sjbuf,1);
1640 #else
1641 longjmp(sjbuf,1);
1642 #endif /* CK_POSIX_SIG */
1643 }
1644
1645
1646 /* Control-C trap for communication line input functions */
1647
1648 int cc_int; /* Flag */
1649 SIGTYP (* occt)(); /* For saving old SIGINT handler */
1650
1651 /*ARGSUSED*/
1652 SIGTYP
cctrap(foo)1653 cctrap(foo) int foo; { /* Needs arg for ANSI C */
1654 cc_int = 1; /* signal() prototype. */
1655 return;
1656 }
1657
1658 /* S Y S I N I T -- System-dependent program initialization. */
1659
1660 /*
1661 * ttgwsiz() returns:
1662 * 1 tt_rows and tt_cols are known, both altered, both > 0
1663 * 0 tt_rows and/or tt_cols are known, both altered, one or both <= 0
1664 * -1 tt_rows and tt_cols are unknown and unaltered
1665 */
1666
1667 extern int tt_rows, tt_cols;
1668
1669 static int
xttgwsiz()1670 xttgwsiz() {
1671 char *p;
1672 int rows = 0, cols = 0;
1673 p = getenv("LINES");
1674 debug(F110,"xttgwsiz LINES",p,0);
1675 if (p) {
1676 rows = atol(p);
1677 if (rows > 0) {
1678 p = getenv("COLUMNS");
1679 debug(F110,"xttgwsiz COLUMNS",p,0);
1680 if (p) {
1681 cols = atol(p);
1682 if (cols > 0) {
1683 tt_rows = rows;
1684 tt_cols = cols;
1685 return(1);
1686 }
1687 return(0);
1688 }
1689 }
1690 }
1691 return(-1);
1692 }
1693
1694 #ifdef TTLEBUF
1695 VOID
le_init()1696 le_init() { /* LocalEchoInit() */
1697 int i;
1698 for (i = 0; i < LEBUFSIZ; i++)
1699 le_buf[i] = '\0';
1700 le_start = 0;
1701 le_end = 0;
1702 le_data = 0;
1703 }
1704
1705 VOID
le_clean()1706 le_clean() { /* LocalEchoCleanup() */
1707 le_init();
1708 return;
1709 }
1710
1711 int
le_inbuf()1712 le_inbuf() {
1713 int rc = 0;
1714 if (le_start != le_end) {
1715 rc = (le_end -
1716 le_start +
1717 LEBUFSIZ) % LEBUFSIZ;
1718 }
1719 debug(F111,"le_inbuf","chars waiting",rc);
1720 return(rc);
1721 }
1722
1723 int
1724 #ifdef CK_ANSIC
le_putchar(CHAR ch)1725 le_putchar(CHAR ch)
1726 #else
1727 le_putchar(ch) CHAR ch;
1728 #endif /* CK_ANSIC */
1729 /* le_putchar */ {
1730 #ifdef COMMENT
1731 /* In UNIX we do not have another thread taking chars out of the buffer */
1732 while ((le_start - le_end == 1) ||
1733 (le_start == 0 && le_end == LEBUFSIZ - 1)) {
1734 /* Buffer is full */
1735 debug(F111,"le_putchar","Buffer is Full",ch);
1736 ReleaseLocalEchoMutex() ;
1737 msleep(250);
1738 RequestLocalEchoMutex( SEM_INDEFINITE_WAIT ) ;
1739 }
1740 #else
1741 if ((le_start - le_end + LEBUFSIZ)%LEBUFSIZ == 1) {
1742 debug(F110,"le_putchar","buffer is full",0);
1743 return(-1);
1744 }
1745 #endif /* COMMENT */
1746 le_buf[le_end++] = ch;
1747 if (le_end == LEBUFSIZ)
1748 le_end = 0;
1749 le_data = 1;
1750 return(0);
1751 }
1752
1753 int
1754 #ifdef CK_ANSIC
le_puts(CHAR * s,int n)1755 le_puts(CHAR * s, int n)
1756 #else
1757 le_puts(s,n) CHAR * s; int n;
1758 #endif /* CK_ANSIC */
1759 /* le_puts */ {
1760 int rc = 0;
1761 int i = 0;
1762 CHAR * p = (CHAR *)"le_puts";
1763 ckhexdump(p,s,n);
1764 for (i = 0; i < n; i++)
1765 rc = le_putchar((char)s[i]);
1766 debug(F101,"le_puts","",rc);
1767 return(rc);
1768 }
1769
1770 int
1771 #ifdef CK_ANSIC
le_putstr(CHAR * s)1772 le_putstr(CHAR * s)
1773 #else
1774 le_putstr(s) CHAR * s;
1775 #endif /* CK_ANSIC */
1776 /* le_puts */ {
1777 CHAR * p;
1778 int rc = 0;
1779 p = (CHAR *)"le_putstr";
1780 ckhexdump(p,s,(int)strlen((char *)s));
1781 for (p = s; *p && !rc; p++)
1782 rc = le_putchar(*p);
1783 return(rc);
1784 }
1785
1786 int
1787 #ifdef CK_ANSIC
le_getchar(CHAR * pch)1788 le_getchar(CHAR * pch)
1789 #else /* CK_ANSIC */
1790 le_getchar(pch) CHAR * pch;
1791 #endif /* CK_ANSIC */
1792 /* le_gatchar */ {
1793 int rc = 0;
1794 if (le_start != le_end) {
1795 *pch = le_buf[le_start];
1796 le_buf[le_start] = 0;
1797 le_start++;
1798
1799 if (le_start == LEBUFSIZ)
1800 le_start = 0;
1801
1802 if (le_start == le_end) {
1803 le_data = 0;
1804 }
1805 rc++;
1806 } else {
1807 *pch = 0;
1808 }
1809 return(rc);
1810 }
1811 #endif /* TTLEBUF */
1812
1813 #ifdef COMMENT
1814 /*
1815 Some systems like OSF/1 use TIOCGSIZE instead of TIOCGWINSZ.
1816 But as far as I know, whenever TIOCGSIZE is defined, it is
1817 equated to TIOCGWINSZ. For cases where this is not done, try this:
1818 */
1819 #ifndef TIOCGWINSZ
1820 #ifdef TIOCGSIZE
1821 #define TIOCGWINSZ TIOCGSIZE
1822 #endif /* TIOCGSIZE */
1823 #endif /* TIOCGWINSZ */
1824 #endif /* COMMENT */
1825
1826 static int tt_xpixel = 0, tt_ypixel = 0;
1827
1828 int
ttgwsiz()1829 ttgwsiz() {
1830 int x = 0;
1831 #ifndef NONAWS
1832 #ifdef QNX
1833 /*
1834 NOTE: TIOCGWSIZ works here too, but only in the 32-bit version.
1835 This code works for both the 16- and 32-bit versions.
1836 */
1837 extern int dev_size(int, int, int, int *, int *);
1838 int r, c;
1839
1840 if (dev_size(0, -1, -1, &r, &c) == 0) {
1841 debug(F101,"ttgwsiz QNX r","",r);
1842 debug(F101,"ttgwsiz QNX c","",c);
1843 tt_rows = r;
1844 tt_cols = c;
1845 return ((r > 0 && c > 0) ? 1 : 0);
1846 } else return(xttgwsiz());
1847 #else /* QNX */
1848 #ifdef TIOCGWINSZ
1849
1850 /* Note, this was M_UNIX, changed to XENIX to allow cross compilation... */
1851 #ifdef XENIX /* SCO UNIX 3.2v4.0 */
1852 #include <sys/stream.h> /* typedef mblk_t needed by ptem.h */
1853 #include <sys/ptem.h> /* for ttgwsiz() */
1854 #endif /* XENIX */
1855
1856 #ifdef I386IX /* Ditto for Interactive */
1857 #include <sys/stream.h>
1858 #include <sys/ptem.h>
1859 #endif /* I386IX */
1860
1861 /* Note, the above might be needed for some other older SVR3 Intel makes... */
1862
1863 struct winsize w;
1864 tt_xpixel = 0;
1865 tt_ypixel = 0;
1866
1867 #ifdef IKSD
1868 if (inserver)
1869 return(xttgwsiz());
1870 #endif /* IKSD */
1871 x = ioctl(0, (int)TIOCGWINSZ, (char *)&w);
1872 debug(F101,"ttgwsiz TIOCGWINSZ","",x);
1873 if (x < 0) {
1874 return(xttgwsiz());
1875 } else if (w.ws_row > 0 && w.ws_col > 0) {
1876 tt_rows = w.ws_row;
1877 tt_cols = w.ws_col;
1878 tt_xpixel = w.ws_xpixel;
1879 tt_ypixel = w.ws_ypixel;
1880 debug(F101,"ttgwsiz tt_rows","",tt_rows);
1881 debug(F101,"ttgwsiz tt_cols","",tt_cols);
1882 return(1);
1883 } else {
1884 debug(F100,"ttgwsiz TIOCGWINSZ 00","",0);
1885 return(xttgwsiz());
1886 }
1887 #else
1888 return(xttgwsiz());
1889 #endif /* TIOCGWINSZ */
1890 #endif /* QNX */
1891 #endif /* NONAWS */
1892 }
1893
1894
1895 #ifdef RLOGCODE
1896 _PROTOTYP( int rlog_naws, (void) );
1897 #endif /* RLOGCODE */
1898
1899 #ifndef NOSIGWINCH
1900 #ifdef SIGWINCH
1901 SIGTYP
winchh(foo)1902 winchh(foo) int foo; { /* SIGWINCH handler */
1903 int x = 0;
1904 #ifdef CK_TTYFD
1905 #ifndef VMS
1906 extern int ttyfd;
1907 #endif /* VMS */
1908 #endif /* CK_TTYFD */
1909 extern int tt_rows, tt_cols, cmd_rows, cmd_cols;
1910 #ifdef DEBUG
1911 if (deblog) {
1912 debug(F100,"***************","",0);
1913 debug(F100,"SIGWINCH caught","",0);
1914 debug(F100,"***************","",0);
1915 #ifdef NETPTY
1916 debug(F101,"SIGWINCH pty_fork_pid","",pty_fork_pid);
1917 #endif /* NETPTY */
1918 }
1919 #endif /* DEUB */
1920 signal(SIGWINCH,winchh); /* Re-arm the signal */
1921 x = ttgwsiz(); /* Get new window size */
1922 cmd_rows = tt_rows; /* Adjust command screen too */
1923 cmd_cols = tt_cols;
1924
1925 #ifdef CK_TTYFD
1926 if /* If we don't have a connection */
1927 #ifdef VMS /* we're done. */
1928 (vmsttyfd() == -1)
1929 #else
1930 (ttyfd == -1)
1931 #endif /* VMS */
1932 #else
1933 (!local)
1934 #endif /* CK_TTYFD */
1935 return;
1936
1937 #ifdef NETPTY
1938 if (pty_fork_pid > -1) { /* "set host" to a PTY? */
1939 int x;
1940
1941 #ifdef TIOCSWINSZ
1942 struct winsize w; /* Resize the PTY */
1943 errno = 0;
1944 w.ws_col = tt_cols;
1945 w.ws_row = tt_rows;
1946 w.ws_xpixel = tt_xpixel;
1947 w.ws_ypixel = tt_ypixel;
1948 x = ioctl(ttyfd,TIOCSWINSZ,&w);
1949 debug(F101,"winchh TIOCSWINSZ","",x);
1950 debug(F101,"winchh TIOCSWINSZ errno","",errno);
1951 #endif /* TIOCSWINSZ */
1952
1953 errno = 0;
1954 x = kill(pty_fork_pid,SIGWINCH);
1955 debug(F101,"winchh kill","",x);
1956 debug(F101,"winchh kill errno","",errno);
1957 }
1958 #endif /* NETPTY */
1959
1960 /*
1961 This should be OK. It might seem that sending this from
1962 interrupt level could interfere with another TELNET IAC string
1963 that was in the process of being sent. But we always send
1964 TELNET strings with a single write(), which should prevent mixups.
1965 blah_snaws() should protect themselves from being called on the
1966 wrong kind of connection.
1967 */
1968 #ifdef TCPSOCKET
1969 #ifndef NOTTGWSIZ
1970 if (x > 0 && tt_rows > 0 && tt_cols > 0) {
1971 tn_snaws();
1972 #ifdef RLOGCODE
1973 rlog_naws();
1974 #endif /* RLOGCODE */
1975 }
1976 #endif /* NOTTGWSIZ */
1977 #endif /* TCPSOCKET */
1978 SIGRETURN;
1979 }
1980 #endif /* SIGWINCH */
1981 #endif /* NOSIGWINCH */
1982
1983 SIGTYP
sighup(foo)1984 sighup(foo) int foo; { /* SIGHUP handler */
1985 backgrd = 1;
1986 debug(F100,"***************","",0);
1987 debug(F100,"SIGHUP received","",0);
1988 debug(F100,"***************","",0);
1989 doexit(BAD_EXIT,-1);
1990 /*NOTREACHED*/
1991 SIGRETURN; /* Shut picky compilers up... */
1992 }
1993
1994 #ifdef CK_SCO32V4
1995 /* Exists but there is no prototype in the header files */
1996 _PROTOTYP( char * ttyname, (int) );
1997 #else
1998 #ifdef SV68R3V6
1999 _PROTOTYP( char * ttyname, (int) );
2000 #else
2001 #ifdef ultrix
2002 _PROTOTYP( char * ttyname, (int) );
2003 #else
2004 #ifdef HPUX6
2005 _PROTOTYP( char * ttyname, (int) );
2006 #else
2007 #ifdef HPUX5
2008 _PROTOTYP( char * ttyname, (int) );
2009 #else
2010 #ifdef PS2AIX10
2011 _PROTOTYP( char * ttyname, (int) );
2012 #else
2013 #ifdef BSD42
2014 _PROTOTYP( char * ttyname, (int) );
2015 #endif /* BSD42 */
2016 #endif /* PS2AIX10 */
2017 #endif /* HPUX5 */
2018 #endif /* HPUX6 */
2019 #endif /* ultrix */
2020 #endif /* SV68R3V6 */
2021 #endif /* CK_SCO32V4 */
2022
2023 #ifndef SIGUSR1 /* User-defined signals */
2024 #define SIGUSR1 30
2025 #endif /* SIGUSR1 */
2026
2027 #ifndef SIGUSR2
2028 #define SIGUSR2 31
2029 #endif /* SIGUSR2 */
2030
2031 /*
2032 ignorsigs() sets certain signals to SIG_IGN. But when a signal is
2033 ignored, it remains ignored across exec(), so we have to restore these
2034 signals before exec(), which is the purpose of restorsigs().
2035 */
2036 static VOID
ignorsigs()2037 ignorsigs() { /* Ignore these signals */
2038 savquit = signal(SIGQUIT,SIG_IGN); /* Ignore Quit signal */
2039
2040 #ifdef SIGDANGER /* Ignore danger signals */
2041 /*
2042 This signal is sent when the system is low on swap space. Processes
2043 that don't handle it are candidates for termination. If swap space doesn't
2044 clear out enough, we still might be terminated via kill() -- nothing we can
2045 do about that! Conceivably, this could be improved by installing a real
2046 signal handler that warns the user, but that would be pretty complicated,
2047 since we are not always in control of the screen -- e.g. during remote-mode
2048 file transfer.
2049 */
2050 savdanger = signal(SIGDANGER,SIG_IGN); /* e.g. in AIX */
2051 #endif /* SIGDANGER */
2052 #ifdef SIGPIPE
2053 /*
2054 This one comes when a TCP/IP connection is broken by the remote.
2055 We prefer to catch this situation by examining error codes from write().
2056 */
2057 savpipe = signal(SIGPIPE,SIG_IGN);
2058 #endif /* SIGPIPE */
2059 savusr1 = signal(SIGUSR1,SIG_IGN); /* Ignore user-defined signals */
2060 savusr2 = signal(SIGUSR2,SIG_IGN);
2061 }
2062
2063 VOID
restorsigs()2064 restorsigs() { /* Restore these signals */
2065 (VOID) signal(SIGQUIT,savquit); /* (used in ckufio.c) */
2066 #ifdef SIGDANGER
2067 (VOID) signal(SIGDANGER,savdanger);
2068 #endif /* SIGDANGER */
2069 #ifdef SIGPIPE
2070 (VOID) signal(SIGPIPE,savpipe);
2071 #endif /* SIGPIPE */
2072 (VOID) signal(SIGUSR1,savusr1);
2073 (VOID) signal(SIGUSR2,savusr2);
2074 }
2075
2076 int
sysinit()2077 sysinit() {
2078 int x;
2079 char * s;
2080 #ifdef CK_UTSNAME
2081 struct utsname name;
2082 #endif /* CK_UTSNAME */
2083
2084 extern char startupdir[];
2085 /*
2086 BEFORE ANYTHING ELSE: Initialize the setuid package.
2087 Change to the user's real user and group ID.
2088 If this can't be done, don't run at all.
2089 */
2090 x = priv_ini();
2091 #ifdef SUIDDEBUG
2092 fprintf(stderr,"PRIV_INI=%d\n",x);
2093 #endif /* SUIDDEBUG */
2094 if (x) {
2095 if (x & 1) fprintf(stderr,"Fatal: setuid failure.\n");
2096 if (x & 2) fprintf(stderr,"Fatal: setgid failure.\n");
2097 if (x & 4) fprintf(stderr,"Fatal: C-Kermit setuid to root!\n");
2098 exit(1);
2099 }
2100 signal(SIGINT,SIG_IGN); /* Ignore interrupts at first */
2101 signal(SIGFPE,SIG_IGN); /* Ignore floating-point exceptions */
2102 signal(SIGHUP,sighup); /* Catch SIGHUP */
2103 #ifndef NOSIGWINCH
2104 #ifdef SIGWINCH
2105 signal(SIGWINCH,winchh); /* Catch window-size change */
2106 #endif /* SIGWINCH */
2107 #endif /* NOSIGWINCH */
2108
2109 #ifdef SIGXFSZ
2110 signal(SIGXFSZ,SIG_IGN); /* Ignore writing past file limit */
2111 #endif /* SIGXFSZ */
2112
2113 #ifndef NOJC
2114 /*
2115 Get the initial job control state.
2116 If it is SIG_IGN, that means the shell does not support job control,
2117 and so we'd better not suspend ourselves.
2118 */
2119 #ifdef SIGTSTP
2120 jchdlr = signal(SIGTSTP,SIG_IGN);
2121 if (jchdlr == SIG_IGN) {
2122 jcshell = 0;
2123 debug(F100,"sysinit jchdlr: SIG_IGN","",0);
2124 } else if (jchdlr == SIG_DFL) {
2125 debug(F100,"sysinit jchdlr: SIG_DFL","",0);
2126 jcshell = 1;
2127 } else {
2128 debug(F100,"sysinit jchdlr: other","",0);
2129 jcshell = 3;
2130 }
2131 (VOID) signal(SIGTSTP,jchdlr); /* Put it back... */
2132 #endif /* SIGTSTP */
2133 #endif /* NOJC */
2134
2135 conbgt(0); /* See if we're in the background */
2136 congm(); /* Get console modes */
2137
2138 (VOID) signal(SIGALRM,SIG_IGN); /* Ignore alarms */
2139
2140 ignorsigs(); /* Ignore some other signals */
2141
2142 #ifdef F_SETFL
2143 iniflags = fcntl(0,F_GETFL,0); /* Get stdin flags */
2144 #endif /* F_SETFL */
2145
2146 #ifdef ultrix
2147 gtty(0,&vanilla); /* Get sgtty info */
2148 #else
2149 #ifdef AUX
2150 set42sig(); /* Don't ask! (hakanson@cs.orst.edu) */
2151 #endif /* AUX */
2152 #endif /* ultrix */
2153 /*
2154 Warning: on some UNIX systems (SVR4?), ttyname() reportedly opens /dev but
2155 never closes it. If it is called often enough, we run out of file
2156 descriptors and subsequent open()'s of other devices or files can fail.
2157 */
2158 s = NULL;
2159 #ifndef MINIX
2160 if (isatty(0)) /* Name of controlling terminal */
2161 s = ttyname(0);
2162 else if (isatty(1))
2163 s = ttyname(1);
2164 else if (isatty(2))
2165 s = ttyname(2);
2166 debug(F110,"sysinit ttyname(0)",s,0);
2167 #endif /* MINIX */
2168
2169 #ifdef BEOS
2170 if (!dftty)
2171 makestr(&dftty,s);
2172 #endif /* BEOS */
2173
2174 if (s)
2175 ckstrncpy((char *)cttnam,s,DEVNAMLEN+1);
2176 #ifdef SVORPOSIX
2177 #ifndef ANDROID
2178 if (!cttnam[0])
2179 ctermid(cttnam);
2180 #endif /* ANDROID */
2181 #endif /* SVORPOSIX */
2182 if (!cttnam[0])
2183 ckstrncpy((char *)cttnam,dftty,DEVNAMLEN+1);
2184 debug(F110,"sysinit CTTNAM",CTTNAM,0);
2185 debug(F110,"sysinit cttnam",cttnam,0);
2186
2187 ttgwsiz(); /* Get window (screen) dimensions. */
2188
2189 #ifndef NOSYSCONF
2190 #ifdef _SC_OPEN_MAX
2191 ckmaxfiles = sysconf(_SC_OPEN_MAX);
2192 #endif /* _SC_OPEN_MAX */
2193 #endif /* NOSYSCONF */
2194
2195 #ifdef Plan9
2196 if (!backgrd) {
2197 consctlfd = open("/dev/consctl", O_WRONLY);
2198 /*noisefd = open("/dev/noise", O_WRONLY)*/
2199 }
2200 ckxech = 1;
2201 #endif /* Plan9 */
2202
2203 #ifdef CK_UTSNAME
2204 if (uname(&name) > -1) {
2205 ckstrncpy(unm_mch,name.machine,CK_SYSNMLN);
2206 ckstrncpy(unm_nam,name.sysname,CK_SYSNMLN);
2207 ckstrncpy(unm_rel,name.release,CK_SYSNMLN);
2208 ckstrncpy(unm_ver,name.version,CK_SYSNMLN);
2209 #ifdef DEBUG
2210 if (deblog) {
2211 debug(F110,"sysinit uname machine",unm_mch,0);
2212 debug(F110,"sysinit uname sysname",unm_nam,0);
2213 debug(F110,"sysinit uname release",unm_rel,0);
2214 debug(F110,"sysinit uname version",unm_ver,0);
2215 }
2216 #endif /* DEBUG */
2217
2218 #ifdef HPUX9PLUS
2219 if (name.machine[5] == '8')
2220 hpis800 = 1;
2221 else
2222 hpis800 = 0;
2223 debug(F101,"sysinit hpis800","",hpis800);
2224 #endif /* HPUX9PLUS */
2225 #ifdef TRU64
2226 getsysinfo(GSI_PLATFORM_NAME, unm_mod, CK_SYSNMLN, 0, 0);
2227 debug(F110,"sysinit getsysinfo model",unm_mod,0);
2228 #endif /* TRU64 */
2229 #ifdef SOLARIS25
2230 sysinfo(SI_PLATFORM, unm_mod, CK_SYSNMLN);
2231 debug(F110,"sysinit sysinfo model",unm_mod,0);
2232 #endif /* SOLARIS25 */
2233 }
2234 #endif /* CK_UTSNAME */
2235
2236 #ifdef CK_ENVIRONMENT
2237 {
2238 #ifdef TNCODE
2239 extern char tn_env_acct[], tn_env_disp[], tn_env_job[],
2240 tn_env_prnt[], tn_env_sys[];
2241 #endif /* TNCODE */
2242 extern char uidbuf[];
2243 extern char * whoami();
2244 char *p;
2245 #ifdef CKSENDUID
2246 uidbuf[0] = '\0';
2247 #ifdef IKSD
2248 if (!inserver) {
2249 #endif /* IKSD */
2250 p = getenv("USER");
2251 debug(F110,"sysinit uidbuf from USER",uidbuf,0);
2252 if (!p) p = "";
2253 if (!*p) {
2254 p = getenv("LOGNAME");
2255 debug(F110,"sysinit uidbuf from LOGNAME",uidbuf,0);
2256 }
2257 if (!p) p = "";
2258 if (!*p) {
2259 p = whoami();
2260 debug(F110,"sysinit uidbuf from whoami()",uidbuf,0);
2261 }
2262 if (!p) p = "";
2263 ckstrncpy(uidbuf, *p ? p : "UNKNOWN", UIDBUFLEN);
2264 #ifdef IKSD
2265 }
2266 #endif /* IKSD */
2267 debug(F110,"sysinit final uidbuf",uidbuf,0);
2268 #endif /* CKSENDUID */
2269
2270 #ifdef TNCODE
2271 if ((p = getenv("JOB"))) ckstrncpy(tn_env_job,p,63);
2272 if ((p = getenv("ACCT"))) ckstrncpy(tn_env_acct,p,63);
2273 if ((p = getenv("PRINTER"))) ckstrncpy(tn_env_prnt,p,63);
2274 if ((p = getenv("DISPLAY"))) ckstrncpy(tn_env_disp,p,63);
2275 #ifdef aegis
2276 ckstrncpy(tn_env_sys,"Aegis",64);
2277 #else
2278 #ifdef Plan9
2279 ckstrncpy(tn_env_sys,"Plan9",64);
2280 #else
2281 ckstrncpy(tn_env_sys,"UNIX",64);
2282 #endif /* Plan9 */
2283 #endif /* aegis */
2284 #endif /* TNCODE */
2285 }
2286 #endif /* CK_ENVIRONMENT */
2287 #ifdef CK_SNDLOC
2288 {
2289 extern char * tn_loc;
2290 char *p;
2291 if (p = getenv("LOCATION"))
2292 if (tn_loc = (char *)malloc((int)strlen(p)+1))
2293 strcpy(tn_loc,p); /* safe */
2294 }
2295 #endif /* CK_SNDLOC */
2296
2297 ckstrncpy(startupdir, zgtdir(), CKMAXPATH);
2298 startupdir[CKMAXPATH] = '\0';
2299 x = strlen(startupdir);
2300 if (x <= 0) {
2301 startupdir[0] = '/';
2302 startupdir[1] = '\0';
2303 } else if (startupdir[x-1] != '/') {
2304 startupdir[x] = '/';
2305 startupdir[x+1] = '\0';
2306 }
2307 debug(F110,"sysinit startupdir",startupdir,0);
2308 #ifdef TTLEBUF
2309 le_init();
2310 #endif /* TTLEBUF */
2311 #ifdef BSD44ORPOSIX
2312 /* This should catch the ncurses platforms */
2313 /* Some platforms don't have putenv(), like NeXTSTEP */
2314 putenv("NCURSES_NO_SETBUF=1");
2315 #endif /* BSD44ORPOSIX */
2316 return(0);
2317 }
2318
2319 /* S Y S C L E A N U P -- System-dependent program cleanup. */
2320
2321 int
syscleanup()2322 syscleanup() {
2323 #ifdef F_SETFL
2324 if (iniflags > -1)
2325 fcntl(0,F_SETFL,iniflags); /* Restore stdin flags */
2326 #endif /* F_SETFL */
2327 #ifdef ultrix
2328 stty(0,&vanilla); /* Get sgtty info */
2329 #endif /* ultrix */
2330 #ifdef NETCMD
2331 if (ttpid) kill(ttpid,9);
2332 #endif /* NETCMD */
2333 return(0);
2334 }
2335
2336 /* T T O P E N -- Open a tty for exclusive access. */
2337
2338 /*
2339 Call with:
2340 ttname: character string - device name or network host name.
2341 lcl:
2342 If called with lcl < 0, sets value of lcl as follows:
2343 0: the terminal named by ttname is the job's controlling terminal.
2344 1: the terminal named by ttname is not the job's controlling terminal.
2345 But watch out: if a line is already open, or if requested line can't
2346 be opened, then lcl remains (and is returned as) -1.
2347 modem:
2348 Less than zero: ttname is a network host name.
2349 Zero or greater: ttname is a terminal device name.
2350 Zero means a local connection (don't use modem signals).
2351 Positive means use modem signals.
2352 timo:
2353 0 = no timer.
2354 nonzero = number of seconds to wait for open() to return before timing out.
2355
2356 Returns:
2357 0 on success
2358 -5 if device is in use
2359 -4 if access to device is denied
2360 -3 if access to lock directory denied
2361 -2 upon timeout waiting for device to open
2362 -1 on other error
2363 */
2364 static int ttotmo = 0; /* Timeout flag */
2365 /* Flag kept here to avoid being clobbered by longjmp. */
2366
2367 int
ttopen(ttname,lcl,modem,timo)2368 ttopen(ttname,lcl,modem,timo) char *ttname; int *lcl, modem, timo; {
2369
2370 #ifdef BSD44
2371 #define ctermid(x) strcpy(x,"")
2372 #else
2373 #ifdef SVORPOSIX
2374 #ifndef CIE
2375 #ifndef ANDROID
2376 extern char *ctermid(); /* Wish they all had this! */
2377 #endif /* ANDROID */
2378 #else /* CIE Regulus */
2379 #define ctermid(x) strcpy(x,"")
2380 #endif /* CIE */
2381 #endif /* SVORPOSIX */
2382 #endif /* BSD44 */
2383
2384 #ifdef ultrix
2385 int temp = 0;
2386 #endif /* ultrix */
2387
2388 #ifndef OPENFIRST
2389 char fullname[DEVNAMLEN+1];
2390 #endif /* OPENFIRST */
2391
2392 char * fnam; /* Full name after expansion */
2393
2394 int y;
2395
2396 #ifndef pdp11
2397 #define NAMEFD /* Feature to allow name to be an open file descriptor */
2398 #endif /* pdp11 */
2399
2400 #ifdef NAMEFD
2401 char *p;
2402 debug(F101,"ttopen telnetfd","",telnetfd);
2403 #endif /* NAMEFD */
2404
2405 debug(F110,"ttopen ttname",ttname,0);
2406 debug(F110,"ttopen ttnmsv",ttnmsv,0);
2407 debug(F101,"ttopen modem","",modem);
2408 debug(F101,"ttopen netconn","",netconn);
2409 debug(F101,"ttopen ttyfd","",ttyfd);
2410 debug(F101,"ttopen *lcl","",*lcl);
2411 debug(F101,"ttopen ttmdm","",ttmdm);
2412 debug(F101,"ttopen ttnet","",ttnet);
2413
2414 ttpmsk = 0xff;
2415 lockpid[0] = '\0';
2416
2417 if (ttyfd > -1) { /* If device already opened */
2418 if (!strncmp(ttname,ttnmsv,DEVNAMLEN)) /* are new & old names equal? */
2419 return(0); /* Yes, nothing to do - just return */
2420 ttnmsv[0] = '\0'; /* No, clear out old name */
2421 ttclos(ttyfd); /* close old connection. */
2422 }
2423 wasclosed = 0; /* New connection, not closed yet. */
2424 ttpipe = 0; /* Assume it's not a pipe */
2425 ttpty = 0; /* or a pty... */
2426
2427 #ifdef NETCONN
2428 /*
2429 This is a bit tricky... Suppose that previously Kermit had dialed a telnet
2430 modem server ("set host xxx:2001, set modem type usr, dial ..."). Then the
2431 connection was closed (ttyfd = -1), and then a REDIAL command was given. At
2432 this point we've obliterated the negative modem type hack, and so would
2433 treat the IP hostname as a device name, and would then fail because of "No
2434 such device or directory". But the previous connection has left behind some
2435 clues, so let's use them...
2436 */
2437 if (ttyfd < 0) { /* Connection is not open */
2438 if (!strcmp(ttname,ttnmsv)) { /* Old and new names the same? */
2439 if (((netconn > 0) && (ttmdm < 0)) ||
2440 ((ttnet > 0) &&
2441 (!ckstrchr(ttname,'/')) && (ckstrchr(ttname,':')))
2442 ) {
2443 int x, rc;
2444 x = (ttmdm < 0) ? -ttmdm : ttnet;
2445 rc = netopen(ttname, lcl, x);
2446 debug(F111,"ttopen REOPEN netopen",ttname,rc);
2447 if (rc > -1) {
2448 netconn = 1;
2449 xlocal = *lcl = 1;
2450 } else {
2451 netconn = 0;
2452 }
2453 gotsigs = 0;
2454 return(rc);
2455 }
2456 }
2457 }
2458 #endif /* NETCONN */
2459
2460 #ifdef MAXNAMLEN
2461 debug(F100,"ttopen MAXNAMLEN defined","",0);
2462 #else
2463 debug(F100,"ttopen MAXNAMLEN *NOT* defined","",0);
2464 #endif
2465
2466 #ifdef BSD4
2467 debug(F100,"ttopen BSD4 defined","",0);
2468 #else
2469 debug(F100,"ttopen BSD4 *NOT* defined","",0);
2470 #endif /* BSD4 */
2471
2472 #ifdef BSD42
2473 debug(F100,"ttopen BSD42 defined","",0);
2474 #else
2475 debug(F100,"ttopen BSD42 *NOT* defined","",0);
2476 #endif /* BSD42 */
2477
2478 #ifdef MYREAD
2479 debug(F100,"ttopen MYREAD defined","",0);
2480 #else
2481 debug(F100,"ttopen MYREAD *NOT* defined","",0);
2482 #endif /* MYREAD */
2483
2484 #ifdef NETCONN
2485 if (modem < 0) { /* modem < 0 = code for network */
2486 int x;
2487 ttmdm = modem;
2488 modem = -modem; /* Positive network type number */
2489 fdflag = 0; /* Stdio not redirected. */
2490 netconn = 1; /* And it's a network connection */
2491 debug(F111,"ttopen net",ttname,modem);
2492 #ifdef NAMEFD
2493 for (p = ttname; isdigit(*p); p++) ; /* Check for all digits */
2494 if (*p == '\0' && (telnetfd || x25fd)) { /* Avoid X.121 addresses */
2495 ttyfd = atoi(ttname); /* Is there a way to test it's open? */
2496 ttfdflg = 1; /* We got an open file descriptor */
2497 debug(F111,"ttopen net ttfdflg",ttname,ttfdflg);
2498 debug(F101,"ttopen net ttyfd","",ttyfd);
2499 ckstrncpy(ttnmsv,ttname,DEVNAMLEN); /* Remember the "name". */
2500 x = 1; /* Return code is "good". */
2501 if (telnetfd) {
2502 ttnet = NET_TCPB;
2503 if (ttnproto != NP_TCPRAW)
2504 ttnproto = NP_TELNET;
2505 #ifdef SUNX25
2506 } else if (x25fd) {
2507 ttnet = NET_SX25;
2508 ttnproto = NP_NONE;
2509 #endif /* SUNX25 */
2510 }
2511 } else { /* Host name or address given */
2512 #ifdef NETPTY
2513 if (modem == NET_PTY) {
2514 int x;
2515 if (nopush) {
2516 debug(F100,"ttopen PTY: nopush","",0);
2517 return(-1);
2518 }
2519 ttnet = NET_PTY;
2520 ttnproto = NP_NONE;
2521 netconn = 1; /* but we don't use network i/o */
2522 ttpty = 1;
2523 debug(F110,"ttopen PTY",ttname,0);
2524 x = do_pty(&ttyfd,ttname,0);
2525 if (x > -1) {
2526 ckstrncpy(ttnmsv,ttname,DEVNAMLEN);
2527 xlocal = *lcl = 1; /* It's local */
2528 } else {
2529 ttpty = 0;
2530 netconn = 0;
2531 }
2532 gotsigs = 0;
2533 return(x);
2534 }
2535 #endif /* NETPTY */
2536 #ifdef NETCMD
2537 /*
2538 dup2() is not available on older System V platforms like AT&T 3Bx. For
2539 those systems we punt by not defining NETCMD, but we might be able to do
2540 better -- see workarounds for this problem in ckufio.c (search for dup2).
2541 */
2542 if (modem == NET_CMD) {
2543 if (nopush) {
2544 debug(F100,"ttopen pipe: nopush","",0);
2545 return(-1);
2546 }
2547 if (pipe(pipe0) || pipe(pipe1)) {
2548 perror("Pipe error");
2549 return(-1);
2550 }
2551 ttpid = fork(); /* Make a fork */
2552
2553 switch (ttpid) {
2554 case -1: /* Error making fork */
2555 close(pipe0[0]);
2556 close(pipe0[1]);
2557 close(pipe1[0]);
2558 close(pipe1[1]);
2559 perror("Fork error");
2560 return(-1);
2561 case 0: /* Child. */
2562 close(pipe0[0]);
2563 close(pipe1[1]);
2564 dup2(pipe0[1], 1);
2565 close(pipe0[1]);
2566 dup2(pipe1[0], 0);
2567 close(pipe1[0]);
2568 /*
2569 I can't image what this is; system() executes a shell command.
2570 ttname holds the name of terminal device, it's not a command.
2571 --fdc Fri Sep 18 15:51:18 2020
2572 system(ttname);
2573 */
2574 _exit(0);
2575 default: /* Parent */
2576 close(pipe0[1]);
2577 close(pipe1[0]);
2578 fdin = pipe0[0]; /* Read from pipe */
2579 fdout = pipe1[1]; /* Write to pipe */
2580 ttout = fdopen(fdout,"w"); /* Get stream so we can */
2581 if (!ttout) { /* make it unbuffered. */
2582 perror("fdopen failure");
2583 return(-1);
2584 }
2585 setbuf(ttout,NULL);
2586 ckstrncpy(ttnmsv,ttname,DEVNAMLEN);
2587 xlocal = *lcl = 1; /* It's local */
2588 netconn = 1; /* Call it a network connection */
2589 ttmdm = modem; /* Remember network type */
2590 ttyfd = fdin;
2591 ttpipe = 1;
2592 gotsigs = 0;
2593 return(0);
2594 }
2595 }
2596 #endif /* NETCMD */
2597 #endif /* NAMEFD */
2598 x = netopen(ttname, lcl, modem); /* (see ckcnet.h) */
2599 if (x > -1) {
2600 ckstrncpy(ttnmsv,ttname,DEVNAMLEN);
2601 } else netconn = 0;
2602 #ifdef NAMEFD
2603 }
2604 #endif /* NAMEFD */
2605
2606 #ifdef sony_news /* Sony NEWS */
2607 if (ioctl(ttyfd,TIOCKGET,&km_ext) < 0) { /* Get Kanji mode */
2608 perror("ttopen error getting Kanji mode (network)");
2609 debug(F111,"ttopen error getting Kanji mode","network",0);
2610 km_ext = -1; /* Make sure this stays undefined. */
2611 }
2612 #endif /* sony_news */
2613
2614 xlocal = *lcl = 1; /* Network connections are local. */
2615 debug(F101,"ttopen net x","",x);
2616 #ifdef COMMENT
2617 /* Let netopen() do this */
2618 if (x > -1 && !x25fd)
2619 x = tn_ini(); /* Initialize TELNET protocol */
2620 #endif /* COMMENT */
2621 gotsigs = 0;
2622 return(x);
2623 } else { /* Terminal device */
2624 #endif /* NETCONN */
2625
2626 #ifdef NAMEFD
2627 /*
2628 This code lets you give Kermit an open file descriptor for a serial
2629 communication device, rather than a device name. Kermit assumes that the
2630 line is already open, locked, conditioned with the right parameters, etc.
2631 */
2632 for (p = ttname; isdigit(*p); p++) ; /* Check for all-digits */
2633 if (*p == '\0') {
2634 ttyfd = atoi(ttname); /* Is there a way to test it's open? */
2635 debug(F111,"ttopen got open fd",ttname,ttyfd);
2636 ckstrncpy(ttnmsv,ttname,DEVNAMLEN); /* Remember the "name". */
2637 if (ttyfd >= 0 && ttyfd < 3) /* If it's stdio... */
2638 xlocal = *lcl = 0; /* we're in remote mode */
2639 else /* otherwise */
2640 xlocal = *lcl = 1; /* local mode. */
2641 netconn = 0; /* Assume it's not a network. */
2642 tvtflg = 0; /* Might need to initialize modes. */
2643 ttmdm = modem; /* Remember modem type. */
2644 fdflag = 0; /* Stdio not redirected. */
2645 ttfdflg = 1; /* Flag we were opened this way. */
2646 debug(F111,"ttopen non-net ttfdflg",ttname,ttfdflg);
2647 debug(F101,"ttopen non-net ttyfd","",ttyfd);
2648
2649 #ifdef sony_news /* Sony NEWS */
2650 /* Get device Kanji mode */
2651 if (ioctl(ttyfd,TIOCKGET,&km_ext) < 0) {
2652 perror("ttopen error getting Kanji mode");
2653 debug(F101,"ttopen error getting Kanji mode","",0);
2654 km_ext = -1; /* Make sure this stays undefined. */
2655 }
2656 #endif /* sony_news */
2657 gotsigs = 0;
2658 return(0); /* Return success */
2659 }
2660 #endif /* NAMEFD */
2661 #ifdef NETCONN
2662 }
2663 #endif /* NETCONN */
2664
2665 /* Here we have to open a serial device of the given name. */
2666
2667 netconn = 0; /* So it's not a network connection */
2668 occt = signal(SIGINT, cctrap); /* Set Control-C trap, save old one */
2669 sigint_ign = 0;
2670
2671 tvtflg = 0; /* Flag for use by ttvt(). */
2672 /* 0 = ttvt not called yet for this device */
2673
2674 fdflag = (!isatty(0) || !isatty(1)); /* Flag for stdio redirected */
2675 debug(F101,"ttopen fdflag","",fdflag);
2676
2677 ttmdm = modem; /* Make this available to other fns */
2678 xlocal = *lcl; /* Make this available to other fns */
2679
2680 /* Code for handling bidirectional tty lines goes here. */
2681 /* Use specified method for turning off logins and suppressing getty. */
2682
2683 #ifdef ACUCNTRL
2684 /* Should put call to priv_on() here, but that would be very risky! */
2685 acucntrl("disable",ttname); /* acucntrl() program. */
2686 /* and priv_off() here... */
2687 #else
2688 #ifdef ATT7300
2689 if ((attmodem & DOGETY) == 0) /* offgetty() program. */
2690 attmodem |= offgetty(ttname); /* Remember response. */
2691 #endif /* ATT7300 */
2692 #endif /* ACUCNTRL */
2693
2694 #ifdef OPENFIRST
2695 /*
2696 1985-2001: opens device first then gets lock; reason:
2697 Kermit usually has to run setuid or setgid in order to create a lockfile.
2698 If you give a SET LINE command for a device that happens to be your job's
2699 controlling terminal, Kermit doesn't have to create a lockfile, and in fact
2700 should not create one, and would fail if it tried to if it did not have the
2701 required privileges. But you can't find out if two tty device names are
2702 equivalent until you have a file descriptor that you can give to ttyname().
2703 But this can cause a race condition between Kermit and [m]getty. So see
2704 the [#]else part...
2705 */
2706
2707 /*
2708 In the following section, we open the tty device for read/write.
2709 If a modem has been specified via "set modem" prior to "set line"
2710 then the O_NDELAY parameter is used in the open, provided this symbol
2711 is defined (e.g. in fcntl.h), so that the program does not hang waiting
2712 for carrier (which in most cases won't be present because a connection
2713 has not been dialed yet). O_NDELAY is removed later on in ttopen(). It
2714 would make more sense to first determine if the line is local before
2715 doing this, but because ttyname() requires a file descriptor, we have
2716 to open it first. See do_open().
2717
2718 Now open the device using the desired treatment of carrier.
2719 If carrier is REQUIRED, then open could hang forever, so an optional
2720 timer is provided. If carrier is not required, the timer should never
2721 go off, and should do no harm...
2722 */
2723 ttotmo = 0; /* Flag no timeout */
2724 debug(F101,"ttopen timo","",timo);
2725 debug(F101,"ttopen xlocal","",xlocal);
2726 if (timo > 0) {
2727 int xx;
2728 saval = signal(SIGALRM,timerh); /* Timed, set up timer. */
2729 xx = alarm(timo); /* Timed open() */
2730 debug(F101,"ttopen alarm","",xx);
2731 if (
2732 #ifdef CK_POSIX_SIG
2733 sigsetjmp(sjbuf,1)
2734 #else
2735 setjmp(sjbuf)
2736 #endif /* CK_POSIX_SIG */
2737 ) {
2738 ttotmo = 1; /* Flag timeout. */
2739 } else ttyfd = do_open(ttname);
2740 ttimoff();
2741 debug(F111,"ttopen","modem",modem);
2742 debug(F101,"ttopen ttyfd","",ttyfd);
2743 debug(F101,"ttopen alarm return","",ttotmo);
2744 } else {
2745 errno = 0;
2746 ttyfd = do_open(ttname);
2747 }
2748 debug(F111,"ttopen ttyfd",ttname,ttyfd);
2749 if (ttyfd < 0) { /* If couldn't open, fail. */
2750 debug(F101,"ttopen errno","",errno);
2751 if (errno > 0 && !quiet)
2752 perror(ttname); /* Print message */
2753
2754 #ifdef ATT7300
2755 if (attmodem & DOGETY) /* was getty(1m) running before us? */
2756 ongetty(ttnmsv); /* yes, restart on tty line */
2757 attmodem &= ~DOGETY; /* no phone in use, getty restored */
2758 #else
2759 #ifdef ACUCNTRL
2760 /* Should put call to priv_on() here, but that would be risky! */
2761 acucntrl("enable",ttname); /* acucntrl() program. */
2762 /* and priv_off() here... */
2763 #endif /* ACUNTRL */
2764 #endif /* ATT7300 */
2765
2766 signal(SIGINT,occt); /* Put old Ctrl-C trap back. */
2767 if (errno == EACCES) { /* Device is protected against user */
2768 debug(F110,"ttopen EACCESS",ttname,0); /* Return -4 */
2769 return(-4);
2770 } else return(ttotmo ? -2 : -1); /* Otherwise -2 if timeout, or -1 */
2771 }
2772
2773 #ifdef QNX
2774 {
2775 extern int qnxportlock;
2776 x = qnxopencount();
2777 debug(F101,"ttopen qnxopencount","",x);
2778 debug(F101,"ttopen qnxportlock","",qnxportlock);
2779 if (x < 0 && qnxportlock) {
2780 ttclos(0);
2781 printf("?Can't get port open count\n");
2782 printf("(Try again with SET QNX-PORT-LOCK OFF)\n");
2783 return(-1); /* Indicate device is in use */
2784 }
2785 if (x > 1) { /* 1 == me */
2786 if (qnxportlock)
2787 ttclos(0);
2788 return(-2); /* Indicate device is in use */
2789 else if (!quiet)
2790 printf("WARNING: \"%s\" looks busy...\n",ttdev);
2791 }
2792 }
2793 #endif /* QNX */
2794
2795 #ifdef Plan9
2796 /* take this opportunity to open the control channel */
2797 if (p9openttyctl(ttname) < 0)
2798 #else
2799 /* Make sure it's a real tty. */
2800 if (!ttfdflg && !isatty(ttyfd) && strcmp(ttname,"/dev/null"))
2801 #endif /* Plan9 */
2802 {
2803 fprintf(stderr,"%s is not a terminal device\n",ttname);
2804 debug(F111,"ttopen not a tty",ttname,errno);
2805 close(ttyfd);
2806 ttyfd = -1;
2807 wasclosed = 1;
2808 signal(SIGINT,occt);
2809 return(-1);
2810 }
2811
2812 #ifdef aegis
2813 /* Apollo C runtime claims that console pads are tty devices, which
2814 * is reasonable, but they aren't any good for packet transfer. */
2815 ios_$inq_type_uid((short)ttyfd, ttyuid, st);
2816 if (st.all != status_$ok) {
2817 fprintf(stderr, "problem getting tty object type: ");
2818 error_$print(st);
2819 } else if (ttyuid != sio_$uid) { /* reject non-SIO lines */
2820 close(ttyfd); ttyfd = -1;
2821 wasclosed = 1;
2822 errno = ENOTTY; perror(ttname);
2823 signal(SIGINT,occt);
2824 return(-1);
2825 }
2826 #endif /* aegis */
2827
2828 sigint_ign = (occt == SIG_IGN) ? 1 : 0;
2829
2830 ckstrncpy(ttnmsv,ttname,DEVNAMLEN); /* Keep copy of name locally. */
2831
2832 /* Caller wants us to figure out if line is controlling tty */
2833
2834 if (*lcl < 0) {
2835 if (strcmp(ttname,CTTNAM) == 0) { /* "/dev/tty" always remote */
2836 xlocal = 0;
2837 debug(F111,"ttopen ttname=CTTNAM",ttname,xlocal);
2838 } else if (strcmp(ttname,cttnam) == 0) {
2839 xlocal = 0;
2840 debug(F111,"ttopen ttname=cttnam",ttname,xlocal);
2841 } else if (cttnam[0]) {
2842 #ifdef BEBOX_DR7
2843 x = ttnmsv; /* ttyname() is broken */
2844 #else
2845 x = ttyname(ttyfd); /* Get real name of ttname. */
2846 #endif /* BEBOX_DR7 */
2847 if (!x) x = "";
2848 if (*x)
2849 xlocal = ((strncmp(x,cttnam,DEVNAMLEN) == 0) ? 0 : 1);
2850 else
2851 xlocal = 1;
2852 debug(F111,"ttopen ttyname(ttyfd) xlocal",x,xlocal);
2853 }
2854 }
2855
2856 #ifndef NOFDZERO
2857 /* Note, the following code was added so that Unix "idle-line" snoopers */
2858 /* would not think Kermit was idle when it was transferring files, and */
2859 /* maybe log people out. */
2860 if (xlocal == 0) { /* Remote mode */
2861 if (fdflag == 0) { /* Standard i/o is not redirected */
2862 debug(F100,"ttopen setting ttyfd = 0","",0);
2863 #ifdef LYNXOS
2864 /* On Lynx OS, fd 0 is open for read only. */
2865 dup2(ttyfd,0);
2866 #endif /* LYNXOS */
2867 close(ttyfd); /* Use file descriptor 0 */
2868 ttyfd = 0;
2869 } else { /* Standard i/o is redirected */
2870 debug(F101,"ttopen stdio redirected","",ttyfd);
2871 }
2872 }
2873 #endif /* NOFDZERO */
2874
2875 /* Now check if line is locked -- if so fail, else lock for ourselves */
2876 /* Note: After having done this, don't forget to delete the lock if you */
2877 /* leave ttopen() with an error condition. */
2878
2879 lkf = 0; /* Check lock */
2880 if (xlocal > 0) {
2881 int xx; int xpid;
2882 if ((xx = ttlock(ttname)) < 0) { /* Can't lock it. */
2883 debug(F111,"ttopen ttlock fails",ttname,xx);
2884 /* WARNING - This close() can hang if tty is an empty socket... */
2885 close(ttyfd); /* Close the device. */
2886 ttyfd = -1; /* Erase its file descriptor. */
2887 wasclosed = 1;
2888 signal(SIGINT,occt); /* Put old SIGINT back. */
2889 sigint_ign = (occt == SIG_IGN) ? 1 : 0;
2890 if (xx == -2) { /* If lockfile says device in use, */
2891 #ifndef NOUUCP
2892 debug(F111,"ttopen reading lockfile pid",flfnam,xx);
2893 xpid = ttrpid(flfnam); /* Try to read pid from lockfile */
2894 if (xpid > -1) { /* If we got a pid */
2895 if (!quiet)
2896 printf("Locked by process %d\n",xpid); /* tell them. */
2897 sprintf(lockpid,"%d",xpid); /* Record it too */
2898 debug(F110,"ttopen lockpid",lockpid,0);
2899 } else if (*flfnam) {
2900 extern char *DIRCMD;
2901 char *p = NULL;
2902 int x;
2903 x = (int)strlen(flfnam) + (int)strlen(DIRCMD) + 2;
2904 p = malloc(x); /* Print a directory listing. */
2905 /*
2906 Note: priv_on() won't help here, because we do not pass privs along to
2907 to inferior processes, in this case ls. So if the real user does not have
2908 directory-listing access to the lockfile directory, this will result in
2909 something like "not found". That's why we try this only as a last resort.
2910 */
2911 if (p) { /* If we got the space... */
2912 ckmakmsg(p,x,DIRCMD," ",flfnam,NULL);
2913 zsyscmd(p); /* Get listing. */
2914 if (p) { /* free the space */
2915 free(p);
2916 p = NULL;
2917 }
2918 }
2919 }
2920 #endif /* NOUUCP */
2921 return(-5); /* Code for device in use */
2922 } else return(-3); /* Access denied */
2923 } else lkf = 1;
2924 }
2925 #else /* OPENFIRST */
2926
2927 /*
2928 27 Oct 2001: New simpler code that gets the lock first and then opens the
2929 device, which eliminates the race condition. The downside is you can no
2930 longer say "set line /dev/ttyp0" or whatever, where /dev/ttyp0 is your login
2931 terminal, without trying to create a lockfile, which fails if C-Kermit lacks
2932 privs, and if it succeeds, it has created a lockfile where it didn't create
2933 one before.
2934 */
2935 xlocal = *lcl; /* Is the device my login terminal? */
2936 debug(F111,"ttopen xlocal","A",xlocal);
2937 fnam = ttname;
2938 if (strcmp(ttname,CTTNAM) && netconn == 0) {
2939 if (zfnqfp(ttname,DEVNAMLEN+1,fullname)) {
2940 if ((int)strlen(fullname) > 0)
2941 fnam = fullname;
2942 }
2943 }
2944 debug(F110,"ttopen fnam",fnam,0);
2945 if (xlocal < 0) {
2946 xlocal = (strcmp(fnam,CTTNAM) != 0);
2947 }
2948 debug(F111,"ttopen xlocal","B",xlocal);
2949
2950 lkf = 0; /* No lock yet */
2951 if (xlocal > 0) { /* If not... */
2952 int xx; int xpid;
2953 xx = ttlock(fnam); /* Try to lock it. */
2954 debug(F101,"ttopen ttlock","",xx);
2955 if (xx < 0) { /* Can't lock it. */
2956 debug(F111,"ttopen ttlock fails",fnam,xx);
2957 if (xx == -2) { /* If lockfile says device in use, */
2958 #ifndef NOUUCP
2959 debug(F111,"ttopen reading lockfile pid",flfnam,xx);
2960 xpid = ttrpid(flfnam); /* Try to read pid from lockfile */
2961 if (xpid > -1) { /* If we got a pid */
2962 if (!quiet)
2963 printf("Locked by process %d\n",xpid); /* tell them. */
2964 ckstrncpy(lockpid,ckitoa(xpid),16);
2965 debug(F110,"ttopen lockpid",lockpid,0);
2966 #ifndef NOPUSH
2967 } else if (flfnam[0] && !nopush) {
2968 extern char *DIRCMD;
2969 char *p = NULL;
2970 int x;
2971 x = (int)strlen(flfnam) + (int)strlen(DIRCMD) + 2;
2972 p = malloc(x); /* Print a directory listing. */
2973 /*
2974 Note: priv_on() won't help here, because we do not pass privs along to
2975 to inferior processes, in this case ls. So if the real user does not have
2976 directory-listing access to the lockfile directory, this will result in
2977 something like "not found". That's why we try this only as a last resort.
2978 */
2979 if (p) { /* If we got the space... */
2980 ckmakmsg(p,x,DIRCMD," ",flfnam,NULL);
2981 zsyscmd(p); /* Get listing. */
2982 if (p) { /* free the space */
2983 free(p);
2984 p = NULL;
2985 }
2986 }
2987 #endif /* NOPUSH */
2988 }
2989 #endif /* NOUUCP */
2990 return(-5); /* Code for device in use */
2991 } else return(-3); /* Access denied */
2992 } else lkf = 1;
2993 }
2994 /* Have lock -- now it's safe to open the device */
2995
2996 debug(F101,"ttopen lkf","",lkf);
2997 debug(F101,"ttopen timo","",timo);
2998
2999 ttotmo = 0; /* Flag no timeout */
3000 if (timo > 0) {
3001 int xx;
3002 saval = signal(SIGALRM,timerh); /* Timed, set up timer. */
3003 xx = alarm(timo); /* Timed open() */
3004 debug(F101,"ttopen alarm","",xx);
3005 if (
3006 #ifdef CK_POSIX_SIG
3007 sigsetjmp(sjbuf,1)
3008 #else
3009 setjmp(sjbuf)
3010 #endif /* CK_POSIX_SIG */
3011 ) {
3012 ttotmo = 1; /* Flag timeout. */
3013 } else {
3014 ttyfd = do_open(fnam);
3015 }
3016 ttimoff();
3017 debug(F111,"ttopen timed ttyfd",fnam,ttyfd);
3018 } else {
3019 errno = 0;
3020 ttyfd = do_open(fnam);
3021 debug(F111,"ttopen untimed ttyfd",fnam,ttyfd);
3022 }
3023 if (ttyfd < 0) { /* If couldn't open, fail. */
3024 debug(F111,"ttopen errno",fnam,errno);
3025 debug(F111,"ttopen xlocal","C",xlocal);
3026 if (xlocal == 0) {
3027 debug(F100,"ttopen substituting 0","",0);
3028 ttyfd = 0;
3029 } else {
3030 if (errno > 0 && !quiet) {
3031 debug(F111,"ttopen perror",fnam,errno);
3032 perror(fnam); /* Print message */
3033 }
3034 if (ttunlck()) /* Release the lock file */
3035 fprintf(stderr,"Warning, problem releasing lock\r\n");
3036 }
3037 }
3038
3039 if (ttyfd < 0) { /* ttyfd is still < 0? */
3040 #ifdef ATT7300
3041 if (attmodem & DOGETY) /* was getty(1m) running before us? */
3042 ongetty(ttnmsv); /* yes, restart on tty line */
3043 attmodem &= ~DOGETY; /* no phone in use, getty restored */
3044 #else
3045 #ifdef ACUCNTRL
3046 /* Should put call to priv_on() here, but that would be risky! */
3047 acucntrl("enable",fnam); /* acucntrl() program. */
3048 /* and priv_off() here... */
3049 #endif /* ACUNTRL */
3050 #endif /* ATT7300 */
3051
3052 signal(SIGINT,occt); /* Put old Ctrl-C trap back. */
3053 if (errno == EACCES) { /* Device is protected against user */
3054 debug(F110,"ttopen EACCESS",fnam,0); /* Return -4 */
3055 return(-4);
3056 } else return(ttotmo ? -2 : -1); /* Otherwise -2 if timeout, or -1 */
3057 }
3058
3059 /* Make sure it's a real tty. */
3060
3061 #ifdef Plan9
3062 /* take this opportunity to open the control channel */
3063 if (p9openttyctl(fnam) < 0)
3064 #else
3065 if (!ttfdflg && !isatty(ttyfd) && strcmp(fnam,"/dev/null"))
3066 #endif /* Plan9 */
3067 {
3068 fprintf(stderr,"%s is not a terminal device\n",fnam);
3069 debug(F111,"ttopen not a tty",fnam,errno);
3070 if (ttunlck()) /* Release the lock file */
3071 fprintf(stderr,"Warning, problem releasing lock\r\n");
3072 close(ttyfd);
3073 ttyfd = -1;
3074 wasclosed = 1;
3075 signal(SIGINT,occt);
3076 return(-1);
3077 }
3078
3079 #ifdef aegis
3080 /*
3081 Apollo C runtime claims that console pads are tty devices, which
3082 is reasonable, but they aren't any good for packet transfer.
3083 */
3084 ios_$inq_type_uid((short)ttyfd, ttyuid, st);
3085 if (st.all != status_$ok) {
3086 fprintf(stderr, "problem getting tty object type: ");
3087 error_$print(st);
3088 } else if (ttyuid != sio_$uid) { /* Reject non-SIO lines */
3089 close(ttyfd); ttyfd = -1;
3090 wasclosed = 1;
3091 errno = ENOTTY; perror(fnam);
3092 signal(SIGINT,occt);
3093 return(-1);
3094 }
3095 #endif /* aegis */
3096
3097 sigint_ign = (occt == SIG_IGN) ? 1 : 0;
3098
3099 ckstrncpy(ttnmsv,ttname,DEVNAMLEN); /* Keep copy of name locally. */
3100
3101 /* Caller wants us to figure out if line is controlling tty */
3102
3103 if (*lcl < 0) {
3104 char * s;
3105 if (strcmp(fnam,CTTNAM) == 0) { /* "/dev/tty" always remote */
3106 xlocal = 0;
3107 debug(F111,"ttopen fnam=CTTNAM",fnam,xlocal);
3108 } else if (strcmp(fnam,cttnam) == 0) {
3109 xlocal = 0;
3110 debug(F111,"ttopen fnam=cttnam",fnam,xlocal);
3111 } else if (cttnam[0]) {
3112 #ifdef BEBOX_DR7
3113 s = ttnmsv; /* ttyname() is broken */
3114 #else
3115 s = ttyname(ttyfd); /* Get real name of ttname. */
3116 #endif /* BEBOX_DR7 */
3117 if (!s) s = "";
3118 if (*s)
3119 xlocal = ((strncmp(s,cttnam,DEVNAMLEN) == 0) ? 0 : 1);
3120 else
3121 xlocal = 1;
3122 debug(F111,"ttopen ttyname(ttyfd) xlocal",s,xlocal);
3123 }
3124 }
3125
3126 #ifndef NOFDZERO
3127 /* Note, the following code was added so that Unix "idle-line" snoopers */
3128 /* would not think Kermit was idle when it was transferring files, and */
3129 /* maybe log people out. */
3130 if (xlocal == 0) { /* Remote mode */
3131 if (fdflag == 0) { /* Standard i/o is not redirected */
3132 debug(F100,"ttopen setting ttyfd = 0","",0);
3133 #ifdef LYNXOS
3134 /* On Lynx OS, fd 0 is open for read only. */
3135 dup2(ttyfd,0);
3136 #endif /* LYNXOS */
3137 close(ttyfd); /* Use file descriptor 0 */
3138 ttyfd = 0;
3139 } else { /* Standard i/o is redirected */
3140 debug(F101,"ttopen stdio redirected","",ttyfd);
3141 }
3142 }
3143 #endif /* NOFDZERO */
3144 #endif /* OPENFIRST */
3145
3146 /* Got the line, now set the desired value for local. */
3147
3148 if (*lcl != 0) *lcl = xlocal;
3149
3150 /* Some special stuff for v7... */
3151
3152 #ifdef V7
3153 #ifndef MINIX
3154 if (kmem[TTY] < 0) { /* If open, then skip this. */
3155 qaddr[TTY] = initrawq(ttyfd); /* Init the queue. */
3156 if ((kmem[TTY] = open("/dev/kmem", 0)) < 0) {
3157 fprintf(stderr, "Can't read /dev/kmem in ttopen.\n");
3158 perror("/dev/kmem");
3159 exit(1);
3160 }
3161 }
3162 #endif /* !MINIX */
3163 #endif /* V7 */
3164
3165 /* No failure returns after this point */
3166
3167 #ifdef ultrix
3168 ioctl(ttyfd, TIOCMODEM, &temp);
3169 #ifdef TIOCSINUSE
3170 if (xlocal && ioctl(ttyfd, TIOCSINUSE, NULL) < 0) {
3171 if (!quiet)
3172 perror(fnam);
3173 }
3174 #endif /* TIOCSINUSE */
3175 #endif /* ultrix */
3176
3177 /* Get tty device settings */
3178
3179 #ifdef BSD44ORPOSIX /* POSIX */
3180 tcgetattr(ttyfd,&ttold);
3181 debug(F101,"ttopen tcgetattr ttold.c_lflag","",ttold.c_lflag);
3182 tcgetattr(ttyfd,&ttraw);
3183 debug(F101,"ttopen tcgetattr ttraw.c_lflag","",ttraw.c_lflag);
3184 tcgetattr(ttyfd,&tttvt);
3185 debug(F101,"ttopen tcgetattr tttvt.c_lflag","",tttvt.c_lflag);
3186 #else /* BSD, V7, and all others */
3187 #ifdef ATTSV /* AT&T UNIX */
3188 ioctl(ttyfd,TCGETA,&ttold);
3189 debug(F101,"ttopen ioctl TCGETA ttold.c_lflag","",ttold.c_lflag);
3190 ioctl(ttyfd,TCGETA,&ttraw);
3191 ioctl(ttyfd,TCGETA,&tttvt);
3192 #else
3193 #ifdef BELLV10
3194 ioctl(ttyfd,TIOCGETP,&ttold);
3195 debug(F101,"ttopen BELLV10 ttold.sg_flags","",ttold.sg_flags);
3196 ioctl(ttyfd,TIOCGDEV,&tdold);
3197 debug(F101,"ttopen BELLV10 tdold.flags","",tdold.flags);
3198 #else
3199 gtty(ttyfd,&ttold);
3200 debug(F101,"ttopen gtty ttold.sg_flags","",ttold.sg_flags);
3201 #endif /* BELLV10 */
3202
3203 #ifdef sony_news /* Sony NEWS */
3204 if (ioctl(ttyfd,TIOCKGET,&km_ext) < 0) { /* Get console Kanji mode */
3205 perror("ttopen error getting Kanji mode");
3206 debug(F101,"ttopen error getting Kanji mode","",0);
3207 km_ext = -1; /* Make sure this stays undefined. */
3208 }
3209 #endif /* sony_news */
3210
3211 #ifdef TIOCGETC
3212 debug(F100,"ttopen TIOCGETC","",0);
3213 tcharf = 0; /* In remote mode, also get */
3214 if (xlocal == 0) { /* special characters */
3215 if (ioctl(ttyfd,TIOCGETC,&tchold) < 0) {
3216 debug(F100,"ttopen TIOCGETC failed","",0);
3217 } else {
3218 tcharf = 1; /* It worked. */
3219 ioctl(ttyfd,TIOCGETC,&tchnoi); /* Get another copy */
3220 debug(F100,"ttopen TIOCGETC ok","",0);
3221 }
3222 }
3223 #else
3224 debug(F100,"ttopen TIOCGETC not defined","",0);
3225 #endif /* TIOCGETC */
3226
3227 #ifdef TIOCGLTC
3228 debug(F100,"ttopen TIOCGLTC","",0);
3229 ltcharf = 0; /* In remote mode, also get */
3230 if (xlocal == 0) { /* local special characters */
3231 if (ioctl(ttyfd,TIOCGLTC,<chold) < 0) {
3232 debug(F100,"ttopen TIOCGLTC failed","",0);
3233 } else {
3234 ltcharf = 1; /* It worked. */
3235 ioctl(ttyfd,TIOCGLTC,<chnoi); /* Get another copy */
3236 debug(F100,"ttopen TIOCGLTC ok","",0);
3237 }
3238 }
3239 #else
3240 debug(F100,"ttopen TIOCGLTC not defined","",0);
3241 #endif /* TIOCGLTC */
3242
3243 #ifdef TIOCLGET
3244 debug(F100,"ttopen TIOCLGET","",0);
3245 lmodef = 0;
3246 if (ioctl(ttyfd,TIOCLGET,&lmode) < 0) {
3247 debug(F100,"ttopen TIOCLGET failed","",0);
3248 } else {
3249 lmodef = 1;
3250 debug(F100,"ttopen TIOCLGET ok","",0);
3251 }
3252 #endif /* TIOCLGET */
3253
3254 #ifdef BELLV10
3255 ioctl(ttyfd,TIOCGETP,&ttraw);
3256 ioctl(ttyfd,TIOCGETP,&tttvt);
3257 #else
3258 gtty(ttyfd,&ttraw); /* And a copy of it for packets*/
3259 gtty(ttyfd,&tttvt); /* And one for virtual tty service */
3260 #endif /* BELLV10 */
3261
3262 #endif /* ATTSV */
3263 #endif /* BSD44ORPOSIX */
3264
3265 /* Section for changing line discipline. It's restored in ttres(). */
3266
3267 #ifdef AIXRS
3268 #ifndef AIX41
3269 { union txname ld_name; int ld_idx = 0;
3270 ttld = 0;
3271 do {
3272 ld_name.tx_which = ld_idx++;
3273 ioctl(ttyfd, TXGETCD, &ld_name);
3274 if (!strncmp(ld_name.tx_name, "rts", 3))
3275 ttld |= 1;
3276 } while (*ld_name.tx_name);
3277 debug(F101,"AIX line discipline","",ttld);
3278 }
3279 #endif /* AIX41 */
3280 #endif /* AIXRS */
3281
3282 #ifdef BSD41
3283 /* For 4.1BSD only, force "old" tty driver, new one botches TANDEM. */
3284 { int k;
3285 ioctl(ttyfd, TIOCGETD, &ttld); /* Get and save line discipline */
3286 debug(F101,"4.1bsd line discipline","",ttld);
3287 k = OTTYDISC; /* Switch to "old" discipline */
3288 k = ioctl(ttyfd, TIOCSETD, &k);
3289 debug(F101,"4.1bsd tiocsetd","",k);
3290 }
3291 #endif /* BSD41 */
3292
3293 #ifdef aegis
3294 /* This was previously done before the last two TCGETA or gtty above,
3295 * in both the ATTSV and not-ATTSV case. If it is not okay to have only
3296 * one copy if it here instead, give us a shout!
3297 */
3298 sio_$control((short)ttyfd, sio_$raw_nl, false, st);
3299 if (xlocal) { /* ignore breaks from local line */
3300 sio_$control((short)ttyfd, sio_$int_enable, false, st);
3301 sio_$control((short)ttyfd, sio_$quit_enable, false, st);
3302 }
3303 #endif /* aegis */
3304
3305 #ifdef VXVE
3306 ttraw.c_line = 0; /* STTY line 0 for VX/VE */
3307 tttvt.c_line = 0; /* STTY line 0 for VX/VE */
3308 ioctl(ttyfd,TCSETA,&ttraw);
3309 #endif /* vxve */
3310
3311 /* If O_NDELAY was used during open(), then remove it now. */
3312
3313 #ifdef O_NDELAY
3314 debug(F100,"ttopen O_NDELAY","",0);
3315 if (xlocal > 0) {
3316 if (fcntl(ttyfd, F_GETFL, 0) & O_NDELAY) {
3317 debug(F100,"ttopen fcntl O_NDELAY","",0);
3318 #ifndef aegis
3319 if (fcntl(ttyfd,F_SETFL, fcntl(ttyfd, F_GETFL, 0) & ~O_NDELAY) < 0) {
3320 debug(F100,"ttopen fcntl failure to unset O_NDELAY","",0);
3321 perror("Can't unset O_NDELAY");
3322 }
3323 #endif /* aegis */
3324 /* Some systems, notably Xenix (don't know how common this is in
3325 * other systems), need special treatment to get rid of the O_NDELAY
3326 * behaviour on read() with respect to carrier presence (i.e. read()
3327 * returning 0 when carrier absent), even though the above fcntl()
3328 * is enough to make read() wait for input when carrier is present.
3329 * This magic, in turn, requires CLOCAL for working when the carrier
3330 * is absent. But if xlocal == 0, presumably you already have CLOCAL
3331 * or you have a carrier, otherwise you wouldn't be running this.
3332 */
3333 debug(F101,"ttopen xlocal","",xlocal);
3334 #ifdef ATTSV
3335 #ifdef BSD44ORPOSIX
3336 #ifdef COMMENT /* 12 Aug 1997 */
3337 #ifdef __bsdi__
3338 if (xlocal)
3339 ttraw.c_cflag |= CLOCAL;
3340 #else
3341 #ifdef __FreeBSD__
3342 if (xlocal)
3343 ttraw.c_cflag |= CLOCAL;
3344 #endif /* __FreeBSD__ */
3345 #endif /* __bsdi__ */
3346 #else /* Not COMMENT */
3347 #ifdef CLOCAL
3348 if (xlocal) /* Unset this if it's defined. */
3349 ttraw.c_cflag |= CLOCAL;
3350 #endif /* CLOCAL */
3351 #endif /* COMMENT */
3352 debug(F101,"ttopen BSD44ORPOSIX calling tcsetattr","",TCSADRAIN);
3353 if (tcsetattr(ttyfd, TCSADRAIN, &ttraw) < 0) {
3354 debug(F100,"ttopen POSIX tcseattr fails","",0);
3355 perror("tcsetattr");
3356 }
3357 #else /* !BSD44ORPOSIX */
3358 if (xlocal) {
3359 ttraw.c_cflag |= CLOCAL;
3360 debug(F100,"ttopen calling ioctl(TCSETA)","",0);
3361 errno = 0;
3362 if (ioctl(ttyfd, TCSETA, &ttraw) < 0) {
3363 debug(F101,"ttopen ioctl(TCSETA) fails","",errno);
3364 perror("ioctl(TCSETA)");
3365 }
3366 }
3367 #endif /* BSD44ORPOSIX */
3368 #endif /* ATTSV */
3369 #ifndef NOCOTFMC /* = NO Close(Open()) To Force Mode Change */
3370 /* Reportedly lets uugetty grab the device in SCO UNIX 3.2 / XENIX 2.3 */
3371 debug(F100,"ttopen executing close/open","",0);
3372 close( priv_opn(fnam, O_RDWR) ); /* Magic to force change. */
3373 #endif /* NOCOTFMC */
3374 }
3375 }
3376 #endif /* O_NDELAY */
3377
3378 /* Instruct the system how to treat the carrier, and set a few other tty
3379 * parameters.
3380 *
3381 * This also undoes the temporary setting of CLOCAL that may have been done
3382 * for the close(open()) above (except in Xenix). Also throw in ~ECHO, to
3383 * prevent the other end of the line from sitting there talking to itself,
3384 * producing garbage when the user performs a connect.
3385 *
3386 * SCO Xenix unfortunately seems to ignore the actual state of CLOCAL.
3387 * Now it thinks CLOCAL is always on. It seems the only real solution for
3388 * Xenix is to switch between the lower and upper case device names.
3389 *
3390 * This section may at some future time expand into setting a complete
3391 * collection of tty parameters, or call a function shared with ttpkt()/
3392 * ttvt() that does so. On the other hand, the initial parameters are not
3393 * that important, since ttpkt() or ttvt() should always fix that before
3394 * any communication is done. Well, we'll see...
3395 */
3396 if (xlocal) {
3397 curcarr = -2;
3398 debug(F100,"ttopen calling carrctl","",0);
3399 carrctl(&ttraw, ttcarr == CAR_ON);
3400 debug(F100,"ttopen carrctl ok","",0);
3401
3402 #ifdef COHERENT
3403 #define SVORPOSIX
3404 #endif /* COHERENT */
3405
3406 #ifdef SVORPOSIX
3407 ttraw.c_lflag &= ~ECHO;
3408 ttold.c_lflag &= ~ECHO;
3409 #ifdef BSD44ORPOSIX
3410 y = tcsetattr(ttyfd, TCSADRAIN, &ttraw);
3411 debug(F101,"ttopen tcsetattr","",y);
3412 #else
3413 y = ioctl(ttyfd, TCSETA, &ttraw);
3414 debug(F100,"ttopen ioctl","",y);
3415 #endif /* BSD44ORPOSIX */
3416
3417 #else /* BSD, etc */
3418 ttraw.sg_flags &= ~ECHO;
3419 ttold.sg_flags &= ~ECHO;
3420 #ifdef BELLV10
3421 y = ioctl(ttyfd,TIOCSETP,&ttraw);
3422 debug(F100,"ttopen ioctl","",y);
3423 #else
3424 y = stty(ttyfd,&ttraw);
3425 debug(F100,"ttopen stty","",y);
3426 #endif /* BELLV10 */
3427 #endif /* SVORPOSIX */
3428
3429 #ifdef COHERENT
3430 #undef SVORPOSIX
3431 #endif /* COHERENT */
3432
3433 /* ttflui(); */ /* This fails for some reason. */
3434 }
3435
3436 /* Get current speed */
3437
3438 #ifndef BEBOX
3439 ttspeed = ttgspd();
3440 #else
3441 ttspeed = 19200;
3442 #endif /* !BEBOX */
3443 debug(F101,"ttopen ttspeed","",ttspeed);
3444
3445 /* Done, make entries in debug log, restore Ctrl-C trap, and return. */
3446
3447 debug(F101,"ttopen ttyfd","",ttyfd);
3448 debug(F101,"ttopen *lcl","",*lcl);
3449 debug(F111,"ttopen lock file",flfnam,lkf);
3450 signal(SIGINT,occt);
3451 sigint_ign = (occt == SIG_IGN) ? 1 : 0;
3452 gotsigs = 0;
3453 return(0);
3454 }
3455
3456
3457 /* D O _ O P E N -- Do the right kind of open() call for the tty. */
3458
3459 int
do_open(ttname)3460 do_open(ttname) char *ttname; {
3461 int flags;
3462
3463 #ifdef QNX6
3464 /* O_NONBLOCK on /dev/tty makes open() fail */
3465 return(priv_opn(ttname, O_RDWR |
3466 (
3467 ((int)strcmp(ttname,"/dev/tty") == 0) ?
3468 0 :
3469 (ttcarr != CAR_ON) ? O_NONBLOCK : 0)
3470 )
3471 );
3472 #else /* !QNX6 */
3473
3474 #ifndef O_NDELAY /* O_NDELAY not defined */
3475 return(priv_opn(ttname,2));
3476 #else /* O_NDELAY defined */
3477
3478 #ifdef ATT7300
3479 /*
3480 Open comms line without waiting for carrier so initial call does not hang
3481 because state of "modem" is likely unknown at the initial call -jrd.
3482 If this is needed for the getty stuff to work, and the open would not work
3483 without O_NDELAY when getty is still on, then this special case is ok.
3484 Otherwise, get rid of it. -ske
3485 */
3486 return(priv_opn(ttname, O_RDWR | O_NDELAY));
3487
3488 #else /* !ATT7300 */
3489
3490 /* Normal case. Use O_NDELAY according to SET CARRIER. See ttscarr(). */
3491 flags = O_RDWR;
3492 debug(F101,"do_open xlocal","",xlocal);
3493 debug(F111,"do_open flags A",ttname,flags);
3494 if (xlocal && (ttcarr != CAR_ON))
3495 flags |= O_NDELAY;
3496 debug(F111,"do_open flags B",ttname,flags);
3497 return(priv_opn(ttname, flags));
3498 #endif /* !ATT7300 */
3499 #endif /* O_NDELAY */
3500 #endif /* QNX6 */
3501 }
3502
3503 /* T T C L O S -- Close the TTY, releasing any lock. */
3504
3505 static int ttc_state = 0; /* ttclose() state */
3506 static char * ttc_nam[] = { "setup", "hangup", "reset", "close" };
3507
3508 int
ttclos(foo)3509 ttclos(foo) int foo; { /* Arg req'd for signal() prototype */
3510 int xx, x = 0;
3511 extern int exithangup;
3512
3513 debug(F101,"ttclos ttyfd","",ttyfd);
3514 debug(F101,"ttclos netconn","",netconn);
3515 debug(F101,"ttclos xlocal","",xlocal);
3516 #ifdef NOFDZERO
3517 debug(F100,"ttclos NOFDZERO","",0);
3518 #endif /* NOFDZERO */
3519
3520 #ifdef COMMENT
3521 #ifdef TTLEBUF
3522 le_init(); /* No need for any of this */
3523 #endif /* TTLEBUF */
3524 #endif /* COMMENT */
3525
3526 if (ttyfd < 0) /* Wasn't open. */
3527 return(0);
3528
3529 if (ttfdflg) /* If we inherited ttyfd from */
3530 return(0); /* another process, don't close it. */
3531
3532 tvtflg = 0; /* (some day get rid of this...) */
3533 gotsigs = 0;
3534
3535 #ifdef IKSD
3536 if (inserver) {
3537 #ifdef TNCODE
3538 tn_push(); /* Place any waiting data into input*/
3539 tn_sopt(DO,TELOPT_LOGOUT); /* Send LOGOUT option before close */
3540 TELOPT_UNANSWERED_DO(TELOPT_LOGOUT) = 1;
3541 tn_reset(); /* The Reset Telnet Option table. */
3542 #endif /* TNCODE */
3543 #ifdef CK_SSL
3544 if (ssl_active_flag) {
3545 if (ssl_debug_flag)
3546 BIO_printf(bio_err,"calling SSL_shutdown(ssl)\n");
3547 SSL_shutdown(ssl_con);
3548 SSL_free(ssl_con);
3549 ssl_con = NULL;
3550 ssl_active_flag = 0;
3551 }
3552 if (tls_active_flag) {
3553 if (ssl_debug_flag)
3554 BIO_printf(bio_err,"calling SSL_shutdown(tls)\n");
3555 SSL_shutdown(tls_con);
3556 SSL_free(tls_con);
3557 tls_con = NULL;
3558 tls_active_flag = 0;
3559 }
3560 #endif /* CK_SSL */
3561 }
3562 #endif /* IKSD */
3563 #ifdef NETCMD
3564 if (ttpipe) { /* We've been using a pipe */
3565 /* ttpipe = 0; */
3566 if (ttpid > 0) {
3567 int wstat;
3568 int statusp;
3569 close(fdin); /* Close these. */
3570 close(fdout);
3571 fdin = fdout = -1;
3572 kill(ttpid,1); /* Kill fork with SIGHUP */
3573 while (1) {
3574 wstat = wait(&statusp);
3575 if (wstat == ttpid || wstat == -1)
3576 break;
3577 pexitstat = (statusp & 0xff) ? statusp : statusp >> 8;
3578 }
3579 ttpid = 0;
3580 }
3581 netconn = 0;
3582 wasclosed = 1;
3583 ttyfd = -1;
3584 return(0);
3585 }
3586 #endif /* NETCMD */
3587 #ifdef NETPTY
3588 if (ttpty) {
3589 #ifndef NODOPTY
3590 end_pty();
3591 #endif /* NODOPTY */
3592 close(ttyfd);
3593 netconn = 0;
3594 wasclosed = 1;
3595 ttpty = 0;
3596 ttyfd = -1;
3597 return(0);
3598 }
3599 #endif /* NETPTY */
3600
3601 #ifdef NETCONN
3602 if (netconn) { /* If it's a network connection. */
3603 debug(F100,"ttclos closing net","",0);
3604 netclos(); /* Let the network module close it. */
3605 netconn = 0; /* No more network connection. */
3606 debug(F101,"ttclos ttyfd after netclos","",ttyfd); /* Should be -1 */
3607 return(0);
3608 }
3609 #endif /* NETCONN */
3610
3611 if (xlocal) { /* We're closing a SET LINE device */
3612 #ifdef FT21 /* Fortune 2.1-specific items ... */
3613 ioctl(ttyfd,TIOCHPCL, NULL);
3614 #endif /* FT21 */
3615 #ifdef ultrix /* Ultrix-specific items ... */
3616 #ifdef TIOCSINUSE
3617 /* Unset the INUSE flag that we set in ttopen() */
3618 ioctl(ttyfd, TIOCSINUSE, NULL);
3619 #endif /* TIOCSINUSE */
3620 ioctl(ttyfd, TIOCNMODEM, &x);
3621 #ifdef COMMENT
3622 /* What was this? */
3623 ioctl(ttyfd, TIOCNCAR, NULL);
3624 #endif /* COMMENT */
3625 #endif /* ultrix */
3626 }
3627
3628 /* This is to prevent us from sticking in tthang() or close(). */
3629
3630 #ifdef O_NDELAY
3631 #ifndef aegis
3632 if (ttyfd > 0) { /* But skip it on stdin. */
3633 debug(F100,"ttclos setting O_NDELAY","",0);
3634 x = fcntl(ttyfd,F_SETFL,fcntl(ttyfd,F_GETFL, 0)|O_NDELAY);
3635 #ifdef DEBUG
3636 if (deblog && x == -1) {
3637 perror("Warning - Can't set O_NDELAY");
3638 debug(F101,"ttclos fcntl failure to set O_NDELAY","",x);
3639 }
3640 #endif /* DEBUG */
3641 }
3642 #endif /* aegis */
3643 #endif /* O_NDELAY */
3644
3645 x = 0;
3646 ttc_state = 0;
3647 if (xlocal
3648 #ifdef NOFDZERO
3649 || ttyfd > 0
3650 #endif /* NOFDZERO */
3651 ) {
3652 saval = signal(SIGALRM,xtimerh); /* Enable timer interrupt. */
3653 xx = alarm(8); /* Allow 8 seconds. */
3654 debug(F101,"ttclos alarm","",xx);
3655 if (
3656 #ifdef CK_POSIX_SIG
3657 sigsetjmp(sjbuf,1)
3658 #else
3659 setjmp(sjbuf)
3660 #endif /* CK_POSIX_SIG */
3661 ) { /* Timer went off? */
3662 x = -1;
3663 #ifdef DEBUG
3664 debug(F111,"ttclos ALARM TRAP errno",ckitoa(ttc_state),errno);
3665 printf("ttclos() timeout: %s\n", ttc_nam[ttc_state]);
3666 #endif /* DEBUG */
3667 }
3668 /* Hang up the device (drop DTR) */
3669
3670 errno = 0;
3671 debug(F111,"ttclos A",ckitoa(x),ttc_state);
3672 if (ttc_state < 1) {
3673 ttc_state = 1;
3674 debug(F101,"ttclos exithangup","",exithangup);
3675 if (exithangup) {
3676 alarm(8); /* Re-arm the timer */
3677 debug(F101,"ttclos calling tthang()","",x);
3678 x = tthang(); /* Hang up first, then... */
3679 debug(F101,"ttclos tthang()","",x);
3680 }
3681 #ifndef CK_NOHUPCL
3682 /*
3683 Oct 2006 - Leave DTR on if SET EXIT HANGUP OFF.
3684 Suggested by Soewono Effendi.
3685 */
3686 #ifdef HUPCL
3687 else {
3688 ttold.c_cflag &= ~HUPCL; /* Let's see how this travels */
3689 #ifdef BSD44ORPOSIX
3690 tcsetattr(ttyfd,TCSANOW,&ttold);
3691 #else /* !BSD44ORPOSIX */
3692 #ifdef ATTSV
3693 ioctl(ttyfd,TCSETAW,&ttold);
3694 #else /* !ATTSV */
3695 stty(ttyfd,&ttold);
3696 #endif /* ATTSV */
3697 #endif /* BSD44ORPOSIX */
3698 }
3699 #endif /* HUPCL */
3700 #endif /* CK_NOHUPCL */
3701 }
3702 /* Put back device modes as we found them */
3703
3704 errno = 0;
3705 debug(F111,"ttclos B",ckitoa(x),ttc_state);
3706 if (ttc_state < 2) {
3707 ttc_state = 2;
3708 /* Don't try to mess with tty modes if tthang failed() */
3709 /* since it probably won't work. */
3710 if (x > -1) {
3711 debug(F101,"ttclos calling ttres()","",x);
3712 signal(SIGALRM,xtimerh); /* Re-enable the alarm. */
3713 alarm(8); /* Re-arm the timer */
3714 x = ttres(); /* Reset device modes. */
3715 debug(F101,"ttclos ttres()","",x);
3716 alarm(0);
3717 }
3718 }
3719 /* Close the device */
3720
3721 errno = 0;
3722 debug(F101,"ttclos C","",ttc_state);
3723 if (ttc_state < 3) {
3724 ttc_state = 3;
3725 errno = 0;
3726 debug(F101,"ttclos calling close","",x);
3727 signal(SIGALRM,xtimerh); /* Re-enable alarm. */
3728 alarm(8); /* Re-arm the timer */
3729 x = close(ttyfd); /* Close the device. */
3730 debug(F101,"ttclos close()","",x);
3731 if (x > -1)
3732 ttc_state = 3;
3733 }
3734 debug(F101,"ttclos D","",ttc_state);
3735 ttimoff(); /* Turn off timer. */
3736 if (x < 0) {
3737 printf("?WARNING - close failed: %s\n",ttnmsv);
3738 #ifdef DEBUG
3739 if (deblog) {
3740 printf("errno = %d\n", errno);
3741 debug(F101,"ttclos failed","",errno);
3742 }
3743 #endif /* DEBUG */
3744 }
3745 /* Unlock after closing but before any getty mumbo jumbo */
3746
3747 debug(F100,"ttclos about to call ttunlck","",0);
3748 if (ttunlck()) /* Release uucp-style lock */
3749 fprintf(stderr,"Warning, problem releasing lock\r\n");
3750 }
3751
3752 /* For bidirectional lines, restore getty if it was there before. */
3753
3754 #ifdef ACUCNTRL /* 4.3BSD acucntrl() method. */
3755 if (xlocal) {
3756 debug(F100,"ttclos ACUCNTRL","",0);
3757 acucntrl("enable",ttnmsv); /* Enable getty on the device. */
3758 }
3759 #else
3760 #ifdef ATT7300 /* ATT UNIX PC (3B1, 7300) method. */
3761 if (xlocal) {
3762 debug(F100,"ttclos ATT7300 ongetty","",0);
3763 if (attmodem & DOGETY) /* Was getty(1m) running before us? */
3764 ongetty(ttnmsv); /* Yes, restart getty on tty line */
3765 attmodem &= ~DOGETY; /* No phone in use, getty restored */
3766 }
3767 #endif /* ATT7300 */
3768 #endif /* System-dependent getty-restoring methods */
3769
3770 #ifdef sony_news
3771 km_ext = -1; /* Invalidate device's Kanji-mode */
3772 #endif /* sony_news */
3773
3774 ttyfd = -1; /* Invalidate the file descriptor. */
3775 wasclosed = 1;
3776 debug(F100,"ttclos done","",0);
3777 return(0);
3778 }
3779
3780 /* T T H A N G -- Hangup phone line or network connection. */
3781 /*
3782 Returns:
3783 0 if it does nothing.
3784 1 if it believes that it hung up successfully.
3785 -1 if it believes that the hangup attempt failed.
3786 */
3787
3788 #define HUPTIME 500 /* Milliseconds for hangup */
3789
3790 #ifdef COMMENT
3791 /* The following didn't work but TIOCSDTR does work */
3792 #ifdef UNIXWARE
3793 /* Define HUP_POSIX to force non-POSIX builds to use the POSIX hangup method */
3794 #ifndef POSIX /* Such as Unixware 1.x, 2.x */
3795 #ifndef HUP_POSIX
3796 #define HUP_POSIX
3797 #endif /* HUP_POSIX */
3798 #endif /* POSIX */
3799 #endif /* UNIXWARE */
3800 #endif /* COMMENT */
3801
3802 #ifndef USE_TIOCSDTR
3803 #ifdef __NetBSD__
3804 /* Because the POSIX method (set output speed to 0) doesn't work in NetBSD */
3805 #ifdef TIOCSDTR
3806 #ifdef TIOCCDTR
3807 #define USE_TIOCSDTR
3808 #endif /* TIOCCDTR */
3809 #endif /* TIOCSDTR */
3810 #endif /* __NetBSD__ */
3811 #endif /* USE_TIOCSDTR */
3812
3813 #ifndef HUP_CLOSE_POSIX
3814 #ifdef OU8
3815 #define HUP_CLOSE_POSIX
3816 #else
3817 #ifdef CK_SCOV5
3818 #define HUP_CLOSE_POSIX
3819 #endif /* CK_SCOV5 */
3820 #endif /* OU8 */
3821 #endif /* HUP_CLOSE_POSIX */
3822
3823 #ifdef NO_HUP_CLOSE_POSIX
3824 #ifdef HUP_CLOSE_POSIX
3825 #undef HUP_CLOSE_POSIX
3826 #endif /* HUP_CLOSE_POSIX */
3827 #endif /* NO_HUP_CLOSE_POSIX */
3828
3829 int
tthang()3830 tthang() {
3831 #ifdef NOLOCAL
3832 return(0);
3833 #else
3834 int x = 0; /* Sometimes used as return code. */
3835 #ifndef POSIX
3836 int z; /* worker */
3837 #endif /* POSIX */
3838
3839 #ifdef COHERENT
3840 #define SVORPOSIX
3841 #endif /* COHERENT */
3842
3843 #ifdef SVORPOSIX /* AT&T, POSIX, HPUX declarations. */
3844 int spdsav; /* for saving speed */
3845 #ifdef HUP_POSIX
3846 int spdsavi;
3847 #else
3848 #ifdef BSD44ORPOSIX
3849 int spdsavi;
3850 #endif /* BSD44ORPOSIX */
3851 #endif /* HUP_POSIX */
3852 #ifdef HPUX
3853 /*
3854 Early versions of HP-UX omitted the mflag typedef. If you get complaints
3855 about it, just change it to long (or better still, unsigned long).
3856 */
3857 mflag
3858 dtr_down = 00000000000,
3859 modem_rtn,
3860 modem_sav;
3861 char modem_state[64];
3862 #endif /* HPUX */
3863 int flags; /* fcntl flags */
3864 unsigned short ttc_save;
3865 #endif /* SVORPOSIX */
3866
3867 if (ttyfd < 0) return(0); /* Don't do this if not open */
3868 if (xlocal < 1) return(0); /* Don't do this if not local */
3869
3870 #ifdef NETCMD
3871 if (ttpipe)
3872 return((ttclos(0) < 0) ? -1 : 1);
3873 #endif /* NETCMD */
3874 #ifdef NETPTY
3875 if (ttpty)
3876 return((ttclos(0) < 0) ? -1 : 1);
3877 #endif /* NETPTY */
3878 #ifdef NETCONN
3879 if (netconn) { /* Network connection. */
3880 #ifdef TN_COMPORT
3881 if (istncomport()) {
3882 int rc = tnc_set_dtr_state(0);
3883 if (rc >= 0) {
3884 msleep(HUPTIME);
3885 rc = tnc_set_dtr_state(1);
3886 }
3887 return(rc >= 0 ? 1 : -1);
3888 } else
3889 #endif /* TN_COMPORT */
3890 return((netclos() < 0) ? -1 : 1); /* Just close it. */
3891 }
3892 #endif /* NETCONN */
3893
3894 /* From here down, we handle real tty devices. */
3895 #ifdef HUP_POSIX
3896 /*
3897 e.g. for Unixware 2, where we don't have a full POSIX build, we
3898 still have to use POSIX-style hangup. Thus the duplication of this
3899 and the next case, the only difference being we use a local termios
3900 struct here, since a different model is used elsewhere.
3901
3902 NO LONGER USED as of C-Kermit 8.0 -- it turns out that this method,
3903 even though it compiles and executes without error, doesn't actually
3904 work (i.e. DTR does not drop), whereas the TIOCSDTR method works just fine,
3905 */
3906 {
3907 struct termios ttcur;
3908 int x;
3909 debug(F100,"tthang HUP_POSIX style","",0);
3910 x = tcgetattr(ttyfd, &ttcur); /* Get current attributes */
3911 debug(F111,"tthang tcgetattr",ckitoa(errno),x);
3912 if (x < 0) return(-1);
3913 spdsav = cfgetospeed(&ttcur); /* Get current speed */
3914 debug(F111,"tthang cfgetospeed",ckitoa(errno),spdsav);
3915 spdsavi = cfgetispeed(&ttcur); /* Get current speed */
3916 debug(F111,"tthang cfgetispeed",ckitoa(errno),spdsavi);
3917 x = cfsetospeed(&ttcur,B0); /* Replace by 0 */
3918 debug(F111,"tthang cfsetospeed",ckitoa(errno),x);
3919 if (x < 0) return(-1);
3920 x = cfsetispeed(&ttcur,B0);
3921 debug(F111,"tthang cfsetispeed",ckitoa(errno),x);
3922 if (x < 0) return(-1);
3923 x = tcsetattr(ttyfd,TCSADRAIN,&ttcur);
3924 debug(F111,"tthang tcsetattr B0",ckitoa(errno),x);
3925 if (x < 0) return(-1);
3926 msleep(HUPTIME); /* Sleep 0.5 sec */
3927 x = cfsetospeed(&ttcur,spdsav); /* Restore prev speed */
3928 if (x < 0) return(-1);
3929 debug(F111,"tthang cfsetospeed prev",ckitoa(errno),x);
3930 x = cfsetispeed(&ttcur,spdsavi);
3931 debug(F111,"tthang cfsetispeed prev",ckitoa(errno),x);
3932 if (x < 0) return(-1);
3933 x = tcsetattr(ttyfd,TCSADRAIN,&ttcur);
3934 debug(F111,"tthang tcsetattr restore",ckitoa(errno),x);
3935 if (x < 0) return(-1);
3936 return(1);
3937 }
3938 #else
3939 #ifdef BSD44ORPOSIX
3940 #ifdef QNX
3941 {
3942 int x;
3943 x = tcdropline(ttyfd,500);
3944 debug(F101,"tthang QNX tcdropline","",x);
3945 ttcur.c_cflag |= CLOCAL;
3946 x = tcsetattr(ttyfd,TCSADRAIN,&ttcur);
3947 debug(F101,"tthang QNX tcsetattr restore","",x);
3948 if (x < 0) {
3949 debug(F101,"tthang QNX tcsetattr restore errno","",errno);
3950 return(-1);
3951 }
3952 /* Fix flags - ensure O_NONBLOCK is off */
3953
3954 errno = 0;
3955 debug(F101,"tthang QNX iniflags","",iniflags);
3956 if (fcntl(ttyfd, F_SETFL, iniflags) == -1) {
3957 debug(F101,"tthang QNX F_SETFL errno","",errno);
3958 return(-1);
3959 }
3960 return(x);
3961 }
3962 #else /* QNX */
3963 {
3964 int x;
3965 #ifdef USE_TIOCSDTR
3966 debug(F100,"tthang BSD44ORPOSIX USE_TIOCSDTR","",0);
3967 errno = 0;
3968 x = ioctl(ttyfd, TIOCCDTR, NULL);
3969 debug(F111,"tthang BSD44ORPOSIX ioctl TIOCCDTR",ckitoa(errno),x);
3970 if (x < 0) return(-1);
3971 msleep(HUPTIME); /* Sleep 0.5 sec */
3972 errno = 0;
3973 x = ioctl(ttyfd, TIOCSDTR, NULL);
3974 debug(F111,"tthang BSD44ORPOSIX ioctl TIOCSDTR",ckitoa(errno),x);
3975 if (x < 0) return(-1);
3976 #else /* USE_TIOCSDTR */
3977
3978 #ifdef HUP_CLOSE_POSIX
3979 /*
3980 In OSR5 versions where TIOCSDTR is not defined (up to and including at
3981 least 5.0.6a) the POSIX APIs in the "#else" part below are available but
3982 don't work, and no other APIs are available that do work. In this case
3983 we have to drop DTR by brute force: close and reopen the port. This
3984 code actually works, but all the steps are crucial: setting CLOCAL, the
3985 O_NDELAY manipulations, etc.
3986 */
3987 debug(F100,"tthang HUP_CLOSE_POSIX close/open","",0);
3988 debug(F101,"tthang HUP_CLOSE_POSIX O_NONBLOCK","",O_NONBLOCK);
3989 debug(F101,"tthang HUP_CLOSE_POSIX O_NDELAY","",O_NDELAY);
3990 errno = 0;
3991 x = tcgetattr(ttyfd, &ttcur); /* Get current attributes */
3992 debug(F101,"tthang HUP_CLOSE_POSIX tcgetattr","",x);
3993 if (x < 0) {
3994 debug(F101,"tthang HUP_CLOSE_POSIX tcgetattr errno","",errno);
3995 return(-1);
3996 }
3997 errno = 0;
3998
3999 x = close(ttyfd); /* Close without releasing lock */
4000 if (x < 0) {
4001 debug(F101,"tthang HUP_CLOSE_POSIX close errno","",errno);
4002 return(-1);
4003 }
4004 errno = 0;
4005 x = msleep(500); /* Pause half a second */
4006 if (x < 0) { /* Or if that doesn't work, 1 sec */
4007 debug(F101,"tthang HUP_CLOSE_POSIX msleep errno","",errno);
4008 sleep(1);
4009 }
4010 errno = 0;
4011 ttyfd = priv_opn(ttnmsv, (O_RDWR|O_NDELAY)); /* Reopen the device */
4012 debug(F111,"tthang HUP_CLOSE_POSIX reopen",ttnmsv,ttyfd);
4013 if (ttyfd < 0) {
4014 debug(F101,"tthang HUP_CLOSE_POSIX reopen errno","",errno);
4015 return(-1);
4016 }
4017 debug(F101,"tthang HUP_CLOSE_POSIX re-ttopen ttyfd","",ttyfd);
4018
4019 /* Restore previous attributes */
4020
4021 errno = 0;
4022 tvtflg = 0;
4023 ttcur.c_cflag |= CLOCAL;
4024 x = tcsetattr(ttyfd,TCSADRAIN,&ttcur);
4025 debug(F101,"tthang HUP_CLOSE_POSIX tcsetattr restore","",x);
4026 if (x < 0) {
4027 debug(F101,"tthang HUP_CLOSE_POSIX tcsetattr restore errno",
4028 "",errno);
4029 return(-1);
4030 }
4031 /* Fix flags - ensure O_NDELAY and O_NONBLOCK are off */
4032
4033 errno = 0;
4034 if ((x = fcntl(ttyfd, F_GETFL, 0)) == -1) {
4035 debug(F101,"tthang HUP_CLOSE_POSIX F_GETFL errno","",errno);
4036 return(-1);
4037 }
4038 debug(F101,"tthang HUP_CLOSE_POSIX flags","",x);
4039 errno = 0;
4040 x &= ~(O_NONBLOCK|O_NDELAY);
4041 debug(F101,"tthang HUP_CLOSE_POSIX flags to set","",x);
4042 debug(F101,"tthang HUP_CLOSE_POSIX iniflags","",iniflags);
4043 if (fcntl(ttyfd, F_SETFL, x) == -1) {
4044 debug(F101,"tthang HUP_CLOSE_POSIX F_SETFL errno","",errno);
4045 return(-1);
4046 }
4047 #ifdef DEBUG
4048 if (deblog) {
4049 if ((x = fcntl(ttyfd, F_GETFL, 0)) > -1) {
4050 debug(F101,"tthang HUP_CLOSE_POSIX flags","",x);
4051 debug(F101,"tthang HUP_CLOSE_POSIX flags & O_NONBLOCK",
4052 "",x&O_NONBLOCK);
4053 debug(F101,"tthang HUP_CLOSE_POSIX flags & O_NDELAY",
4054 "",x&O_NDELAY);
4055 }
4056 }
4057 #endif /* DEBUG */
4058
4059 #else /* HUP_CLOSE_POSIX */
4060
4061 /* General BSD44ORPOSIX case (Linux, BSDI, FreeBSD, etc) */
4062
4063 debug(F100,"tthang BSD44ORPOSIX B0","",0);
4064 x = tcgetattr(ttyfd, &ttcur); /* Get current attributes */
4065 debug(F111,"tthang BSD44ORPOSIX tcgetattr",ckitoa(errno),x);
4066 if (x < 0) return(-1);
4067 spdsav = cfgetospeed(&ttcur); /* Get current speed */
4068 debug(F111,"tthang BSD44ORPOSIX cfgetospeed",ckitoa(errno),spdsav);
4069 spdsavi = cfgetispeed(&ttcur); /* Get current speed */
4070 debug(F111,"tthang BSD44ORPOSIX cfgetispeed",ckitoa(errno),spdsavi);
4071 x = cfsetospeed(&ttcur,B0); /* Replace by 0 */
4072 debug(F111,"tthang BSD44ORPOSIX cfsetospeed",ckitoa(errno),x);
4073 if (x < 0) return(-1);
4074 x = cfsetispeed(&ttcur,B0);
4075 debug(F111,"tthang BSD44ORPOSIX cfsetispeed",ckitoa(errno),x);
4076 if (x < 0) return(-1);
4077 /* This gets EINVAL on NetBSD 1.4.1 because of B0... */
4078 x = tcsetattr(ttyfd,TCSADRAIN,&ttcur);
4079 debug(F111,"tthang BSD44ORPOSIX tcsetattr B0",ckitoa(errno),x);
4080 if (x < 0) return(-1);
4081 msleep(HUPTIME); /* Sleep 0.5 sec */
4082 debug(F101,"tthang BSD44ORPOSIX restore output speed","",spdsav);
4083 x = cfsetospeed(&ttcur,spdsav); /* Restore prev speed */
4084 debug(F111,"tthang BSD44ORPOSIX cfsetospeed prev",ckitoa(errno),x);
4085 if (x < 0) return(-1);
4086 debug(F101,"tthang BSD44ORPOSIX restore input speed","",spdsavi);
4087 x = cfsetispeed(&ttcur,spdsavi);
4088 debug(F111,"tthang BSD44ORPOSIX cfsetispeed prev",ckitoa(errno),x);
4089 if (x < 0) return(-1);
4090 ttcur.c_cflag |= CLOCAL; /* Don't expect CD after hangup */
4091 x = tcsetattr(ttyfd,TCSADRAIN,&ttcur);
4092 debug(F111,"tthang BSD44ORPOSIX tcsetattr restore",ckitoa(errno),x);
4093 if (x < 0) return(-1);
4094
4095 #endif /* HUP_CLOSE_POSIX */
4096 #endif /* USE_TIOCSDTR */
4097
4098 return(1);
4099 }
4100
4101 #endif /* QNX */
4102 #else /* BSD44ORPOSIX */
4103
4104 #ifdef aegis /* Apollo Aegis */
4105 sio_$control((short)ttyfd, sio_$dtr, false, st); /* DTR down */
4106 msleep(HUPTIME); /* pause */
4107 sio_$control((short)ttyfd, sio_$dtr, true, st); /* DTR up */
4108 return(1);
4109 #endif /* aegis */
4110
4111 #ifdef ANYBSD /* Any BSD version. */
4112 #ifdef TIOCCDTR /* Except those that don't have this */
4113 debug(F100,"tthang BSD style","",0);
4114 if (ioctl(ttyfd,TIOCCDTR,0) < 0) { /* Clear DTR. */
4115 debug(F101,"tthang TIOCCDTR fails","",errno);
4116 return(-1);
4117 }
4118 msleep(HUPTIME); /* For about 1/2 sec */
4119 errno = 0;
4120 x = ioctl(ttyfd,TIOCSDTR,0); /* Restore DTR */
4121 if (x < 0) {
4122 /*
4123 For some reason, this tends to fail with "no such device or address"
4124 but the operation still works, probably because of the close/open
4125 later on. So let's not scare the user unnecessarily here.
4126 */
4127 debug(F101,"tthang TIOCSDTR errno","",errno); /* Log the error */
4128 x = 1; /* Pretend we succeeded */
4129 } else if (x == 0) x = 1; /* Success */
4130 #ifdef COMMENT
4131 #ifdef FT21
4132 ioctl(ttyfd, TIOCSAVEMODES, 0);
4133 ioctl(ttyfd, TIOCHPCL, 0);
4134 close(ttyfd); /* Yes, must do this twice */
4135 if ((ttyfd = open(ttnmsv,2)) < 0) /* on Fortune computers... */
4136 return(-1); /* (but why?) */
4137 else x = 1;
4138 #endif /* FT21 */
4139 #endif /* COMMENT */
4140 #endif /* TIOCCDTR */
4141 close(do_open(ttnmsv)); /* Clear i/o error condition */
4142 errno = 0;
4143 #ifdef COMMENT
4144 /* This is definitely dangerous. Why was it here? */
4145 z = ttvt(ttspeed,ttflow); /* Restore modes. */
4146 debug(F101,"tthang ttvt returns","",z);
4147 return(z < 0 ? -1 : 1);
4148 #else
4149 return(x);
4150 #endif /* COMMENT */
4151 #endif /* ANYBSD */
4152
4153 #ifdef ATTSV
4154 /* AT&T UNIX section, includes HP-UX and generic AT&T System III/V... */
4155
4156 #ifdef HPUX
4157 /* Hewlett Packard allows explicit manipulation of modem signals. */
4158
4159 #ifdef COMMENT
4160 /* Old way... */
4161 debug(F100,"tthang HP-UX style","",0);
4162 if (ioctl(ttyfd,MCSETAF,&dtr_down) < 0) /* lower DTR */
4163 return(-1); /* oops, can't. */
4164 msleep(HUPTIME); /* Pause half a second. */
4165 x = 1; /* Set return code */
4166 if (ioctl(ttyfd,MCGETA,&modem_rtn) > -1) { /* Get line status. */
4167 if ((modem_rtn & MDCD) != 0) /* Check if CD is low. */
4168 x = -1; /* CD didn't drop, fail. */
4169 } else x = -1;
4170
4171 /* Even if above calls fail, RTS & DTR should be turned back on. */
4172 modem_rtn = MRTS | MDTR;
4173 if (ioctl(ttyfd,MCSETAF,&modem_rtn) < 0) x = -1;
4174 return(x);
4175 #else
4176 /* New way, from Hellmuth Michaelis */
4177 debug(F100,"tthang HP-UX style, HPUXDEBUG","",0);
4178 if (ioctl(ttyfd,MCGETA,&modem_rtn) == -1) { /* Get current status. */
4179 debug(F100,"tthang HP-UX: can't get modem lines, NO HANGUP!","",0);
4180 return(-1);
4181 }
4182 sprintf(modem_state,"%#lx",modem_rtn);
4183 debug(F110,"tthang HP-UX: modem lines = ",modem_state,0);
4184 modem_sav = modem_rtn; /* Save current modem signals */
4185 modem_rtn &= ~MDTR; /* Turn DTR bit off */
4186 sprintf(modem_state,"%#lx",modem_rtn);
4187 debug(F110,"tthang HP-UX: DTR down = ",modem_state,0);
4188 if (ioctl(ttyfd,MCSETAF,&modem_rtn) < 0) { /* lower DTR */
4189 debug(F100,"tthang HP-UX: can't lower DTR!","",0);
4190 return(-1); /* oops, can't. */
4191 }
4192 msleep(HUPTIME); /* Pause half a second. */
4193 x = 1; /* Set return code */
4194 if (ioctl(ttyfd,MCGETA,&modem_rtn) > -1) { /* Get line status. */
4195 sprintf(modem_state,"%#lx",modem_rtn);
4196 debug(F110,"tthang HP-UX: modem lines got = ",modem_state,0);
4197 if ((modem_rtn & MDCD) != 0) { /* Check if CD is low. */
4198 debug(F100,"tthang HP-UX: DCD not down","",0);
4199 x = -1; /* CD didn't drop, fail. */
4200 } else {
4201 debug(F100,"tthang HP-UX: DCD down","",0);
4202 }
4203 } else {
4204 x = -1;
4205 debug(F100,"tthang HP-UX: can't get DCD status !","",0);
4206 }
4207
4208 /* Even if above calls fail, DTR should be turned back on. */
4209
4210 modem_sav |= MDTR;
4211 if (ioctl(ttyfd,MCSETAF,&modem_sav) < 0) {
4212 x = -1;
4213 debug(F100,"tthang HP-UX: can't set saved state","",0);
4214 } else {
4215 sprintf(modem_state,"%#lx",modem_sav);
4216 debug(F110,"tthang HP-UX: final modem lines = ",modem_state,0);
4217 }
4218 return(x);
4219 #endif /* COMMENT */
4220
4221 #else /* AT&T but not HP-UX */
4222
4223 /* SVID for AT&T System V R3 defines ioctl's for handling modem signals. */
4224 /* It is not known how many, if any, systems actually implement them, */
4225 /* so we include them here in ifdef's. */
4226
4227 /*
4228 Unixware has the TIOCMxxx symbols defined, but calling ioctl() with them
4229 gives error 22 (invalid argument).
4230 */
4231 #ifndef _IBMR2
4232 /*
4233 No modem-signal twiddling for IBM RT PC or RS/6000.
4234 In AIX 3.1 and earlier, the ioctl() call is broken.
4235 This code could be activated for AIX 3.1 with PTF 2006 or later
4236 (e.g. AIX 3.2), but close/open does the job too, so why bother.
4237 */
4238 #ifdef TIOCMBIS /* Bit Set */
4239 #ifdef TIOCMBIC /* Bit Clear */
4240 #ifdef TIOCM_DTR /* DTR */
4241
4242 /* Clear DTR, sleep 300 msec, turn it back on. */
4243 /* If any of the ioctl's return failure, go on to the next section. */
4244
4245 z = TIOCM_DTR; /* Code for DTR. */
4246 #ifdef COMMENT
4247 /*
4248 This was the cause of the troubles with the Solaris Port Monitor.
4249 The problem is: RTS never comes back on. Moral: Don't do it!
4250 (But why doesn't it come back on? See the TIOCMBIS call...)
4251 */
4252 #ifdef TIOCM_RTS /* Lower RTS too if symbol is known. */
4253 z |= TIOCM_RTS;
4254 #endif /* TIOCM_RTS */
4255 #endif /* COMMENT */
4256
4257 debug(F101,"tthang TIOCM signal mask","",z);
4258 if (ioctl(ttyfd,TIOCMBIC,&z) > -1) { /* Try to lower DTR. */
4259 debug(F100,"tthang TIOCMBIC ok","",0);
4260 msleep(HUPTIME); /* Pause half a second. */
4261 if (ioctl(ttyfd,TIOCMBIS,&z) > -1) { /* Try to turn it back on. */
4262 debug(F100,"tthang TIOCMBIS ok","",0);
4263 #ifndef CLSOPN
4264 return(1); /* Success, done. */
4265 #endif /* CLSOPN */
4266 } else { /* Couldn't raise, continue. */
4267 debug(F101,"tthang TIOCMBIS errno","",errno);
4268 }
4269 } else { /* Couldn't lower, continue. */
4270 debug(F101,"tthang TIOCMBIC errno","",errno);
4271 }
4272 #endif /* TIOCM_DTR */
4273 #endif /* TIOCMBIC */
4274 #endif /* TIOCMBIS */
4275 #endif /* _IBMR2 */
4276
4277 /*
4278 General AT&T UNIX case, not HPUX. The following code is highly suspect. No
4279 two AT&T-based systems seem to do this the same way. The object is simply
4280 to turn off DTR and then turn it back on. SVID says the universal method
4281 for turning off DTR is to set the speed to zero, and this does seem to do
4282 the trick in all cases. But neither SVID nor any known man pages say how to
4283 turn DTR back on again. Some variants, like most Xenix implementations,
4284 raise DTR again when the speed is restored to a nonzero value. Others
4285 require the device to be closed and opened again, but this is risky because
4286 getty could seize the device during the instant it is closed.
4287 */
4288
4289 /* Return code for ioctl failures... */
4290 #ifdef ATT6300
4291 x = 1; /* ATT6300 doesn't want to fail... */
4292 #else
4293 x = -1;
4294 #endif /* ATT6300 */
4295
4296 debug(F100,"tthang get settings","",0);
4297 if (ioctl(ttyfd,TCGETA,&ttcur) < 0) /* Get current settings. */
4298 return(x); /* Fail if this doesn't work. */
4299 if ((flags = fcntl(ttyfd,F_GETFL,0)) < 0) /* Get device flags. */
4300 return(x);
4301 ttc_save = ttcur.c_cflag; /* Remember current speed. */
4302 spdsav = ttc_save & CBAUD;
4303 debug(F101,"tthang speed","",spdsav);
4304
4305 #ifdef O_NDELAY
4306 debug(F100,"tthang turning O_NDELAY on","",0);
4307 fcntl(ttyfd, F_SETFL, flags | O_NDELAY); /* Activate O_NDELAY */
4308 #endif /* O_NDELAY */
4309
4310 #ifdef ATT7300 /* This is the way it is SUPPOSED to work */
4311 ttcur.c_cflag &= ~CBAUD; /* Change the speed to zero. */
4312 #else
4313 #ifdef RTAIX
4314 ttcur.c_cflag &= ~CBAUD; /* Change the speed to zero. */
4315 #else /* This way really works but may be dangerous */
4316 #ifdef u3b2
4317 ttcur.c_cflag = ~(CBAUD|CLOCAL); /* Special for AT&T 3B2s */
4318 /* (CLOCAL must be OFF) */
4319 #else
4320 #ifdef SCO3R2 /* SCO UNIX 3.2 */
4321 /*
4322 This is complete nonsense, but an SCO user claimed this change made
4323 hanging up work. Comments from other SCO UNIX 3.2 users would be
4324 appreciated.
4325 */
4326 ttcur.c_cflag = CBAUD|B0;
4327 #else
4328 #ifdef AIXRS /* AIX on RS/6000 */
4329 /*
4330 Can't set speed to zero on AIX 3.1 on RS/6000 64-port adapter,
4331 even though you can do it on the built-in port and the 8- and 16-port
4332 adapters. (Untested on 128-port adapter.)
4333 */
4334 ttcur.c_cflag = CLOCAL|HUPCL|spdsav; /* Speed 0 causes EINVAL */
4335 #else /* None of the above */
4336 /*
4337 Set everything, including the speed, to zero, except for the CLOCAL
4338 and HUPCL bits.
4339 */
4340 ttcur.c_cflag = CLOCAL|HUPCL;
4341 #endif /* AIXRS */
4342 #endif /* SCO3R2 */
4343 #endif /* u3b2 */
4344 #endif /* RTAIX */
4345 #endif /* ATT7300 */
4346
4347 #ifdef COMMENT
4348 /* and if none of those work, try one of these... */
4349 ttcur.c_cflag = 0;
4350 ttcur.c_cflag = CLOCAL;
4351 ttcur.c_cflag &= ~(CBAUD|HUPCL);
4352 ttcur.c_cflag &= ~(CBAUD|CREAD);
4353 ttcur.c_cflag &= ~(CBAUD|CREAD|HUPCL);
4354 /* or other combinations */
4355 #endif /* COMMENT */
4356
4357 #ifdef TCXONC
4358 debug(F100,"tthang TCXONC","",0);
4359 if (ioctl(ttyfd, TCXONC, 1) < 0) {
4360 debug(F101,"tthang TCXONC failed","",errno);
4361 }
4362 #endif /* TCXONC */
4363
4364 #ifdef TIOCSTART
4365 debug(F100,"tthang TIOCSTART","",0);
4366 if (ioctl(ttyfd, TIOCSTART, 0) < 0) {
4367 debug(F101,"tthang TIOCSTART failed","",errno);
4368 }
4369 #endif /* TIOCSTART */
4370
4371 if (ioctl(ttyfd,TCSETAF,&ttcur) < 0) { /* Fail if we can't. */
4372 debug(F101,"tthang TCSETAF failed","",errno);
4373 fcntl(ttyfd, F_SETFL, flags); /* Restore flags */
4374 return(-1); /* before returning. */
4375 }
4376 msleep(300); /* Give modem time to notice. */
4377
4378 #ifndef NOCOTFMC
4379
4380 /* Now, even though it doesn't say this in SVID or any man page, we have */
4381 /* to close and reopen the device. This is not necessary for all systems, */
4382 /* but it's impossible to predict which ones need it and which ones don't. */
4383
4384 #ifdef ATT7300
4385 /*
4386 Special handling for ATT 7300 UNIX PC and 3B1, which have "phone"
4387 related ioctl's for their internal modems. attmodem has getty status and
4388 modem-in-use bit. Reportedly the ATT7300/3B1 PIOCDISC call is necessary,
4389 but also ruins the file descriptor, and no other phone(7) ioctl call can fix
4390 it. Whatever it does, it seems to escape detection with PIOCGETA and TCGETA.
4391 The only way to undo the damage is to close the fd and then reopen it.
4392 */
4393 if (attmodem & ISMODEM) {
4394 debug(F100,"tthang attmodem close/open","",0);
4395 ioctl(ttyfd,PIOCUNHOLD,&dialer); /* Return call to handset. */
4396 ioctl(ttyfd,PIOCDISC,&dialer); /* Disconnect phone. */
4397 close(ttyfd); /* Close and reopen the fd. */
4398 ttyfd = priv_opn(ttnmsv, O_RDWR | O_NDELAY);
4399 attmodem &= ~ISMODEM; /* Phone no longer in use. */
4400 }
4401 #else /* !ATT7300 */
4402 /* It seems we have to close and open the device for other AT&T systems */
4403 /* too, and this is the place to do it. The following code does the */
4404 /* famous close(open(...)) magic by default. If that doesn't work for you, */
4405 /* then try uncommenting the following statement or putting -DCLSOPN in */
4406 /* the makefile CFLAGS. */
4407
4408 /* #define CLSOPN */
4409
4410 #ifndef SCO32 /* Not needed by, and harmful to, SCO UNIX 3.2 / Xenix 2.3 */
4411
4412 #ifdef O_NDELAY
4413 #define OPENFLGS O_RDWR | O_NDELAY
4414 #else
4415 #define OPENFLGS O_RDWR
4416 #endif
4417
4418 #ifndef CLSOPN
4419 /* This method is used by default, i.e. unless CLSOPN is defined. */
4420 /* It is thought to be safer because there is no window where getty */
4421 /* can seize control of the device. The drawback is that it might not work. */
4422
4423 debug(F101,"tthang close(open()), OPENFLGS","",OPENFLGS);
4424 close(priv_opn(ttnmsv, OPENFLGS));
4425
4426 #else
4427 /* This method is used if you #define CLSOPN. It is more likely to work */
4428 /* than the previous method, but it's also more dangerous. */
4429
4430 debug(F101,"tthang close/open, OPENFLGS","",OPENFLGS);
4431 close(ttyfd);
4432 msleep(10);
4433 ttyfd = priv_opn(ttnmsv, OPENFLGS); /* Open it again */
4434 #endif /* CLSOPN */
4435 #undef OPENFLGS
4436
4437 #endif /* SCO32 */
4438 #endif /* ATT7300 */
4439
4440 #endif /* NOCOTFMC */
4441
4442 /* Now put all flags & modes back the way we found them. */
4443 /* (Does the order of ioctl & fcntl matter ? ) */
4444
4445 debug(F100,"tthang restore settings","",0);
4446 ttcur.c_cflag = ttc_save; /* Get old speed back. */
4447 if (ioctl(ttyfd,TCSETAF,&ttcur) < 0) /* ioctl parameters. */
4448 return(-1);
4449 #ifdef O_NDELAY
4450 /*
4451 This is required for IBM RT and RS/6000, probably helps elsewhere too (?).
4452 After closing a modem line, the modem will probably not be asserting
4453 carrier any more, so we should not require carrier any more. If this
4454 causes trouble on non-IBM UNIXes, change the #ifdef to use _IBMR2 rather
4455 than O_NDELAY.
4456 */
4457 flags &= ~O_NDELAY; /* Don't require carrier on reopen */
4458 #endif /* O_NDELAY */
4459 if (fcntl(ttyfd,F_SETFL,flags) < 0) /* fcntl parameters */
4460 return(-1);
4461
4462 return(1);
4463 #endif /* not HPUX */
4464 #endif /* ATTSV */
4465 #endif /* BSD44ORPOSIX */
4466 #endif /* HUP_POSIX */
4467 #endif /* NOLOCAL */
4468 }
4469
4470 /*
4471 Major change in 5A(174). We used to use LPASS8, if it was defined, to
4472 allow 8-bit data and Xon/Xoff flow control at the same time. But this
4473 LPASS8 business seems to have been causing trouble for everybody but me!
4474 For example, Annex terminal servers, commonly used with Encore computers,
4475 do not support LPASS8 even though the Encore itself does. Ditto for many
4476 other terminal servers, TELNET connections, rlogin connections, etc etc.
4477 Now, reportedly, even vanilla 4.3 BSD systems can't do this right on their
4478 serial lines, even though LPASS8 is a feature of 4.3BSD. So let's turn it
4479 off for everybody. That means we goes back to using raw mode, with no
4480 flow control. Phooey.
4481
4482 NOTE: This must be done before the first reference to LPASS8 in this file,
4483 and after the last #include statment.
4484 */
4485 #ifdef LPASS8
4486 #undef LPASS8
4487 #endif /* LPASS8 */
4488
4489 /* T T R E S -- Restore terminal to "normal" mode. */
4490
4491 /* ske@pkmab.se: There are two choices for what this function should do.
4492 * (1) Restore the tty to current "normal" mode, with carrier treatment
4493 * according to ttcarr, to be used after every kermit command. (2) Restore
4494 * the tty to the state it was in before kermit opened it. These choices
4495 * conflict, since ttold can't hold both choices of tty parameters. ttres()
4496 * is currently being called as in choice (1), but ttold basically holds
4497 * the initial parameters, as in (2), and the description at the beginning
4498 * of this file says (2).
4499 *
4500 * I don't think restoring tty parameters after all kermit commands makes
4501 * much of a difference. Restoring them upon exit from kermit may be of
4502 * some use in some cases (when the line is not restored automatically on
4503 * close, by the operating system).
4504 *
4505 * I can't choose which one it should be, so I haven't changed it. It
4506 * probably works as it is, too. It would probably even work even with
4507 * ttres() entirely deleted...
4508 *
4509 * (from fdc: Actually, this function operates in remote mode too, so
4510 * it restores the console (command) terminal to whatever mode it was
4511 * in before packet operations began, so that commands work right again.)
4512 */
4513 int
ttres()4514 ttres() { /* Restore the tty to normal. */
4515 int x;
4516
4517 if (ttyfd < 0) return(-1); /* Not open. */
4518
4519 if (ttfdflg) return(0); /* Don't mess with terminal modes if */
4520 /* we got ttyfd from another process */
4521 #ifdef NETCONN
4522 if (netconn) { /* Network connection */
4523 tvtflg = 0;
4524 #ifdef TCPSOCKET
4525 #ifdef TCP_NODELAY
4526 {
4527 extern int tcp_nodelay; /* Just put this back if necessary */
4528 if (ttnet == NET_TCPB) {
4529 if (nodelay_sav > -1) {
4530 no_delay(ttyfd,nodelay_sav);
4531 nodelay_sav = -1;
4532 }
4533 }
4534 }
4535 #endif /* TCP_NODELAY */
4536 #ifdef TN_COMPORT
4537 if (istncomport()) {
4538 int rc = -1;
4539 if ((rc = tnsetflow(ttflow)) < 0)
4540 return(rc);
4541 if (ttspeed <= 0)
4542 ttspeed = tnc_get_baud();
4543 else if ((rc = tnc_set_baud(ttspeed)) < 0)
4544 return(rc);
4545 tnc_set_datasize(8);
4546 tnc_set_stopsize(stopbits);
4547
4548 #ifdef HWPARITY
4549 if (hwparity) {
4550 switch (hwparity) {
4551 case 'e': /* Even */
4552 debug(F100,"ttres 8 bits + even parity","",0);
4553 tnc_set_parity(3);
4554 break;
4555 case 'o': /* Odd */
4556 debug(F100,"ttres 8 bits + odd parity","",0);
4557 tnc_set_parity(2);
4558 break;
4559 case 'm': /* Mark */
4560 debug(F100,"ttres 8 bits + invalid parity: mark","",0);
4561 tnc_set_parity(4);
4562 break;
4563 case 's': /* Space */
4564 debug(F100,"ttres 8 bits + invalid parity: space","",0);
4565 tnc_set_parity(5);
4566 break;
4567 }
4568 } else
4569 #endif /* HWPARITY */
4570 {
4571 tnc_set_parity(1); /* None */
4572 }
4573 tvtflg = 0;
4574 return(0);
4575 }
4576 #endif /* TN_COMPORT */
4577 #endif /* TCPSOCKET */
4578 return(0);
4579 }
4580 #endif /* NETCONN */
4581 #ifdef NETCMD
4582 if (ttpipe) return(0);
4583 #endif /* NETCMD */
4584 #ifdef NETPTY
4585 if (ttpty) return(0);
4586 #endif /* NETPTY */
4587
4588 /* Real terminal device, so restore its original modes */
4589
4590 #ifdef BSD44ORPOSIX /* For POSIX like this */
4591 debug(F100,"ttres BSD44ORPOSIX","",0);
4592 x = tcsetattr(ttyfd,TCSADRAIN,&ttold);
4593 #else /* For all others... */
4594 #ifdef ATTSV /* For AT&T versions... */
4595 debug(F100,"ttres ATTSV","",0);
4596 x = ioctl(ttyfd,TCSETAW,&ttold); /* Restore tty modes this way. */
4597 #else
4598 /* Here we restore the modes for BSD */
4599
4600 #ifdef LPASS8 /* Undo "pass8" if it were done */
4601 if (lmodef) {
4602 if (ioctl(ttyfd,TIOCLSET,&lmode) < 0)
4603 debug(F100,"ttres TIOCLSET failed","",0);
4604 else
4605 debug(F100,"ttres TIOCLSET ok","",0);
4606 }
4607 #endif /* LPASS8 */
4608
4609 #ifdef CK_DTRCTS /* Undo hardware flow if it were done */
4610 if (lmodef) {
4611 if (ioctl(ttyfd,TIOCLSET,&lmode) < 0)
4612 debug(F100,"ttres TIOCLSET failed","",0);
4613 else
4614 debug(F100,"ttres TIOCLSET ok","",0);
4615 }
4616 #endif /* CK_DTRCTS */
4617
4618 #ifdef TIOCGETC /* Put back special characters */
4619 if (tcharf && (xlocal == 0)) {
4620 if (ioctl(ttyfd,TIOCSETC,&tchold) < 0)
4621 debug(F100,"ttres TIOCSETC failed","",0);
4622 else
4623 debug(F100,"ttres TIOCSETC ok","",0);
4624 }
4625 #endif /* TIOCGETC */
4626
4627 #ifdef TIOCGLTC /* Put back local special characters */
4628 if (ltcharf && (xlocal == 0)) {
4629 if (ioctl(ttyfd,TIOCSLTC,<chold) < 0)
4630 debug(F100,"ttres TIOCSLTC failed","",0);
4631 else
4632 debug(F100,"ttres TIOCSLTC ok","",0);
4633 }
4634 #endif /* TIOCGLTC */
4635
4636 #ifdef BELLV10
4637 debug(F100,"ttres BELLV10","",0);
4638 x = ioctl(ttyfd,TIOCSETP,&ttold); /* Restore both structs */
4639 x = ioctl(ttyfd,TIOCSDEV,&tdold);
4640 #else
4641 debug(F100,"ttres stty","",0);
4642 x = stty(ttyfd,&ttold); /* Restore tty modes the old way. */
4643 #endif /* BELLV10 */
4644
4645 if (!xlocal)
4646 msleep(100); /* This replaces sleep(1)... */
4647 /* Put back sleep(1) if tty is */
4648 /* messed up after close. */
4649 #endif /* ATTSV */
4650 #endif /* BSD44ORPOSIX */
4651
4652 debug(F101,"ttres result","",x);
4653 #ifndef QNX
4654 if (x < 0) debug(F101,"ttres errno","",errno);
4655 #endif /* QNX */
4656
4657 #ifdef AIXRS
4658 #ifndef AIX41
4659 x = ioctl(ttyfd, ttld & 1 ? TXADDCD : TXDELCD, "rts");
4660 debug(F101,"ttres AIX line discipline rts restore","",x);
4661 #endif /* AIX41 */
4662 #endif /* AIXRS */
4663
4664 #ifdef BSD41
4665 if (ttld > -1) { /* Put back line discipline */
4666 x = ioctl(ttyfd, TIOCSETD, &ttld);
4667 debug(F101,"ttres BSD41 line discipline restore","",x);
4668 if (x < 0) debug(F101,"...ioctl errno","",errno);
4669 ttld = -1;
4670 }
4671 #endif /* BSD41 */
4672
4673 #ifdef sony_news
4674 x = xlocal ? km_ext : km_con; /* Restore Kanji mode. */
4675 if (x != -1) { /* Make sure we know original modes. */
4676 if (ioctl(ttyfd,TIOCKSET, &x) < 0) {
4677 perror("ttres can't set Kanji mode");
4678 debug(F101,"ttres error setting Kanji mode","",x);
4679 return(-1);
4680 }
4681 }
4682 debug(F100,"ttres set Kanji mode ok","",0);
4683 #endif /* sony_news */
4684
4685 tvtflg = 0; /* Invalidate terminal mode settings */
4686 debug(F101,"ttres return code","",x);
4687 return(x);
4688 }
4689
4690 #ifndef NOUUCP
4691
4692 /* T T C H K P I D -- Check lockfile pid */
4693 /*
4694 Read pid from lockfile named f, check that it's still valid.
4695 If so, return 1.
4696 On failure to read pid, return 1.
4697 Otherwise, try to delete lockfile f and return 0 if successful, else 1.
4698 */
4699 static int
ttchkpid(f)4700 ttchkpid(f) char *f; {
4701 int pid, mypid, x;
4702 pid = ttrpid(f); /* Read pid from file. */
4703 if (pid > -1) { /* If we were able to read the pid.. */
4704 debug(F101,"ttchkpid lock pid","",pid);
4705 errno = 0; /* See if process still exists. */
4706 mypid = (int)getpid(); /* Get my own pid. */
4707 debug(F101,"ttchkpid my pid","",mypid);
4708 if (pid == mypid) { /* It's me! */
4709 x = -1; /* So I can delete it */
4710 errno = ESRCH; /* pretend it's invalid */
4711 } else { /* It's not me */
4712 x = kill((PID_T)pid, 0); /* See if it's a live process */
4713 debug(F101,"ttchkpid kill errno","",errno);
4714 }
4715 debug(F101,"ttchkpid pid test","",x);
4716 if (x < 0 && errno == ESRCH) { /* pid is invalid */
4717 debug(F111,"removing stale lock",f,pid);
4718 if (!backgrd)
4719 printf("Removing stale lock %s (pid %d terminated)\n", f, pid);
4720 priv_on();
4721 x = unlink(f); /* Remove the lockfile. */
4722 priv_off();
4723 debug(F111,"ttchkpid unlink",f,x);
4724 if (x > -1)
4725 return(0); /* Device is not locked after all */
4726 else if (!backgrd)
4727 perror(f);
4728 }
4729 return(1);
4730 }
4731 return(1); /* Failure to read pid */
4732 }
4733
4734 #ifdef HPUX
4735
4736 /* Aliases (different drivers) for HP-UX dialout devices: */
4737
4738 static char *devprefix[] = { "tty", "ttyd", "cul", "cua", "cuad", "culd", "" };
4739 static int ttydexists = 0;
4740
4741 #endif /* HPUX */
4742
4743 /* T T R P I D -- Read pid from lockfile "name" */
4744
4745 static int
ttrpid(name)4746 ttrpid(name) char *name; {
4747 long len;
4748 int x, fd, pid;
4749 short spid;
4750 char buf[32];
4751
4752 debug(F110,"ttrpid",name,0);
4753 if (!name) return(-1);
4754 if (!*name) return(-1);
4755 priv_on();
4756 len = zchki(name); /* Get file length */
4757 priv_off();
4758 debug(F101,"ttrpid zchki","",len);
4759 if (len < 0)
4760 return(-1);
4761 if (len > 31)
4762 return(-1);
4763 priv_on();
4764 fd = open(name,O_RDONLY); /* Try to open lockfile. */
4765 priv_off();
4766 debug(F101,"ttrpid fd","",fd);
4767 if (fd <= 0)
4768 return(-1);
4769 /*
4770 Here we try to be flexible and allow for all different binary and string
4771 formats at runtime, rather than a specific format for each configuration
4772 hardwired at compile time.
4773 */
4774 pid = -1;
4775 #ifndef COHERENT
4776 /*
4777 COHERENT uses a string PID but without leading spaces or 0's, so there is
4778 no way to tell from the file's length whether it contains a string or binary
4779 pid. So for COHERENT only, we only allow string pids. For all others, we
4780 decide based on the size of the lockfile.
4781 */
4782 if (len > 4) { /* If file > 4 bytes it's a string */
4783 #endif /* COHERENT */
4784 x = read(fd,buf,(int)len);
4785 debug(F111,"ttrpid string read",buf,x);
4786 if (x < 0) {
4787 pid = -1;
4788 } else {
4789 buf[31] = '\0';
4790 x = sscanf(buf,"%d",&pid); /* Get the integer pid from it. */
4791 }
4792 #ifndef COHERENT
4793 } else if (len == 4) { /* 4 bytes so binary */
4794 x = read(fd, (char *)&pid, 4); /* Read the bytes into an int */
4795 debug(F101,"ttrpid integer read","",x);
4796 if (x < 4)
4797 pid = -1;
4798 } else if (len == 2) { /* 2 bytes binary */
4799 x = read(fd, (char *)&spid, 2); /* Read the bytes into a short */
4800 debug(F101,"ttrpid short read","",x);
4801 if (x < 2)
4802 pid = -1;
4803 else
4804 pid = spid;
4805 } else
4806 pid = -1;
4807 #endif /* COHERENT */
4808 close(fd); /* Close the lockfile */
4809 debug(F101,"ttrpid pid","",pid);
4810 return(pid);
4811 }
4812 #endif /* NOUUCP */
4813
4814 /* T T L O C K */
4815
4816 /*
4817 This function attempts to coordinate use of the communication device with
4818 other copies of Kermit and any other program that follows the UUCP
4819 device-locking conventions, which, unfortunately, vary among different UNIX
4820 implementations. The idea is to look for a file of a certain name, the
4821 "lockfile", in a certain directory. If such a file is found, then the line
4822 is presumed to be in use, and Kermit should not use it. If no such file is
4823 found, Kermit attempts to create one so that other programs will not use the
4824 same line at the same time. Because the lockfile and/or the directory it's
4825 in might lack write permission for the person running Kermit, Kermit could
4826 find itself running setuid to uucp or other user that does have the
4827 necessary permissions. At startup, Kermit has changed its effective uid to
4828 the user's real uid, and so ttlock() must switch back to the original
4829 effective uid in order to create the lockfile, and then back again to the
4830 real uid to prevent unauthorized access to other directories or files owned
4831 by the user the program is setuid to.
4832
4833 Totally rewritten for C-Kermit 5A to eliminate windows of vulnerability,
4834 based on suggestions from Warren Tucker. Call with pointer to name of
4835 tty device. Returns:
4836
4837 0 on success
4838 -1 on failure
4839
4840 Note: Once privileges are turned on using priv_on(), it is essential that
4841 they are turned off again before this function returns.
4842 */
4843 #ifdef SVR4 /* Lockfile uses device numbers. */
4844 /*
4845 Although I can't find this in writing anywhere (e.g. in SVID for SVR4),
4846 it is the behavior of the "reference version" of SVR4, i.e. the Intel
4847 port from UNIX Systems Laboratories, then called Univel UnixWare,
4848 then called Novell UnixWare, then called SCO Unixware, then called Caldera
4849 Open UNIX... It also makes much more sense than device-name-based lockfiles
4850 since there can be multiple names for the same device, symlinks, etc.
4851 */
4852 #ifndef NOLFDEVNO
4853 #ifndef LFDEVNO /* Define this for SVR4 */
4854 #ifndef AIXRS /* But not for RS/6000 AIX 3.2, etc. */
4855 #ifndef BSD44 /* If anybody else needs it... */
4856 #ifndef __386BSD__
4857 #ifndef __FreeBSD__
4858 #ifndef HPUX10
4859 #ifndef IRIX51 /* SGI IRIX 5.1 or later */
4860 #ifndef CK_SCOV5 /* SCO Open Server 5.0 */
4861 #define LFDEVNO
4862 #endif /* CK_SCOV5 */
4863 #endif /* IRIX51 */
4864 #endif /* HPUX10 */
4865 #endif /* __FreeBSD__ */
4866 #endif /* __386BSD__ */
4867 #endif /* BSD44 */
4868 #endif /* AIXRS */
4869 #endif /* LFDEVNO */ /* ... define it here or on CC */
4870 #endif /* NOLFDEVNO */
4871 #endif /* SVR4 */ /* command line. */
4872
4873 #ifdef COHERENT
4874 #define LFDEVNO
4875 #endif /* COHERENT */
4876
4877 /*
4878 For platforms where the lockfile name is made from device/major/minor
4879 device number, as in SVR4. Which, if we must have lockfiles at all, is
4880 by far the best format, since it eliminates all the confusion that stems
4881 from multiple names (or drivers) for the same port, not to mention
4882 symlinks. It might even be a good idea to start using this form even
4883 on platforms where it's not supported, alongside the normal forms for those
4884 platforms, in order to get people used to it...
4885 */
4886 #ifdef LFDEVNO
4887 #ifndef major /* If we didn't find it */
4888 #ifdef SVR4 /* then for Sys V R4 */
4889 #include <sys/mkdev.h> /* look here */
4890 #else /* or for SunOS versions */
4891 #ifdef SUNOS4 /* ... */
4892 #include <sys/sysmacros.h> /* look here */
4893 #else /* Otherwise take a chance: */
4894 #define major(dev) ( (int) ( ((unsigned)(dev) >> 8) & 0xff))
4895 #define minor(dev) ( (int) ( (dev) & 0xff))
4896 #endif /* SUNOS4 */
4897 #endif /* SVR4 */
4898 #endif /* major */
4899 #endif /* LFDEVNO */
4900
4901 /* No advisory locks if F_TLOCK and F_ULOCK are not defined at this point */
4902
4903 #ifdef LOCKF
4904 #ifndef F_TLOCK
4905 #undef LOCKF
4906 #ifndef NOLOCKF
4907 #define NOLOCKF
4908 #endif /* NOLOCKF */
4909 #endif /* F_TLOCK */
4910 #endif /* LOCKF */
4911
4912 #ifdef LOCKF
4913 #ifndef F_ULOCK
4914 #undef LOCKF
4915 #ifndef NOLOCKF
4916 #define NOLOCKF
4917 #endif /* NOLOCKF */
4918 #endif /* F_ULOCK */
4919 #endif /* LOCKF */
4920
4921 static char linkto[DEVNAMLEN+1];
4922 static char * linkdev = NULL;
4923
4924 #ifndef NOUUCP
4925 #ifdef USETTYLOCK
4926 #ifdef LOCK_DIR
4927 char * uucplockdir = LOCK_DIR;
4928 #else
4929 char * uucplockdir = "";
4930 #endif /* LOCK_DIR */
4931 #else
4932 #ifdef LOCK_DIR
4933 char * uucplockdir = LOCK_DIR;
4934 #else
4935 char * uucplockdir = "";
4936 #endif /* LOCK_DIR */
4937 #endif /* USETTYLOCK */
4938 #else
4939 char * uucplockdir = "";
4940 #endif /* NOUUCP */
4941
4942 #ifdef QNX /* Only for QNX4 */
4943 int /* Visible to outside world */
qnxopencount()4944 qnxopencount() { /* Get QNX device open count */
4945 struct _dev_info_entry info;
4946 int x;
4947
4948 x = -1; /* Unknown */
4949 if (ttyfd > -1) {
4950 if (!dev_info(ttyfd, &info)) {
4951 debug(F101,"ttlock QNX open_count","",info.open_count);
4952 x = info.open_count;
4953 }
4954 }
4955 return(x);
4956 }
4957 #endif /* QNX */
4958
4959 char *
ttglckdir()4960 ttglckdir() { /* Get Lockfile directory name */
4961 #ifdef __OpenBSD__
4962 return("/var/spool/lock");
4963 #else /* __OpenBSD__ */
4964 #ifdef __FreeBSD__
4965 return("/var/spool/lock");
4966 #else /* __FreeBSD__ */
4967 #ifdef LOCK_DIR
4968 char * s = LOCK_DIR;
4969 #endif /* LOCK_DIR */
4970 #ifdef NOUUCP
4971 return("");
4972 #else /* NOUUCP */
4973 #ifdef LOCK_DIR
4974 return(s);
4975 #else /* LOCK_DIR */
4976 return("");
4977 #endif /* LOCK_DIR */
4978 #endif /* NOUUCP */
4979 #endif /* __FreeBSD__ */
4980 #endif /* __OpenBSD__ */
4981 }
4982
4983 static int
ttlock(ttdev)4984 ttlock(ttdev) char *ttdev; {
4985
4986 int x, n;
4987 int islink = 0;
4988 #ifdef __FreeBSD__
4989 char *devname;
4990 #endif /* __FreeBSD__ */
4991
4992 #ifdef NOUUCP
4993 debug(F100,"ttlock NOUUCP","",0);
4994 ckstrncpy(flfnam,"NOLOCK",FLFNAML);
4995 haslock = 1;
4996 return(0);
4997 #else /* !NOUUCP */
4998
4999 #ifdef USETTYLOCK
5000 haslock = 0; /* Not locked yet. */
5001 *flfnam = '\0'; /* Lockfile name is empty. */
5002 #ifdef __FreeBSD__
5003 if ((devname = xxlast(ttdev,'/')) != NULL)
5004 #ifdef FREEBSD8
5005 ckstrncat(lockname,devname+1,DEVNAMLEN-ckstrncpy(lockname,"pts",4));
5006 #else
5007 ckstrncpy(lockname,devname+1,DEVNAMLEN);
5008 #endif /* FREEBSD8 */
5009 #else
5010 if (!strncmp(ttdev,"/dev/",5) && ttdev[5])
5011 ckstrncpy(lockname,ttdev+5,DEVNAMLEN);
5012 #endif /* __FreeBSD__ */
5013 else
5014 ckstrncpy(lockname,ttdev,DEVNAMLEN);
5015 /*
5016 This might be overkill, but it's not clear from the man pages whether
5017 ttylock() can be called without calling ttylocked() first, since the doc
5018 says that ttylocked() removes any stale lockfiles, but it does not say this
5019 about ttylock(). Also the docs don't say what ttylocked() returns in the
5020 case when it finds and removes a stale lockfile. So one or both calls to
5021 to ttylocked() might be superfluous, but they should do no harm. Also I'm
5022 assuming that we have to do all the same ID swapping, etc, with these
5023 routines as we do without them. Thus the priv_on/off() sandwich.
5024 */
5025 #ifdef USE_UU_LOCK
5026 priv_on(); /* Turn on privs */
5027 x = uu_lock(lockname); /* Try to set the lock */
5028 priv_off(); /* Turn privs off */
5029 debug(F111,"ttlock uu_lock",lockname,x);
5030 switch (x) {
5031 case UU_LOCK_INUSE:
5032 return(-2);
5033 case UU_LOCK_OK:
5034 #ifdef BSD44
5035 ckmakmsg(flfnam,FLFNAML,"/var/spool/lock/LCK..",lockname,NULL,NULL);
5036 #endif /* BSD44 */
5037 haslock = 1;
5038 return(0);
5039 default:
5040 return(-1);
5041 }
5042 #else /* USE_UU_LOCK */
5043 priv_on(); /* Turn on privs */
5044 if (ttylocked(lockname)) { /* This should remove any stale lock */
5045 if (ttylocked(lockname)) { /* so check again. */
5046 priv_off();
5047 return(-5); /* Still locked, fail. */
5048 }
5049 }
5050 x = ttylock(lockname); /* Lock it. */
5051 priv_off(); /* Turn off privs */
5052
5053 debug(F111,"ttlock lockname",lockname,x);
5054 if (x > -1) {
5055 /*
5056 We don't really know the name of the lockfile, but
5057 this is what the man page says it is. In USETTYLOCK
5058 builds, it is used only for display by SHOW COMM.
5059 */
5060 ckmakmsg(flfnam,FLFNAML,"/etc/locks/LCK..",lockname,NULL,NULL);
5061 haslock = 1;
5062 }
5063 return(x);
5064 #endif /* USE_UU_LOCK */
5065 #else /* Systems that don't have ttylock()... */
5066
5067 #ifndef HPUX
5068
5069 int lockfd; /* File descriptor for lock file. */
5070 PID_T pid; /* Process id of this process. */
5071 int tries; /* How many times we've tried... */
5072 int dummy;
5073 struct stat devbuf; /* For device numbers (SVR4). */
5074
5075 #ifdef PIDSTRING
5076 char pid_str[32]; /* My pid in string format. */
5077 #endif /* PIDSTRING */
5078
5079 char *device, *devname;
5080
5081 /* Note: ridiculously long to prevent gcc complaints when used in sprintf */
5082 #define LFNAML 5126 /* Max length for lock file name. */
5083 char lockfil[LFNAML]; /* Lock file name */
5084 #ifdef RTAIX
5085 char lklockf[LFNAML]; /* Name for link to lock file */
5086 #endif /* RTAIX */
5087 #ifdef CKSYMLINK
5088 char symlock[LFNAML]; /* Name for symlink lockfile name */
5089 #endif /* CKSYMLINK */
5090 char tmpnam[LFNAML+30]; /* Temporary lockfile name. */
5091 char *lockdir = LOCK_DIR; /* Defined near top of this file, */
5092 /* or on cc command line. */
5093 haslock = 0; /* Not locked yet. */
5094 *flfnam = '\0'; /* Lockfile name is empty. */
5095 lock2[0] = '\0'; /* Clear secondary lockfile name. */
5096 pid = getpid(); /* Get id of this process. */
5097
5098 /* Construct name of lockfile and temporary file */
5099
5100 /* device = name of tty device without the path, e.g. "ttyh8" */
5101 /* lockfil = name of lock file, without path, e.g. "LCK..ttyh8" */
5102
5103 device = ((devname = xxlast(ttdev,'/')) != NULL ? devname+1 : ttdev);
5104
5105 if (stat(ttdev,&devbuf) < 0)
5106 return(-1);
5107
5108 #ifdef CKSYMLINK
5109 islink = 1; /* Assume it's a symlink */
5110 linkto[0] = '\0'; /* But we don't know to what */
5111 #ifdef COMMENT
5112 /*
5113 This is undependable. If it worked it would save the readlink call if
5114 we knew the device name was not a link.
5115 */
5116 #ifdef S_ISLNK
5117 islink = S_ISLNK(devbuf.st_mode);
5118 debug(F101,"ttlock stat S_ISLNK","",islink);
5119 #endif /* S_ISLNK */
5120 #endif /* COMMENT */
5121 if (islink) {
5122 n = readlink(ttdev,linkto,DEVNAMLEN); /* See if it's a link */
5123 debug(F111,"ttlock readlink",ttdev,n);
5124 if (n > -1) /* It is */
5125 linkto[n] = '\0';
5126 else /* It's not */
5127 islink = 0;
5128 debug(F111,"ttlock link",linkto,islink);
5129 }
5130 if (islink) {
5131 linkdev = (devname = xxlast(linkto,'/')) ? devname + 1 : linkto;
5132 debug(F110,"ttlock linkdev",linkdev,0);
5133 }
5134 #endif /* CKSYMLINK */
5135
5136 /*
5137 On SCO platforms, if we don't have a symlink, then let's pretend the
5138 name given for the device is a symlink, because later we will change
5139 the name if it contains any uppercase characters.
5140 */
5141 #ifdef CK_SCOV5 /* SCO Open Server 5.0 */
5142 if (!islink) {
5143 islink = 1;
5144 ckstrncpy(linkto,ttdev,DEVNAMLEN);
5145 linkdev = (devname = xxlast(linkto,'/')) ? devname + 1 : linkto;
5146 debug(F110,"ttlock linkdev",linkdev,0);
5147 }
5148 #else
5149 #ifdef M_XENIX /* SCO Xenix or UNIX */
5150 if (!islink) {
5151 islink = 1;
5152 ckstrncpy(linkto,ttdev,DEVNAMLEN);
5153 linkdev = (devname = xxlast(linkto,'/')) ? devname + 1 : linkto;
5154 debug(F110,"ttlock linkdev",linkdev,0);
5155 }
5156 #endif /* M_XENIX */
5157 #endif /* CK_SCOV5 */
5158
5159 #ifdef ISIII /* Interactive System III, PC/IX */
5160 ckstrncpy(lockfil, device, DEVNAMLEN);
5161 #else /* not ISIII */
5162 #ifdef LFDEVNO /* Lockfilename has device numbers. */
5163 #ifdef COHERENT
5164 sprintf(lockfil,"LCK..%d.%d", /* SAFE */
5165 major(devbuf.st_rdev), /* major device number */
5166 0x1f & minor(devbuf.st_rdev)); /* minor device number */
5167 #else
5168 /* Note: %d changed to %u in 8.0 -- %u is part of SVID for SVR4 */
5169 /* Lockfile name format verified to agree with Solaris cu, Dec 2001 */
5170 sprintf(lockfil,"LK.%03u.%03u.%03u", /* SAFE */
5171 major(devbuf.st_dev), /* device */
5172 major(devbuf.st_rdev), /* major device number */
5173 minor(devbuf.st_rdev)); /* minor device number */
5174 #endif /* COHERENT */
5175 #else /* Not LFDEVNO */
5176 #ifdef PTX /* Dynix PTX */
5177 if ((device != &ttdev[5]) && (strncmp(ttdev,"/dev/",5) == 0)) {
5178 if ((int)strlen(device) + 8 < LFNAML)
5179 sprintf(lockfil,"LCK..%.3s%s", &ttdev[5], device);
5180 else
5181 ckstrncpy(lockfil,"LOCKFILE_NAME_TOO_LONG",LFNAML);
5182 } else
5183 #endif /* PTX */
5184 if ((int)strlen(device) + 5 < LFNAML)
5185 sprintf(lockfil,"LCK..%s", device);
5186 else
5187 ckstrncpy(lockfil,"LOCKFILE_NAME_TOO_LONG",LFNAML);
5188 #ifdef RTAIX
5189 ckstrncpy(lklockf,device,DEVNAMLEN);
5190 #endif /* RTAIX */
5191 #ifdef CKSYMLINK
5192 symlock[0] = '\0';
5193 if (islink)
5194 ckmakmsg(symlock,LFNAML, "LCK..", linkdev, NULL, NULL);
5195 #endif /* CKSYMLINK */
5196 #endif /* LFDEVNO */
5197 #endif /* ISIII */
5198
5199 #ifdef CK_SCOV5 /* SCO Open Server 5.0 */
5200 {
5201 /* Lowercase the entire filename. */
5202 /* SCO says we must do this in V5.0 and later. */
5203 /* BUT... watch out for devices -- like Digiboard Portserver */
5204 /* That can have hundreds of ports... */
5205 char *p = (char *)(lockfil + 5);
5206 while (*p) { if (isupper(*p)) *p = (char) tolower(*p); p++; }
5207 }
5208 #ifdef CKSYMLINK
5209 if (islink) { /* If no change */
5210 if (!strcmp(lockfil,symlock)) { /* then no second lockfile needed */
5211 islink = 0;
5212 symlock[0] = '\0';
5213 }
5214 }
5215 #endif /* CKSYMLINK */
5216 #else
5217 #ifdef M_XENIX /* SCO Xenix or UNIX */
5218 {
5219 int x; char c;
5220 x = (int)strlen(lockfil) - 1; /* Get last letter of device name. */
5221 if (x > 0) { /* If it's uppercase, lower it. */
5222 c = lockfil[x];
5223 if (c >= 'A' && c <= 'Z') lockfil[x] += ('a' - 'A');
5224 }
5225 }
5226 #ifdef CKSYMLINK
5227 if (islink) {
5228 if (!strcmp(lockfil,symlock)) { /* No change */
5229 islink = 0; /* so no second lockfile */
5230 symlock[0] = '\0';
5231 }
5232 }
5233 #endif /* CKSYMLINK */
5234 #endif /* M_XENIX */
5235 #endif /* CK_SCOV5 */
5236
5237 /* flfnam = full lockfile pathname, e.g. "/usr/spool/uucp/LCK..ttyh8" */
5238 /* tmpnam = temporary unique, e.g. "/usr/spool/uucp/LTMP..pid" */
5239
5240 ckmakmsg(flfnam,LFNAML,lockdir,"/",lockfil,NULL);
5241
5242 #ifdef RTAIX
5243 ckmakmsg(lkflfn,FLFNAML,lockdir,"/",lklockf,NULL);
5244 #endif /* RTAIX */
5245
5246 #ifndef LFDEVNO
5247 #ifdef CKSYMLINK
5248 /* If it's a link then also make a lockfile for the real name */
5249 debug(F111,"ttlock link symlock",symlock,islink);
5250 if (islink && symlock[0]) {
5251 /* But only if the lockfile names would be different. */
5252 /* WARNING: They won't be, e.g. for /dev/ttyd2 => /hw/ttys/ttyd2 */
5253 ckmakmsg(lock2,FLFNAML,lockdir,"/",symlock,NULL);
5254 debug(F110,"ttlock lock2",lock2,0);
5255 if (!strcmp(lock2,flfnam)) { /* Are lockfile names the same? */
5256 debug(F100,"ttlock lock2 cleared","",0);
5257 lock2[0] = '\0'; /* Clear secondary lockfile name. */
5258 }
5259 }
5260 #endif /* CKSYMLINK */
5261 #endif /* LFDEVNO */
5262
5263 sprintf(tmpnam,"%s/LTMP.%05d",lockdir,(int) pid); /* safe */
5264 debug(F110,"ttlock flfnam",flfnam,0);
5265 debug(F110,"ttlock tmpnam",tmpnam,0);
5266
5267 priv_on(); /* Turn on privileges if possible. */
5268 lockfd = creat(tmpnam, 0444); /* Try to create temp lock file. */
5269 if (lockfd < 0) { /* Create failed. */
5270 debug(F111,"ttlock creat failed",tmpnam,errno);
5271 if (errno == ENOENT) {
5272 perror(lockdir);
5273 printf("UUCP not installed or Kermit misconfigured\n");
5274 } else {
5275 if (!quiet)
5276 perror(lockdir);
5277 unlink(tmpnam); /* Get rid of the temporary file. */
5278 }
5279 priv_off(); /* Turn off privileges!!! */
5280 return(-1); /* Return failure code. */
5281 }
5282 /* Now write the pid into the temp lockfile in the appropriate format */
5283
5284 #ifdef PIDSTRING /* For Honey DanBer UUCP, */
5285 sprintf( /* write PID as decimal string */
5286 pid_str,
5287 #ifdef LINUXFSSTND /* The "Linux File System Standard" */
5288 #ifdef FSSTND10 /* Version 1.0 calls for */
5289 "%010d\n", /* leading zeros */
5290 #else /* while version 1.2 calls for */
5291 "%10d\n", /* leading spaces */
5292 #endif /* FSSTND10 */
5293 #else
5294 #ifdef COHERENT
5295 "%d\n", /* with leading nothing */
5296 #else
5297 "%10d\n", /* with leading blanks */
5298 #endif /* COHERENT */
5299 #endif /* LINUXFSSTND */
5300 (int) pid
5301 ); /* safe */
5302 dummy = write(lockfd, pid_str, 11);
5303 debug(F111,"ttlock hdb pid string",pid_str,(int) pid);
5304
5305 #else /* Not PIDSTRING, use integer PID */
5306
5307 write(lockfd, (char *)&pid, sizeof(pid) );
5308 debug(F101,"ttlock pid","",(int) pid);
5309
5310 #endif /* PIDSTRING */
5311
5312 /* Now try to rename the temp file to the real lock file name. */
5313 /* This will fail if a lock file of that name already exists. */
5314
5315 close(lockfd); /* Close the temp lockfile. */
5316 chmod(tmpnam,0444); /* Permission for a valid lock. */
5317 tries = 0;
5318 while (!haslock && tries++ < 2) {
5319 haslock = 0;
5320 dummy = link(tmpnam,flfnam); /* Create a link to it. */
5321 if (dummy == 0) haslock = 1;
5322 if (haslock) { /* If we got the lockfile */
5323 #ifdef RTAIX
5324 link(flfnam,lkflfn);
5325 #endif /* RTAIX */
5326 #ifdef CKSYMLINK
5327 #ifndef LFDEVNO
5328 if (islink && lock2[0])
5329 dummy = link(flfnam,lock2);
5330 #endif /* LFDEVNO */
5331 #endif /* CKSYMLINK */
5332
5333 #ifdef COMMENT
5334 /* Can't do this any more because device is not open yet so no ttyfd. */
5335 #ifdef LOCKF
5336 /*
5337 Advisory file locking works on SVR4, so we use it. In fact, it is
5338 necessary in some cases, e.g. when SLIP is involved. But it still doesn't
5339 seem to prevent multiple users accessing the same device by different names.
5340 */
5341 while (lockf(ttyfd, F_TLOCK, 0L) != 0) {
5342 debug(F111, "ttlock lockf returns errno", "", errno);
5343 if ((++tries >= 3) || (errno != EAGAIN)) {
5344 x = unlink(flfnam); /* remove the lockfile */
5345 #ifdef RTAIX
5346 unlink(lkflfn); /* And any links to it... */
5347 #endif /* RTAIX */
5348 #ifdef CKSYMLINK
5349 #ifndef LFDEVNO
5350 if (islink && lock2[0])
5351 unlink(lock2); /* ditto... */
5352 #endif /* LFDEVNO */
5353 #endif /* CKSYMLINK */
5354 debug(F111,"ttlock unlink",flfnam,x);
5355 haslock = 0;
5356 break;
5357 }
5358 sleep(2);
5359 }
5360 if (haslock) /* If we got an advisory lock */
5361 #endif /* LOCKF */
5362 #endif /* COMMENT */
5363 break; /* We're done. */
5364
5365 } else { /* We didn't create a new lockfile. */
5366 priv_off();
5367 if (ttchkpid(flfnam)) { /* Check existing lockfile */
5368 priv_on(); /* cause ttchkpid turns priv_off... */
5369 unlink(tmpnam); /* Delete the tempfile */
5370 debug(F100,"ttlock found tty locked","",0);
5371 priv_off(); /* Turn off privs */
5372 return(-2); /* Code for device is in use. */
5373 }
5374 priv_on();
5375 }
5376 }
5377 unlink(tmpnam); /* Unlink (remove) the temp file. */
5378 priv_off(); /* Turn off privs */
5379 return(haslock ? 0 : -1); /* Return link's return code. */
5380
5381 #else /* HPUX */
5382
5383 /*
5384 HP-UX gets its own copy of this routine, modeled after the observed behavior
5385 of the HP-UX 'cu' program. HP-UX serial device names consist of a base name
5386 such as "tty", "ttyd", "cua", "cul", "cuad", or "culd", followed by a unit
5387 designator which is a string of digits, possibly containing an imbedded
5388 letter "p". Examples (for base name "tty"):
5389
5390 /dev/tty0, /dev/tty00, dev/ttyd00, /dev/tty0p0
5391
5392 According to the HP-UX UUCP manual of 1988, the "0p0" notation has been
5393 used on Series 800 since HP-UX 2.00, and the "non-p" notation was used
5394 on other models. In HP-UX 10.00, "0p0" notation was adopted for all models.
5395 However, we make and enforce no such distinctions; either notation is
5396 accepted on any model or HP-UX version as a valid unit designator.
5397
5398 If a valid unit is specified (as opposed to a designer name or symlink), we
5399 check for all aliases of the given unit according to the devprefix[] array.
5400 If no lockfiles are found for the given unit, we can have the device; we
5401 create a lockfile LCK..name in the lockfile directory appropriate for the
5402 HP-UX version (/var/spool/locks for 10.00 and later, /usr/spool/uucp for
5403 9.xx and earlier). If it is a "cua" or "cul" device, a second lockfile is
5404 created with the "ttyd" prefix. This is exactly what cu does.
5405
5406 If the "set line" device does not have a valid unit designator, then it is
5407 used literally and no synomyms are searched for and only one lockfile is
5408 created.
5409
5410 -fdc, March 1998.
5411 */
5412 #define LFNAML 80 /* Max length for lock file name. */
5413
5414 int lockfd; /* File descriptor for lock file. */
5415 PID_T pid; /* Process ID of this process. */
5416 int fpid; /* pid found in existing lockfile. */
5417 int tries; /* How many times we've tried... */
5418 int i, k; /* Workers */
5419
5420 char *device, *devname; /* "/dev/xxx", "xxx" */
5421 char *unit, *p; /* <instance>p<port> part of xxx */
5422
5423 char lockfil[LFNAML]; /* Lockfile name (no path) */
5424 char tmpnam[LFNAML]; /* Temporary lockfile name. */
5425
5426 #ifdef HPUX10 /* Lockfile directory */
5427 char *lockdir = "/var/spool/locks"; /* Always this for 10.00 and higher */
5428 #else /* HP-UX 9.xx and below */
5429 #ifdef LOCK_DIR
5430 char *lockdir = LOCK_DIR; /* Defined near top of this file */
5431 #else
5432 char *lockdir = "/usr/spool/uucp"; /* or not... */
5433 #endif /* LOCK_DIR */
5434 #endif /* HPUX10 */
5435
5436 haslock = 0; /* Not locked yet. */
5437 *flfnam = '\0'; /* Lockfile name is empty. */
5438 lock2[0] = '\0'; /* Second one too. */
5439 pid = getpid(); /* Get my process ID */
5440 /*
5441 Construct name of lockfile and temporary file...
5442 device = name of tty device without the path, e.g. "tty0p0"
5443 lockfil = name of lock file, without path, e.g. "LCK..tty0p0"
5444 */
5445 device = ((devname = xxlast(ttdev,'/')) != NULL ? devname+1 : ttdev);
5446 debug(F110,"TTLOCK device",device,0);
5447 ckmakmsg(lockfil,LFNAML,"LCK..",device,NULL,NULL);
5448
5449 k = 0; /* Assume device is not locked */
5450 n = 0; /* Digit counter */
5451 unit = device; /* Unit = <instance>p<port> */
5452 while (*unit && !isdigit(*unit)) /* Search for digit... */
5453 unit++;
5454 p = unit; /* Verify <num>p<num> format... */
5455 debug(F110,"TTLOCK unit 1",unit,0);
5456 /*
5457 The unit number is recognized as:
5458 (a) any sequence of digits that runs to the end of the string.
5459 (b) any (a) that includes one and only one letter "p", with at least
5460 one digit before and after it.
5461 */
5462 while (isdigit(*p)) p++, n++; /* Get a run of digits */
5463 if (*p && n > 0) { /* Have a "p"? */
5464 if (*p == 'p' && isdigit(*(p+1))) {
5465 p++;
5466 n = 0;
5467 while (isdigit(*p)) p++, n++;
5468 }
5469 }
5470 if (n == 0 || *p) unit = "";
5471 debug(F110,"TTLOCK unit 2",unit,0);
5472
5473 if (*unit) { /* Device name has unit number. */
5474 /* The following loop not only searches for the various lockfile */
5475 /* synonyms, but also removes all -- not just one -- stale lockfile */
5476 /* for the device, should there be more than one. See ttchkpid(). */
5477 ttydexists = 0;
5478 for (i = 0; *devprefix[i]; i++) { /* For each driver... */
5479 /* Make device name */
5480 ckmakmsg(lock2,FLFNAML,"/dev/",devprefix[i],unit,NULL);
5481 priv_on(); /* Privs on */
5482 k = zchki(lock2) != -1; /* See if device exists */
5483 priv_off(); /* Privs off */
5484 debug(F111,"TTLOCK exist",lock2,k);
5485 if (k) {
5486 if (!strcmp(devprefix[i],"ttyd")) /* ttyd device exists */
5487 ttydexists = 1;
5488 /* Make lockfile name */
5489 ckmakmsg(lock2,FLFNAML,lockdir,"/LCK..",devprefix[i],unit);
5490 debug(F110,"TTLOCK checking",lock2,0);
5491 priv_on(); /* Privs on */
5492 k = zchki(lock2) != -1; /* See if lockfile exists */
5493 priv_off(); /* Privs off */
5494 debug(F111,"TTLOCK check for lock A",lock2,k);
5495 if (k) if (ttchkpid(lock2)) { /* If pid still active, fail. */
5496 ckstrncpy(flfnam,lock2,FLFNAML);
5497 return(-2);
5498 }
5499 }
5500 }
5501 } else { /* Some other device-name format */
5502 /* This takes care of symbolic links, etc... */
5503 /* But does not chase them down! */
5504 ckmakmsg(lock2,FLFNAML,lockdir,"/LCK..",device,NULL);
5505 priv_on();
5506 k = zchki(lock2) != -1; /* Check for existing lockfile */
5507 priv_off();
5508 debug(F111,"TTLOCK check for lock B",lock2,k);
5509 if (k) if (ttchkpid(lock2)) { /* Check pid from lockfile */
5510 ckstrncpy(flfnam,lock2,FLFNAML);
5511 debug(F110,"TTLOCK in use",device,0);
5512 debug(F101,"TTLOCK returns","",-2);
5513 return(-2);
5514 }
5515 }
5516 /*
5517 Get here only if there is no (more) lockfile, so now we make one (or two)...
5518 flfnam = full lockfile pathname, e.g. "/usr/spool/uucp/LCK..cul0p0".
5519 tmpnam = unique temporary filname, e.g. "/usr/spool/uucp/LTMP..pid".
5520 */
5521 ckmakmsg(flfnam,FLFNAML,lockdir,"/",lockfil,NULL); /* SET LINE device */
5522
5523 /* If dialout device, also make one for corresponding dialin device */
5524 lock2[0] = '\0';
5525 if (!strncmp(device,"cu",2) && *unit && ttydexists)
5526 ckmakmsg(lock2,FLFNAML,lockdir,"/LCK..ttyd",unit,NULL);
5527
5528 if ((int)strlen(lockdir)+12 < LFNAML)
5529 sprintf(tmpnam,"%s/LTMP.%05d",lockdir,(int) pid); /* Make temp name */
5530 #ifdef DEBUG
5531 if (deblog) {
5532 debug(F110,"TTLOCK flfnam",flfnam,0);
5533 debug(F110,"TTLOCK lock2",lock2,0);
5534 debug(F110,"TTLOCK tmpnam",tmpnam,0);
5535 }
5536 #endif /* DEBUG */
5537 /*
5538 Lockfile permissions...
5539 444 is standard, HP-UX 10.00 uses 664. It doesn't matter.
5540 Kermit uses 444; the difference lets us tell whether Kermit created
5541 the lock file.
5542 */
5543 priv_on(); /* Turn on privileges. */
5544 lockfd = creat(tmpnam, 0444); /* Try to create temporary file. */
5545 if (lockfd < 0) { /* Create failed. */
5546 debug(F111,"TTLOCK creat failed",tmpnam,errno);
5547 if (errno == ENOENT) {
5548 perror(lockdir);
5549 printf("UUCP not installed or Kermit misconfigured\n");
5550 } else {
5551 if (!quiet)
5552 perror(lockdir);
5553 unlink(tmpnam); /* Get rid of the temporary file. */
5554 }
5555 priv_off(); /* Turn off privileges!!! */
5556 debug(F101,"TTLOCK returns","",-1);
5557 return(-1); /* Return failure code. */
5558 }
5559 debug(F110,"TTLOCK temp ok",tmpnam,0);
5560
5561 /* Now write our pid into the temp lockfile in integer format. */
5562
5563 i = write(lockfd, (char *)&pid, sizeof(pid));
5564
5565 #ifdef DEBUG
5566 if (deblog) {
5567 debug(F101,"TTLOCK pid","",pid);
5568 debug(F101,"TTLOCK sizeof pid","",sizeof(pid));
5569 debug(F101,"TTLOCK write pid returns","",i);
5570 }
5571 #endif /* DEBUG */
5572
5573 /*
5574 Now try to rename the temporary file to the real lockfile name.
5575 This will fail if a lock file of that name already exists, which
5576 will catch race conditions with other users.
5577 */
5578 close(lockfd); /* Close the temp lockfile. */
5579 chmod(tmpnam,0444);
5580
5581 tries = 0;
5582 while (!haslock && tries++ < 2) {
5583 haslock = (link(tmpnam,flfnam) == 0); /* Create a link to it. */
5584 debug(F101,"TTLOCK link","",haslock);
5585 if (haslock) { /* If we made the lockfile... */
5586
5587 #ifdef COMMENT
5588 /* We can't do this any more because we don't have a file descriptor yet. */
5589 #ifdef LOCKF /* Can be canceled with -DNOLOCKF */
5590 /*
5591 Create an advisory lock on the device through its file descriptor.
5592 This code actually seems to work. If it is executed, and then another
5593 process tries to open the same device under a different name to circumvent
5594 the lockfile, they get a "device busy" error.
5595 */
5596 debug(F100,"TTLOCK LOCKF code...","",0);
5597 while ( lockf(ttyfd, F_TLOCK, 0L) != 0 ) {
5598 debug(F111, "TTLOCK lockf error", "", errno);
5599 if ((++tries >= 3) || (errno != EAGAIN)) {
5600 x = unlink(flfnam); /* Remove the lockfile */
5601 if (errno == EACCES && !quiet)
5602 printf("Device already locked by another process\n");
5603 haslock = 0;
5604 break;
5605 }
5606 sleep(2);
5607 }
5608 #endif /* LOCKF */
5609 #endif /* COMMENT */
5610
5611 if (haslock) { /* If we made the lockfile ... */
5612 if (lock2[0]) { /* if there is to be a 2nd lockfile */
5613 lockfd = creat(lock2, 0444); /* Create it */
5614 debug(F111,"TTLOCK lock2 creat", lock2, lockfd);
5615 if (lockfd > -1) { /* Created OK, write pid. */
5616 write(lockfd, (char *)&pid, sizeof(pid) );
5617 close(lockfd); /* Close and */
5618 chmod(lock2, 0444); /* set permissions. */
5619 } else { /* Not OK, but don't fail. */
5620 lock2[0] = '\0'; /* Just remember it's not there. */
5621 }
5622 }
5623 break; /* and we're done. */
5624 }
5625 }
5626 }
5627 unlink(tmpnam); /* Unlink (remove) the temp file. */
5628 priv_off(); /* Turn off privs */
5629 i = haslock ? 0 : -1; /* Our return value */
5630 debug(F101,"TTLOCK returns","",i);
5631 return(i);
5632 #endif /* HPUX */
5633 #endif /* USETTYLOCK */
5634 #endif /* !NOUUCP */
5635 }
5636
5637 /* T T U N L O C K */
5638
5639 static int
ttunlck()5640 ttunlck() { /* Remove UUCP lockfile(s). */
5641 #ifndef NOUUCP
5642 int x;
5643
5644 debug(F111,"ttunlck",flfnam,haslock);
5645
5646 #ifdef USETTYLOCK
5647
5648 if (haslock && *flfnam) {
5649 int x;
5650 priv_on(); /* Turn on privs */
5651 #ifdef USE_UU_LOCK
5652 x = uu_unlock(lockname);
5653 #else /* USE_UU_LOCK */
5654 x = ttyunlock(lockname); /* Try to unlock */
5655 #endif /* USE_UU_LOCK */
5656 priv_off(); /* Turn off privs */
5657 if (x < 0 && !quiet)
5658 printf("Warning - Can't remove lockfile: %s\n", flfnam);
5659
5660 *flfnam = '\0'; /* Erase the name. */
5661 haslock = 0;
5662 return(0);
5663 }
5664
5665 #else /* No ttylock()... */
5666
5667 if (haslock && *flfnam) {
5668 /* Don't remove lockfile if we didn't make it ourselves */
5669 if ((x = ttrpid(flfnam)) != (int)getpid()) {
5670 debug(F111,"ttunlck lockfile seized",flfnam,x);
5671 printf("Warning - Lockfile %s seized by pid %d\n",
5672 flfnam,
5673 x
5674 );
5675 return(0);
5676 }
5677 priv_on(); /* Turn privileges on. */
5678 errno = 0;
5679 x = unlink(flfnam); /* Remove the lockfile. */
5680 debug(F111,"ttunlck unlink",flfnam,x);
5681 if (x < 0) {
5682 if (errno && !quiet)
5683 perror(ttnmsv);
5684 printf("Warning - Can't remove lockfile: %s\n", flfnam);
5685 }
5686 haslock = 0;
5687 *flfnam = '\0'; /* Erase the name. */
5688
5689 #ifdef RTAIX
5690 errno = 0;
5691 x = unlink(lkflfn); /* Remove link to lockfile */
5692 debug(F111,"ttunlck AIX link unlink",lkflfn,x);
5693 if (x < 0) {
5694 if (errno && !quiet)
5695 perror(ttnmsv);
5696 printf("Warning - Can't remove link to lockfile: %s\n", lkflfn);
5697 }
5698 *lkflfn = '\0';
5699 #else
5700 if (lock2[0]) { /* If there is a second lockfile, */
5701 errno = 0;
5702 x = unlink(lock2); /* remove it too. */
5703 debug(F111,"ttunlck lock2 unlink",lock2,x);
5704 if (x < 0) {
5705 if (errno && !quiet)
5706 perror(ttnmsv);
5707 printf("Warning - Can't remove secondary lockfile: %s\n",
5708 lock2
5709 );
5710 }
5711 lock2[0] = '\0'; /* Forget its name. */
5712 }
5713 #endif /* RTAIX */
5714
5715 #ifdef COMMENT
5716 #ifdef LOCKF
5717 (VOID) lockf(ttyfd, F_ULOCK, 0L); /* Remove advisory lock */
5718 #endif /* LOCKF */
5719 #endif /* COMMENT */
5720
5721 priv_off(); /* Turn privileges off. */
5722 }
5723 #endif /* USETTYLOCK */
5724 #endif /* !NOUUCP */
5725 return(0);
5726 }
5727
5728 /*
5729 4.3BSD-style UUCP line direction control.
5730 (Stan Barber, Rice U, 1980-something...)
5731 */
5732 #ifndef NOUUCP
5733 #ifdef ACUCNTRL
5734 VOID
acucntrl(flag,ttname)5735 acucntrl(flag,ttname) char *flag, *ttname; {
5736 char x[DEVNAMLEN+32], *device, *devname;
5737
5738 if (strcmp(ttname,CTTNAM) == 0 || xlocal == 0) /* If not local, */
5739 return; /* just return. */
5740 device = ((devname = xxlast(ttname,'/')) != NULL ? devname+1 : ttname);
5741 if (strncmp(device,"LCK..",4) == 0) device += 5;
5742 ckmakmsg(x,DEVNAMLEN+32,"/usr/lib/uucp/acucntrl ",flag," ",device);
5743 debug(F110,"called ",x,0);
5744 zsyscmd(x);
5745 }
5746 #endif /* ACUCNTRL */
5747 #endif /* NOUUCP */
5748
5749 /*
5750 T T H F L O W -- Set or Reset hardware flow control.
5751
5752 This is an attempt to collect all hardware-flow-control related code
5753 into a single module. Thanks to Rick Sladkey and John Kohl for lots of
5754 help here. Overview:
5755
5756 Hardware flow control is not supported in many UNIX implementions. Even
5757 when it is supported, there is no (ha ha) "standard" for the programming
5758 interface. In general, 4.3BSD and earlier (sometimes), 4.4BSD, System V,
5759 SunOS, AIX, etc, have totally different methods. (And, not strictly
5760 relevant here, the programming interface often brings one only to a no-op
5761 in the device driver!)
5762
5763 Among all these, we have two major types of APIs: those in which hardware
5764 flow control is determined by bits in the same termio/termios/sgtty mode
5765 word(s) that are used for controlling such items as CBREAK vs RAW mode, and
5766 which are also used by the ttvt(), ttpkt(), conbin(), and concb() routines
5767 for changing terminal modes. And those that use entirely different
5768 mechanisms.
5769
5770 In the first category, it is important that any change in the mode bits be
5771 reflected in the relevant termio(s)/sgtty structure, so that subsequent
5772 changes to that structure do not wipe out the effects of this routine. That
5773 is why a pointer, attrs, to the appropriate structure is passed as a
5774 parameter to this routine.
5775
5776 The second category should give us no worries, since any changes to hardware
5777 flow control accomplished by this routine should not affect the termio(s)/
5778 sgtty structures, and therefore will not be undone by later changes to them.
5779
5780 The second argument, status, means to turn on hardware flow control if
5781 nonzero, and to turn it off if zero.
5782
5783 Returns: 0 on apparent success, -1 on probable failure.
5784 */
5785
5786 /*
5787 The following business is for BSDI, where it was discovered that two
5788 separate bits, CCTS_OFLOW and CRTS_IFLOW, are used in hardware flow control,
5789 but CTRSCTS is defined (in <termios.h>) to be just CCTS_OFLOW rather both
5790 bits, so hwfc only works in one direction if you use CRTSCTS to control it.
5791 Other 4.4BSD-based Unixes such as FreeBSD 4.1, which use these two bits,
5792 define CRTSCTS correctly.
5793 */
5794 #ifdef FIXCRTSCTS
5795 #ifdef CRTSCTS
5796 #ifdef CCTS_OFLOW
5797 #ifdef CRTS_IFLOW
5798 #undef CRTSCTS
5799 #define CRTSCTS (CRTS_IFLOW|CCTS_OFLOW)
5800 #endif /* CRTS_IFLOW */
5801 #endif /* CCTS_OFLOW */
5802 #endif /* CRTSCTS */
5803 #endif /* FIXCRTSCTS */
5804
5805 static int
tthflow(flow,status,attrs)5806 tthflow(flow, status, attrs)
5807 int flow, /* Type of flow control (ckcdeb.h) */
5808 status; /* Nonzero = turn it on */
5809 /* Zero = turn it off */
5810 #ifdef BSD44ORPOSIX /* POSIX or BSD44 */
5811 struct termios *attrs;
5812 #else /* System V */
5813 #ifdef ATTSV
5814 #ifdef ATT7300
5815 #ifdef UNIX351M
5816 /* AT&T UNIX 3.51m can set but not test for hardware flow control */
5817 #define RTSFLOW CTSCD
5818 #define CTSFLOW CTSCD
5819 #endif /* ATT7300 */
5820 #endif /* UNIX351M */
5821 struct termio *attrs;
5822 #else /* BSD, V7, etc */
5823 struct sgttyb *attrs; /* sgtty info... */
5824 #endif /* ATTSV */
5825 #endif /* BSD44ORPOSIX */
5826 /* tthflow */ {
5827
5828 int x = 0; /* tthflow() return code */
5829
5830 #ifdef Plan9
5831 return p9tthflow(flow, status);
5832 #else
5833
5834 #ifndef OXOS /* NOT Olivetti X/OS... */
5835 /*
5836 For SunOS 4.0 and later in the BSD environment ...
5837
5838 The declarations are copied and interpreted from the System V header files,
5839 so we don't actually have to pull in all the System V junk when building
5840 C-Kermit for SunOS in the BSD environment, which would be dangerous because
5841 having those symbols defined would cause us to take the wrong paths through
5842 the code. The code in this section is used in both the BSD and Sys V SunOS
5843 versions.
5844 */
5845 #ifdef SUNOS41
5846 /*
5847 In SunOS 4.1 and later, we use the POSIX calls rather than ioctl calls
5848 because GNU CC uses different formats for the _IOxxx macros than regular CC;
5849 the POSIX forms work for both. But the POSIX calls are not available in
5850 SunOS 4.0.
5851 */
5852 #define CRTSCTS 0x80000000 /* RTS/CTS flow control */
5853 #define TCSANOW 0 /* Do it now */
5854
5855 struct termios {
5856 unsigned long c_iflag; /* Input modes */
5857 unsigned long c_oflag; /* Output modes */
5858 unsigned long c_cflag; /* Control modes */
5859 unsigned long c_lflag; /* Line discipline modes */
5860 char c_line;
5861 CHAR c_cc[17];
5862 };
5863 struct termios temp;
5864
5865 _PROTOTYP( int tcgetattr, (int, struct termios *) );
5866 _PROTOTYP( int tcsetattr, (int, int, struct termios *) );
5867 /*
5868 When CRTSCTS is set, SunOS won't do output unless both CTS and CD are
5869 asserted. So we don't set CRTSCTS unless CD is up. This should be OK,
5870 since we don't need RTS/CTS during dialing, and after dialing is complete,
5871 we should have CD. If not, we still communicate, but without RTS/CTS.
5872 */
5873 int mflags; /* Modem signal flags */
5874
5875 #ifdef NETCMD
5876 if (ttpipe) return(0);
5877 #endif /* NETCMD */
5878 #ifdef NETPTY
5879 if (ttpty) return(0);
5880 #endif /* NETPTY */
5881
5882 debug(F101,"tthflow SUNOS41 entry status","",status);
5883 if (!status) { /* Turn hard flow off */
5884 if (tcgetattr(ttyfd, &temp) > -1 && /* Get device attributes */
5885 (temp.c_cflag & CRTSCTS)) { /* Check for RTS/CTS */
5886 temp.c_cflag &= ~CRTSCTS; /* It's there, remove it */
5887 x = tcsetattr(ttyfd,TCSANOW,&temp);
5888 }
5889 } else { /* Turn hard flow on */
5890 if (ioctl(ttyfd,TIOCMGET,&mflags) > -1 && /* Get modem signals */
5891 (mflags & TIOCM_CAR)) { /* Check for CD */
5892 debug(F100,"tthflow SunOS has CD","",0);
5893 if (tcgetattr(ttyfd, &temp) > -1 && /* Get device attributes */
5894 !(temp.c_cflag & CRTSCTS)) { /* Check for RTS/CTS */
5895 temp.c_cflag |= CRTSCTS; /* Not there, add it */
5896 x = tcsetattr(ttyfd,TCSANOW,&temp);
5897 }
5898 } else {
5899 x = -1;
5900 debug(F100,"tthflow SunOS no CD","",0);
5901 }
5902 }
5903 #else
5904 #ifdef QNX
5905 struct termios temp;
5906 #ifdef NETCMD
5907 if (ttpipe) return(0);
5908 #endif /* NETCMD */
5909 #ifdef NETPTY
5910 if (ttpty) return(0);
5911 #endif /* NETPTY */
5912 debug(F101,"tthflow QNX entry status","",status);
5913 if (tcgetattr(ttyfd, &temp) > -1) { /* Get device attributes */
5914 if (!status) { /* Turn hard flow off */
5915 if ((temp.c_cflag & (IHFLOW|OHFLOW)) == (IHFLOW|OHFLOW)) {
5916 temp.c_cflag &= ~(IHFLOW|OHFLOW); /* It's there, remove it */
5917 attrs->c_cflag &= ~(IHFLOW|OHFLOW);
5918 x = tcsetattr(ttyfd,TCSANOW,&temp);
5919 }
5920 } else { /* Turn hard flow on */
5921 if ((temp.c_cflag & (IHFLOW|OHFLOW)) != (IHFLOW|OHFLOW)) {
5922 temp.c_cflag |= (IHFLOW|OHFLOW); /* Not there, add it */
5923 temp.c_iflag &= ~(IXON|IXOFF); /* Bye to IXON/IXOFF */
5924 ttraw.c_lflag |= IEXTEN; /* Must be on */
5925 x = tcsetattr(ttyfd,TCSANOW,&temp);
5926 attrs->c_cflag |= (IHFLOW|OHFLOW);
5927 attrs->c_iflag &= ~(IXON|IXOFF);
5928 }
5929 }
5930 } else {
5931 x = -1;
5932 debug(F100, "tthflow QNX getattr fails", "", 0);
5933 }
5934 #else
5935 #ifdef POSIX_CRTSCTS
5936 /*
5937 POSIX_CRTSCTS is defined in ckcdeb.h or on CC command line.
5938 Note: Do not assume CRTSCTS is a one-bit field!
5939 */
5940 struct termios temp;
5941 #ifdef NETCMD
5942 if (ttpipe) return(0);
5943 #endif /* NETCMD */
5944 #ifdef NETPTY
5945 if (ttpty) return(0);
5946 #endif /* NETPTY */
5947 debug(F101,"tthflow POSIX_CRTSCTS entry status","",status);
5948 errno = 0;
5949 x = tcgetattr(ttyfd, &temp);
5950 debug(F111,"tthflow POSIX_CRTSCTS tcgetattr",ckitoa(x),errno);
5951 errno = 0;
5952 if (x < 0) {
5953 x = -1;
5954 } else {
5955 if (!status) { /* Turn hard flow off */
5956 if (
5957 #ifdef COMMENT
5958 /* This can fail because of sign extension */
5959 /* e.g. in Linux where it's Bit 31 */
5960 (temp.c_cflag & CRTSCTS) == CRTSCTS
5961 #else
5962 (temp.c_cflag & CRTSCTS) != 0
5963 #endif /* COMMENT */
5964 ) {
5965 temp.c_cflag &= ~CRTSCTS; /* It's there, remove it */
5966 attrs->c_cflag &= ~CRTSCTS;
5967 x = tcsetattr(ttyfd,TCSANOW,&temp);
5968 debug(F111,"tthflow POSIX_CRTSCTS OFF tcsetattr",
5969 ckitoa(x),errno);
5970 } else { /* John Dunlap 2010-01-26 */
5971 debug(F001,
5972 "tthflow before forcing off attrs CRTSCTS",
5973 "",
5974 attrs->c_cflag&CRTSCTS
5975 );
5976 attrs->c_cflag &= ~CRTSCTS; /* force it off if !status */
5977 debug(F001,
5978 "tthflow after forcing off attrs CRTSCTS",
5979 "",
5980 attrs->c_cflag&CRTSCTS
5981 );
5982 }
5983 } else { /* Turn hard flow on */
5984 if (
5985 #ifdef COMMENT
5986 /* This can fail because of sign extension */
5987 (temp.c_cflag & CRTSCTS) != CRTSCTS
5988 #else
5989 (temp.c_cflag & CRTSCTS) == 0
5990 #endif /* COMMENT */
5991 ) {
5992 temp.c_cflag |= CRTSCTS; /* Not there, add it */
5993 temp.c_iflag &= ~(IXON|IXOFF|IXANY); /* Bye to IXON/IXOFF */
5994 x = tcsetattr(ttyfd,TCSANOW,&temp);
5995 debug(F111,"tthflow POSIX_CRTSCTS ON tcsetattr",
5996 ckitoa(x),errno);
5997 attrs->c_cflag |= CRTSCTS;
5998 attrs->c_iflag &= ~(IXON|IXOFF|IXANY);
5999 }
6000 }
6001 }
6002 #else
6003 #ifdef SUNOS4
6004 /*
6005 SunOS 4.0 (and maybe earlier?). This code is dangerous because it
6006 prevents compilation with GNU gcc, which uses different formats for the
6007 _IORxxx macros than regular cc. SunOS 4.1 and later can use the POSIX
6008 routines above, which work for both cc and gcc.
6009 */
6010 #define TCGETS _IOR(T, 8, struct termios) /* Get modes into termios struct */
6011 #define TCSETS _IOW(T, 9, struct termios) /* Set modes from termios struct */
6012 #define CRTSCTS 0x80000000 /* RTS/CTS flow control */
6013
6014 struct termios {
6015 unsigned long c_iflag; /* Input modes */
6016 unsigned long c_oflag; /* Output modes */
6017 unsigned long c_cflag; /* Control modes */
6018 unsigned long c_lflag; /* Line discipline modes */
6019 char c_line;
6020 CHAR c_cc[17];
6021 };
6022 struct termios temp;
6023 #ifdef NETCMD
6024 if (ttpipe) return(0);
6025 #endif /* NETCMD */
6026 #ifdef NETPTY
6027 if (ttpty) return(0);
6028 #endif /* NETPTY */
6029 debug(F101,"tthflow entry status","",status);
6030 if (ioctl(ttyfd,TCGETS,&temp) > -1) { /* Get terminal modes. */
6031 if (status) { /* Turn hard flow on */
6032 temp.c_cflag |= CRTSCTS; /* Add RTS/CTS to them. */
6033 x = ioctl(ttyfd,TCSETS,&temp); /* Set them again. */
6034 attrs->c_cflag |= CRTSCTS; /* Add to global info. */
6035 } else { /* Turn hard flow off */
6036 temp.c_cflag &= ~CRTSCTS;
6037 x = ioctl(ttyfd,TCSETS,&temp);
6038 attrs->c_cflag &= ~CRTSCTS;
6039 }
6040 }
6041 #else /* Not SunOS 4.0 or later */
6042 #ifdef AIXRS /* IBM AIX RS/6000 */
6043 #ifndef AIX41 /* But only pre-4.x == SVR4 */
6044 #ifdef NETCMD
6045 if (ttpipe) return(0);
6046 #endif /* NETCMD */
6047 #ifdef NETPTY
6048 if (ttpty) return(0);
6049 #endif /* NETPTY */
6050 if (status) {
6051 if ((x = ioctl(ttyfd, TXADDCD, "rts")) < 0 && errno != EBUSY)
6052 debug(F100,"hardflow TXADDCD (rts) error", "", 0);
6053 } else {
6054 if ((x = ioctl(ttyfd, TXDELCD, "rts")) < 0 && errno != EINVAL)
6055 debug(F100,"hardflow TXDELCD (rts) error", "", 0);
6056 }
6057 #endif /* AIX41 */
6058 #else /* Not AIX RS/6000 */
6059
6060 #ifdef ATTSV /* System V... */
6061
6062 #ifdef CK_SCOV5 /* SCO Open Server 5.0 */
6063 #define CK_SCOUNIX
6064 #else
6065 #ifdef M_UNIX /* SCO UNIX 3.2v4.x or earlier */
6066 #define CK_SCOUNIX
6067 #endif /* M_UNIX */
6068 #endif /* CK_SCOV5 */
6069
6070 #ifdef SCO_FORCE_RTSXOFF
6071 #ifdef CK_SCOUNIX /* But not SCO OpenServer 5.0.4 */
6072 #ifdef SCO_OSR504 /* or later... */
6073 #undef CK_SCOUNIX
6074 #endif /* SCO_OSR504 */
6075 #endif /* CK_SCOUNIX */
6076 #endif /* SCO_FORCE_RTSXOFF */
6077
6078 #ifdef CK_SCOUNIX
6079 #ifdef POSIX
6080 struct termios temp;
6081 #ifdef NETCMD
6082 if (ttpipe) return(0);
6083 #endif /* NETCMD */
6084 #ifdef NETPTY
6085 if (ttpty) return(0);
6086 #endif /* NETPTY */
6087 debug(F101,"tthflow SCOUNIX POSIX entry status","",status);
6088 errno = 0;
6089 x = tcgetattr(ttyfd, &temp);
6090 debug(F111,"tthflow SCO UNIX POSIX tcgetattr",ckitoa(x),errno);
6091 #else /* POSIX */
6092 struct termio temp;
6093 #ifdef NETCMD
6094 if (ttpipe) return(0);
6095 #endif /* NETCMD */
6096 #ifdef NETPTY
6097 if (ttpty) return(0);
6098 #endif /* NETPTY */
6099 debug(F101,"tthflow SCOUNIX non-POSIX entry status","",status);
6100 x = ioctl(ttyfd, TCGETA, &temp);
6101 debug(F111,"tthflow SCO UNIX non-POSIX TCGETA",ckitoa(x),errno);
6102 #endif /* POSIX */
6103 /*
6104 This is not really POSIX, since POSIX does not deal with hardware flow
6105 control, but we are using the POSIX APIs. In fact, RTSFLOW and CTSFLOW
6106 are defined in termio.h, but within #ifndef _POSIX_SOURCE..#endif. So
6107 let's try forcing their definitions here.
6108 */
6109 #ifndef CTSFLOW
6110 #define CTSFLOW 0020000
6111 debug(F101,"tthflow SCO defining CTSFLOW","",CTSFLOW);
6112 #else
6113 debug(F101,"tthflow SCO CTSFLOW","",CTSFLOW);
6114 #endif /* CTSFLOW */
6115 #ifndef RTSFLOW
6116 #define RTSFLOW 0040000
6117 debug(F101,"tthflow SCO defining RTSFLOW","",RTSFLOW);
6118 #else
6119 debug(F101,"tthflow SCO RTSFLOW","",RTSFLOW);
6120 #endif /* RTSFLOW */
6121 #ifndef ORTSFL
6122 #define ORTSFL 0100000
6123 debug(F101,"tthflow SCO defining ORTSFL","",ORTSFL);
6124 #else
6125 debug(F101,"tthflow SCO ORTSFL","",ORTSFL);
6126 #endif /* ORTSFL */
6127
6128 if (x != -1) {
6129 if (status) { /* Turn it ON */
6130 temp.c_cflag |= RTSFLOW|CTSFLOW;
6131 attrs->c_cflag |= RTSFLOW|CTSFLOW;
6132 #ifdef ORTSFL
6133 temp.c_cflag &= ~ORTSFL;
6134 attrs->c_cflag &= ~ORTSFL;
6135 #endif /* ORTSFL */
6136 temp.c_iflag &= ~(IXON|IXOFF|IXANY);
6137 attrs->c_iflag &= ~(IXON|IXOFF|IXANY);
6138 } else { /* Turn it OFF */
6139 #ifdef ORTSFL
6140 temp.c_cflag &= ~(RTSFLOW|CTSFLOW|ORTSFL);
6141 attrs->c_cflag &= ~(RTSFLOW|CTSFLOW|ORTSFL);
6142 #else /* ORTSFL */
6143 temp.c_cflag &= ~(RTSFLOW|CTSFLOW);
6144 attrs->c_cflag &= ~(RTSFLOW|CTSFLOW);
6145 #endif /* ORTSFL */
6146 }
6147 #ifdef POSIX
6148 x = tcsetattr(ttyfd, TCSADRAIN, &temp);
6149 #else
6150 x = ioctl(ttyfd, TCSETA, &temp);
6151 #endif /* POSIX */
6152 debug(F101,"tthflow SCO set modes","",x);
6153 }
6154 #else /* Not SCO UNIX */
6155 #ifdef NETCMD
6156 if (ttpipe) return(0);
6157 #endif /* NETCMD */
6158 #ifdef NETPTY
6159 if (ttpty) return(0);
6160 #endif /* NETPTY */
6161 if (!status) { /* Turn it OFF */
6162 #ifdef RTSXOFF
6163 debug(F100,"tthflow ATTSV RTS/CTS OFF","",0);
6164 rctsx.x_hflag &= ~(RTSXOFF|CTSXON);
6165 #ifdef TCSETX
6166 x = ioctl(ttyfd,TCSETX,&rctsx);
6167 debug(F101,"tthflow ATTSV TCSETX OFF","",x);
6168 #else
6169 x = -1
6170 debug(F100,"tthflow TCSETX not defined","",0);
6171 #endif /* TCSETX */
6172 #else
6173 debug(F100,"tthflow ATTSV RTSXOFF not defined","",0);
6174 #endif /* RTSXOFF */
6175 #ifdef DTRXOFF
6176 debug(F100,"tthflow ATTSV DTR/CD OFF","",0);
6177 rctsx.x_hflag &= ~(DTRXOFF|CDXON);
6178 x = ioctl(ttyfd,TCSETX,&rctsx);
6179 debug(F101,"tthflow ATTSV DTRXOFF OFF","",x);
6180 #else
6181 debug(F100,"tthflow ATTSV DTRXOFF not defined","",0);
6182 #endif /* DTRXOFF */
6183 } else { /* Turn it ON. */
6184 if (flow == FLO_RTSC) { /* RTS/CTS Flow control... */
6185 debug(F100,"tthflow ATTSV RTS/CTS ON","",0);
6186 #ifdef RTSXOFF
6187 /* This is the preferred way, according to SVID3 */
6188 #ifdef TCGETX
6189 x = ioctl(ttyfd,TCGETX,&rctsx);
6190 debug(F101,"tthflow TCGETX","",x);
6191 if (x > -1) {
6192 rctsx.x_hflag |= RTSXOFF | CTSXON;
6193 x = ioctl(ttyfd,TCSETX,&rctsx);
6194 debug(F100,"tthflow ATTSV ioctl","",x);
6195 }
6196 #else
6197 debug(F100,"tthflow TCGETX not defined","",0);
6198 x = -1
6199 #endif /* TCGETX */
6200 #else
6201 debug(F100,"tthflow RTSXOFF not defined","",0);
6202 x = -1;
6203 #endif /* RTSXOFF */
6204 } else if (flow == FLO_DTRC) { /* DTR/CD Flow control... */
6205 debug(F100,"tthflow ATTSV DTR/CD ON","",0);
6206 #ifdef DTRXOFF
6207 /* This is straight out of SVID R4 */
6208 if (ioctl(ttyfd,TCGETX,&rctsx) > -1) {
6209 rctsx.x_hflag &= ~(DTRXOFF|CDXON);
6210 x = ioctl(ttyfd,TCSETX,&rctsx);
6211 }
6212 #else
6213 debug(F100,"tthflow ATTSV DTRXOFF not defined","",0);
6214 x = -1;
6215 #endif /* DTRXOFF */
6216 }
6217 }
6218 #endif /* CK_SCOUNIX */
6219
6220 #else /* not System V... */
6221
6222 #ifdef CK_DTRCTS
6223 #ifdef LDODTR
6224 #ifdef LDOCTS
6225 #ifdef NETCMD
6226 if (ttpipe) return(0);
6227 #endif /* NETCMD */
6228 #ifdef NETPTY
6229 if (ttpty) return(0);
6230 #endif /* NETPTY */
6231 x = LDODTR | LDOCTS; /* Found only on UTEK? */
6232 if (flow == FLO_DTRT && status) { /* Use hardware flow control */
6233 if (lmodef) {
6234 x = ioctl(ttyfd,TIOCLBIS,&x);
6235 if (x < 0) {
6236 debug(F100,"hardflow TIOCLBIS error","",0);
6237 } else {
6238 lmodef++;
6239 debug(F100,"hardflow TIOCLBIS ok","",0);
6240 }
6241 }
6242 } else {
6243 if (lmodef) {
6244 x = ioctl(ttyfd,TIOCLBIC,&x);
6245 if (x < 0) {
6246 debug(F100,"hardflow TIOCLBIC error","",0);
6247 } else {
6248 lmodef++;
6249 debug(F100,"hardflow TIOCLBIC ok","",0);
6250 }
6251 }
6252 }
6253 #endif /* LDODTR */
6254 #endif /* LDOCTS */
6255 #endif /* CK_DTRCTS */
6256 #endif /* ATTSV */
6257 #endif /* AIXRS */
6258 #endif /* SUNOS4 */
6259 #endif /* QNX */
6260 #endif /* POSIX_CRTSCTS */
6261 #endif /* SUNOS41 */
6262
6263 #else /* OXOS */
6264
6265 struct termios temp; /* Olivetti X/OS ... */
6266
6267 #ifdef NETCMD
6268 if (ttpipe) return(0);
6269 #endif /* NETCMD */
6270 #ifdef NETPTY
6271 if (ttpty) return(0);
6272 #endif /* NETPTY */
6273 x = ioctl(ttyfd,TCGETS,&temp);
6274 if (x == 0) {
6275 temp.c_cflag &= ~(CRTSCTS|CDTRCTS|CBRKFLOW|CDTRDSR|CRTSDSR);
6276 if (status) {
6277 switch (flow) {
6278 case FLO_RTSC: temp.c_cflag |= CRTSCTS; /* RTS/CTS (hard) */
6279 break;
6280 case FLO_DTRT: temp.c_cflag |= CDTRCTS; /* DTR/CTS (hard) */
6281 break;
6282 }
6283 }
6284 x = ioctl(ttyfd,TCSETS,&temp);
6285 }
6286 #endif /* OXOS */
6287 return(x);
6288
6289 #endif /* Plan9 */
6290 }
6291
6292 /* T T P K T -- Condition the communication line for packets */
6293 /* or for modem dialing */
6294
6295 /*
6296 If called with speed > -1, also set the speed.
6297 Returns 0 on success, -1 on failure.
6298
6299 NOTE: the "xflow" parameter is supposed to be the currently selected
6300 type of flow control, but for historical reasons, this parameter is also
6301 used to indicate that we are dialing. Therefore, when the true flow
6302 control setting is needed, we access the external variable "flow", rather
6303 than trusting our "xflow" argument.
6304 */
6305 int
6306 #ifdef CK_ANSIC
ttpkt(long speed,int xflow,int parity)6307 ttpkt(long speed, int xflow, int parity)
6308 #else
6309 ttpkt(speed,xflow,parity) long speed; int xflow, parity;
6310 #endif /* CK_ANSIC */
6311 /* ttpkt */ {
6312 #ifndef NOLOCAL
6313 int s2;
6314 int s = -1;
6315 #endif /* NOLOCAL */
6316 int x;
6317 extern int flow; /* REAL flow-control setting */
6318
6319 if (ttyfd < 0) return(-1); /* Not open. */
6320
6321 debug(F101,"ttpkt parity","",parity);
6322 debug(F101,"ttpkt xflow","",xflow);
6323 debug(F101,"ttpkt speed","",(int) speed);
6324
6325 ttprty = parity; /* Let other tt functions see these. */
6326 ttspeed = speed; /* Make global copy for this module */
6327 ttpmsk = ttprty ? 0177 : 0377; /* Parity stripping mask */
6328 #ifdef PARSENSE
6329 needpchk = ttprty ? 0 : 1; /* Parity check needed? */
6330 #else
6331 needpchk = 0;
6332 #endif /* PARSENSE */
6333
6334 debug(F101,"ttpkt ttpmsk","",ttpmsk);
6335 debug(F101,"ttpkt netconn","",netconn);
6336
6337 #ifdef NETCONN /* No mode-changing for telnet */
6338 if (netconn) {
6339 #ifdef TCPSOCKET
6340 #ifdef TCP_NODELAY
6341 if (ttnet == NET_TCPB) { /* But turn off Nagle */
6342 extern int tcp_nodelay;
6343 nodelay_sav = tcp_nodelay;
6344 no_delay(ttyfd,1);
6345 }
6346 #endif /* TCP_NODELAY */
6347 #ifdef TN_COMPORT
6348 if (istncomport()) {
6349 int rc = -1;
6350 if (tvtflg == 0 && speed == ttspeed && flow == ttflow
6351 /* && ttcarr == curcarr */ ) {
6352 debug(F100,"ttpkt modes already set, skipping...","",0);
6353 return(0); /* Already been called. */
6354 }
6355 if (flow != ttflow) {
6356 if ((rc = tnsetflow(flow)) < 0)
6357 return(rc);
6358 ttflow = flow;
6359 }
6360 if (speed != ttspeed) {
6361 if (speed <= 0)
6362 speed = tnc_get_baud();
6363 else if ((rc = tnc_set_baud(speed)) < 0)
6364 return(rc);
6365 ttspeed = speed;
6366 }
6367 tnc_set_datasize(8);
6368 tnc_set_stopsize(stopbits);
6369
6370 #ifdef HWPARITY
6371 if (hwparity) {
6372 switch (hwparity) {
6373 case 'e': /* Even */
6374 debug(F100,"ttres 8 bits + even parity","",0);
6375 tnc_set_parity(3);
6376 break;
6377 case 'o': /* Odd */
6378 debug(F100,"ttres 8 bits + odd parity","",0);
6379 tnc_set_parity(2);
6380 break;
6381 case 'm': /* Mark */
6382 debug(F100,"ttres 8 bits + invalid parity: mark","",0);
6383 tnc_set_parity(4);
6384 break;
6385 case 's': /* Space */
6386 debug(F100,"ttres 8 bits + invalid parity: space","",0);
6387 tnc_set_parity(5);
6388 break;
6389 }
6390 } else
6391 #endif /* HWPARITY */
6392 {
6393 tnc_set_parity(1); /* None */
6394 }
6395 tvtflg = 0;
6396 return(0);
6397 }
6398 #endif /* TN_COMPORT */
6399 #endif /* TCPSOCKET */
6400 tvtflg = 0;
6401 return(0);
6402 }
6403 #endif /* NETCONN */
6404 #ifdef NETCMD
6405 if (ttpipe) return(0);
6406 #endif /* NETCMD */
6407 #ifdef NETPTY
6408 if (ttpty) return(0);
6409 #endif /* NETPTY */
6410
6411 #ifndef Plan9
6412 if (ttfdflg && !isatty(ttyfd)) return(0);
6413 #endif /* Plan9 */
6414
6415 #ifdef COHERENT
6416 #define SVORPOSIX
6417 #endif /* COHERENT */
6418
6419 #ifndef SVORPOSIX /* Berkeley, V7, etc. */
6420 #ifdef LPASS8
6421 /*
6422 For some reason, with BSD terminal drivers, you can't set FLOW to XON/XOFF
6423 after having previously set it to NONE without closing and reopening the
6424 device. Unless there's something I overlooked below...
6425 */
6426 if (ttflow == FLO_NONE && flow == FLO_XONX && xlocal == 0) {
6427 debug(F101,"ttpkt executing horrible flow kludge","",0);
6428 ttclos(0); /* Close it */
6429 x = 0;
6430 ttopen(ttnmsv,&x,ttmdm,0); /* Open it again */
6431 }
6432 #endif /* LPASS8 */
6433 #endif /* SVORPOSIX */
6434
6435 #ifdef COHERENT /* This must be vestigial since we */
6436 #undef SVORPOSIX /* reverse it a few lines below... */
6437 #endif /* COHERENT */
6438
6439 if (xflow != FLO_DIAL && xflow != FLO_DIAX)
6440 ttflow = xflow; /* Now make this available too. */
6441
6442 #ifndef NOLOCAL
6443 if (xlocal) {
6444 s2 = (int) (speed / 10L); /* Convert bps to cps */
6445 debug(F101,"ttpkt calling ttsspd","",s2);
6446 s = ttsspd(s2); /* Check and set the speed */
6447 debug(F101,"ttpkt ttsspd result","",s);
6448 carrctl(&ttraw, xflow != FLO_DIAL /* Carrier control */
6449 && (ttcarr == CAR_ON || (ttcarr == CAR_AUT && ttmdm != 0)));
6450 tvtflg = 0; /* So ttvt() will work next time */
6451 }
6452 #endif /* NOLOCAL */
6453
6454 #ifdef COHERENT
6455 #define SVORPOSIX
6456 #endif /* COHERENT */
6457
6458 #ifndef SVORPOSIX /* BSD section */
6459 if (flow == FLO_RTSC || /* Hardware flow control */
6460 flow == FLO_DTRC ||
6461 flow == FLO_DTRT) {
6462 tthflow(flow, 1, &ttraw);
6463 debug(F100,"ttpkt hard flow, TANDEM off, RAW on","",0);
6464 ttraw.sg_flags &= ~TANDEM; /* Turn off software flow control */
6465 ttraw.sg_flags |= RAW; /* Enter raw mode */
6466 } else if (flow == FLO_NONE) { /* No flow control */
6467 debug(F100,"ttpkt no flow, TANDEM off, RAW on","",0);
6468 ttraw.sg_flags &= ~TANDEM; /* Turn off software flow control */
6469 tthflow(flow, 0, &ttraw); /* Turn off any hardware f/c too */
6470 ttraw.sg_flags |= RAW; /* Enter raw mode */
6471 } else if (flow == FLO_KEEP) { /* Keep device's original setting */
6472 debug(F100,"ttpkt keeping original TANDEM","",0);
6473 ttraw.sg_flags &= ~TANDEM;
6474 ttraw.sg_flags |= (ttold.sg_flags & TANDEM);
6475 /* NOTE: We should also handle hardware flow control here! */
6476 }
6477
6478 /* SET FLOW XON/XOFF is in effect, or SET FLOW KEEP resulted in Xon/Xoff */
6479
6480 if ((flow == FLO_XONX) || (ttraw.sg_flags & TANDEM)) {
6481 debug(F100,"ttpkt turning on TANDEM","",0);
6482 ttraw.sg_flags |= TANDEM; /* So ask for it. */
6483
6484 #ifdef LPASS8 /* Can pass 8-bit data through? */
6485 /* If the LPASS8 local mode is available, then flow control can always */
6486 /* be used, even if parity is none and we are transferring 8-bit data. */
6487 /* But we only need to do all this if Xon/Xoff is requested. */
6488 /* BUT... this tends not to work through IP or LAT connections, terminal */
6489 /* servers, telnet, rlogin, etc, so it is currently disabled. */
6490 x = LPASS8; /* If LPASS8 defined, then */
6491 debug(F100,"ttpkt executing LPASS8 code","",0);
6492 if (lmodef) { /* TIOCLBIS must be too. */
6493 x = ioctl(ttyfd,TIOCLBIS,&x); /* Try to set LPASS8. */
6494 if (x < 0) {
6495 debug(F100,"ttpkt TIOCLBIS error","",0);
6496 } else {
6497 lmodef++;
6498 debug(F100,"ttpkt TIOCLBIS ok","",0);
6499 }
6500 }
6501 /*
6502 But if we use LPASS8 mode, we must explicitly turn off
6503 terminal interrupts of all kinds.
6504 */
6505 #ifdef TIOCGETC /* Not rawmode, */
6506 if (tcharf && (xlocal == 0)) { /* must turn off */
6507 tchnoi.t_intrc = -1; /* interrupt character */
6508 tchnoi.t_quitc = -1; /* and quit character. */
6509 tchnoi.t_startc = 17; /* Make sure xon */
6510 tchnoi.t_stopc = 19; /* and xoff not ignored. */
6511 #ifndef NOBRKC
6512 tchnoi.t_eofc = -1; /* eof character. */
6513 tchnoi.t_brkc = -1; /* brk character. */
6514 #endif /* NOBRKC */
6515 if (ioctl(ttyfd,TIOCSETC,&tchnoi) < 0) {
6516 debug(F100,"ttpkt TIOCSETC failed","",0);
6517 } else {
6518 tcharf = 1;
6519 debug(F100,"ttpkt TIOCSETC ok","",0);
6520 }
6521 #ifdef COMMENT
6522 /* only for paranoid debugging */
6523 if (tcharf) {
6524 struct tchars foo;
6525 char tchbuf[100];
6526 ioctl(0,TIOCGETC,&foo);
6527 sprintf(tchbuf,
6528 "intr=%d,quit=%d, start=%d, stop=%d, eof=%d, brk=%d",
6529 foo.t_intrc, foo.t_quitc, foo.t_startc,
6530 foo.t_stopc, foo.t_eofc, foo.t_brkc);
6531 debug(F110,"ttpkt chars",tchbuf,0);
6532 }
6533 #endif /* COMMENT */
6534 }
6535 ttraw.sg_flags |= CBREAK; /* Needed for unknown reason */
6536 #endif /* TIOCGETC */
6537
6538 /* Prevent suspend during packet mode */
6539 #ifdef TIOCGLTC /* Not rawmode, */
6540 if (ltcharf && (xlocal == 0)) { /* must turn off */
6541 ltchnoi.t_suspc = -1; /* suspend character */
6542 ltchnoi.t_dsuspc = -1; /* and delayed suspend character */
6543 if (ioctl(ttyfd,TIOCSLTC,&tchnoi) < 0) {
6544 debug(F100,"ttpkt TIOCSLTC failed","",0);
6545 } else {
6546 ltcharf = 1;
6547 debug(F100,"ttpkt TIOCSLTC ok","",0);
6548 }
6549 }
6550 #endif /* TIOCGLTC */
6551
6552 #else /* LPASS8 not defined */
6553
6554 /* Previously, BSD-based implementations always */
6555 /* used rawmode for packets. Now, we use rawmode only if parity is NONE. */
6556 /* This allows the flow control requested above to actually work, but only */
6557 /* if the user asks for parity (which also means they get 8th-bit quoting). */
6558
6559 if (parity) { /* If parity, */
6560 ttraw.sg_flags &= ~RAW; /* use cooked mode */
6561 #ifdef COMMENT
6562 /* WHY??? */
6563 if (xlocal)
6564 #endif /* COMMENT */
6565 ttraw.sg_flags |= CBREAK;
6566 debug(F101,"ttpkt cooked, cbreak, parity","",parity);
6567 #ifdef TIOCGETC /* Not rawmode, */
6568 if (tcharf && (xlocal == 0)) { /* must turn off */
6569 tchnoi.t_intrc = -1; /* interrupt character */
6570 tchnoi.t_quitc = -1; /* and quit character. */
6571 tchnoi.t_startc = 17; /* Make sure xon */
6572 tchnoi.t_stopc = 19; /* and xoff not ignored. */
6573 #ifndef NOBRKC
6574 tchnoi.t_eofc = -1; /* eof character. */
6575 tchnoi.t_brkc = -1; /* brk character. */
6576 #endif /* NOBRKC */
6577 if (ioctl(ttyfd,TIOCSETC,&tchnoi) < 0) {
6578 debug(F100,"ttpkt TIOCSETC failed","",0);
6579 } else {
6580 tcharf = 1;
6581 debug(F100,"ttpkt TIOCSETC ok","",0);
6582 }
6583 }
6584 #endif /* TIOCGETC */
6585 #ifdef TIOCGLTC /* Not rawmode, */
6586 /* Prevent suspend during packet mode */
6587 if (ltcharf && (xlocal == 0)) { /* must turn off */
6588 ltchnoi.t_suspc = -1; /* suspend character */
6589 ltchnoi.t_dsuspc = -1; /* and delayed suspend character */
6590 if (ioctl(ttyfd,TIOCSLTC,&tchnoi) < 0) {
6591 debug(F100,"ttpkt TIOCSLTC failed","",0);
6592 } else {
6593 ltcharf = 1;
6594 debug(F100,"ttpkt TIOCSLTC ok","",0);
6595 }
6596 }
6597 #endif /* TIOCGLTC */
6598 } else { /* If no parity, */
6599 ttraw.sg_flags |= RAW; /* must use 8-bit raw mode. */
6600 debug(F101,"ttpkt setting rawmode, parity","",parity);
6601 }
6602 #endif /* LPASS8 */
6603 } /* End of Xon/Xoff section */
6604
6605 /* Don't echo, don't map CR to CRLF on output, don't fool with case */
6606 #ifdef LCASE
6607 ttraw.sg_flags &= ~(ECHO|CRMOD|LCASE);
6608 #else
6609 ttraw.sg_flags &= ~(ECHO|CRMOD);
6610 #endif /* LCASE */
6611
6612 #ifdef TOWER1
6613 ttraw.sg_flags &= ~ANYP; /* Must set this on old Towers */
6614 #endif /* TOWER1 */
6615
6616 #ifdef BELLV10
6617 if (ioctl(ttyfd,TIOCSETP,&ttraw) < 0) /* Set the new modes. */
6618 return(-1);
6619 #else
6620 errno = 0;
6621 if (stty(ttyfd,&ttraw) < 0) { /* Set the new modes. */
6622 debug(F101,"ttpkt stty failed","",errno);
6623 return(-1);
6624 }
6625 #endif /* BELLV10 */
6626 debug(F100,"ttpkt stty ok","",0);
6627
6628 #ifdef sony_news
6629 x = xlocal ? km_ext : km_con; /* Put line in ASCII mode. */
6630 if (x != -1) { /* Make sure we know original modes. */
6631 x &= ~KM_TTYPE;
6632 x |= KM_ASCII;
6633 if (ioctl(ttyfd,TIOCKSET, &x) < 0) {
6634 perror("ttpkt can't set ASCII mode");
6635 debug(F101,"ttpkt error setting ASCII mode","",x);
6636 return(-1);
6637 }
6638 }
6639 debug(F100,"ttpkt set ASCII mode ok","",0);
6640 #endif /* sony_news */
6641
6642 if (xlocal == 0) { /* Turn this off so we can read */
6643 signal(SIGINT,SIG_IGN); /* Ctrl-C chars typed at console */
6644 sigint_ign = 1;
6645 }
6646 tvtflg = 0; /* So ttvt() will work next time */
6647 debug(F100,"ttpkt success","",0);
6648 return(0);
6649
6650 #endif /* Not ATTSV or POSIX */
6651
6652 /* AT&T UNIX and POSIX */
6653
6654 #ifdef COHERENT
6655 #define SVORPOSIX
6656 #endif /* COHERENT */
6657
6658 #ifdef SVORPOSIX
6659 if (flow == FLO_XONX) { /* Xon/Xoff */
6660 ttraw.c_iflag |= (IXON|IXOFF);
6661 tthflow(flow, 0, &ttraw);
6662 } else if (flow == FLO_NONE) { /* None */
6663 /* NOTE: We should also turn off hardware flow control here! */
6664 ttraw.c_iflag &= ~(IXON|IXOFF);
6665 tthflow(flow, 0, &ttraw);
6666 } else if (flow == FLO_KEEP) { /* Keep */
6667 ttraw.c_iflag &= ~(IXON|IXOFF); /* Turn off Xon/Xoff flags */
6668 ttraw.c_iflag |= (ttold.c_iflag & (IXON|IXOFF)); /* OR in old ones */
6669 /* NOTE: We should also handle hardware flow control here! */
6670 #ifdef POSIX_CRTSCTS
6671 /* In Linux case, we do this, which is unlikely to be portable */
6672 ttraw.c_cflag &= ~CRTSCTS; /* Turn off RTS/CTS flag */
6673 ttraw.c_cflag |= (ttold.c_cflag & CRTSCTS); /* OR in old one */
6674 #endif /* POSIX_CRTSCTS */
6675 } else if (flow == FLO_RTSC || /* Hardware */
6676 flow == FLO_DTRC ||
6677 flow == FLO_DTRT) {
6678 ttraw.c_iflag &= ~(IXON|IXOFF); /* (190) */
6679 tthflow(flow, 1, &ttraw);
6680 }
6681 ttraw.c_lflag &= ~(ICANON|ECHO);
6682 ttraw.c_lflag &= ~ISIG; /* Do NOT check for interrupt chars */
6683
6684 #ifndef OXOS
6685 #ifdef QNX
6686 if (flow != FLO_RTSC && flow != FLO_DTRC && flow != FLO_DTRT)
6687 #endif /* QNX */
6688 #ifndef COHERENT
6689 ttraw.c_lflag &= ~IEXTEN; /* Turn off ^O/^V processing */
6690 #endif /* COHERENT */
6691 #else /* OXOS */
6692 ttraw.c_cc[VDISCARD] = ttraw.c_cc[VLNEXT] = CDISABLE;
6693 #endif /* OXOS */
6694 ttraw.c_lflag |= NOFLSH; /* Don't flush */
6695 ttraw.c_iflag |= IGNPAR; /* Ignore parity errors */
6696 #ifdef ATTSV
6697 #ifdef BSD44
6698 ttraw.c_iflag &= ~(IGNBRK|INLCR|IGNCR|ICRNL|INPCK|ISTRIP|IXANY);
6699 #else
6700 ttraw.c_iflag &= ~(IGNBRK|INLCR|IGNCR|ICRNL|IUCLC|INPCK|ISTRIP|IXANY);
6701 #endif /* BSD44 */
6702 #else /* POSIX */
6703 ttraw.c_iflag &= ~(IGNBRK|INLCR|IGNCR|ICRNL|INPCK|ISTRIP);
6704 #endif /* ATTSV */
6705 ttraw.c_oflag &= ~OPOST;
6706 ttraw.c_cflag &= ~(CSIZE);
6707 ttraw.c_cflag |= (CS8|CREAD|HUPCL);
6708
6709 #ifdef CSTOPB
6710 if (xlocal) {
6711 if (stopbits == 2) {
6712 ttraw.c_cflag |= CSTOPB; /* 2 stop bits */
6713 debug(F100,"ttpkt 2 stopbits","",0);
6714 } else if (stopbits == 1) {
6715 ttraw.c_cflag &= ~(CSTOPB); /* 1 stop bit */
6716 debug(F100,"ttpkt 1 stopbit","",0);
6717 }
6718 }
6719 #endif /* CSTOPB */
6720
6721 #ifdef HWPARITY
6722 if (hwparity && xlocal) { /* Hardware parity */
6723 ttraw.c_cflag |= PARENB; /* Enable parity */
6724 #ifdef COMMENT
6725 /* Uncomment this only if needed -- I don't think it is */
6726 ttraw.c_cflag &= ~(CSIZE); /* Clear out character-size mask */
6727 ttraw.c_cflag |= CS8; /* And set it to 8 */
6728 #endif /* COMMENT */
6729 #ifdef IGNPAR
6730 ttraw.c_iflag |= IGNPAR; /* Don't discard incoming bytes */
6731 debug(F100,"ttpkt IGNPAR","",0); /* that have parity errors */
6732 #endif /* IGNPAR */
6733 switch (hwparity) {
6734 case 'e': /* Even */
6735 ttraw.c_cflag &= ~(PARODD);
6736 debug(F100,"ttpkt 8 bits + even parity","",0);
6737 break;
6738 case 'o': /* Odd */
6739 ttraw.c_cflag |= PARODD;
6740 debug(F100,"ttpkt 8 bits + odd parity","",0);
6741 break;
6742 case 'm': /* Mark */
6743 case 's': /* Space */
6744 /* PAREXT is mentioned in SVID but the details are not given. */
6745 /* PAREXT is not included in POSIX ISO/IEC 9945-1. */
6746 debug(F100,"ttpkt 8 bits + invalid parity","",0);
6747 break;
6748 }
6749 } else { /* We handle parity ourselves */
6750 #endif /* HWPARITY */
6751 ttraw.c_cflag &= ~(PARENB); /* Don't enable parity */
6752 #ifdef HWPARITY
6753 }
6754 #endif /* HWPARITY */
6755
6756 #ifdef IX370
6757 ttraw.c_cc[4] = 48; /* So Series/1 doesn't interrupt on every char */
6758 ttraw.c_cc[5] = 1;
6759 #else
6760 #ifndef VEOF /* for DGUX this is VEOF, not VMIN */
6761 ttraw.c_cc[4] = 1; /* [VMIN] return max of this many characters or */
6762 #else
6763 #ifndef OXOS
6764 #ifdef VMIN
6765 ttraw.c_cc[VMIN] = 1;
6766 #endif /* VMIN */
6767 #else /* OXOS */
6768 ttraw.c_min = 1;
6769 #endif /* OXOS */
6770 #endif /* VEOF */
6771 #ifndef VEOL /* for DGUX this is VEOL, not VTIME */
6772 ttraw.c_cc[5] = 0; /* [VTIME] when this many secs/10 expire w/no input */
6773 #else
6774 #ifndef OXOS
6775 #ifdef VTIME
6776 ttraw.c_cc[VTIME] = 0;
6777 #endif /* VTIME */
6778 #else /* OXOS */
6779 ttraw.c_time = 0;
6780 #endif /* OXOS */
6781 #endif /* VEOL */
6782 #endif /* IX370 */
6783
6784 #ifdef VINTR /* Turn off interrupt character */
6785 if (xlocal == 0) /* so ^C^C can break us out of */
6786 ttraw.c_cc[VINTR] = 0; /* packet mode. */
6787 #endif /* VINTR */
6788
6789 #ifdef Plan9
6790 if (p9ttyparity('n') < 0)
6791 return -1;
6792 #else
6793 #ifdef BSD44ORPOSIX
6794 errno = 0;
6795 #ifdef BEOSORBEBOX
6796 ttraw.c_cc[VMIN] = 0; /* DR7 can only poll. */
6797 #endif /* BEOSORBEBOX */
6798
6799 #define TESTING234
6800 #ifdef TESTING234
6801 if (1) {
6802 debug(F100,"ttpkt TESTING234 rawmode","",0);
6803
6804 /* iflags */
6805 ttraw.c_iflag &= ~(PARMRK|ISTRIP|BRKINT|INLCR|IGNCR|ICRNL);
6806 ttraw.c_iflag &= ~(INPCK|IGNPAR|IXON|IXOFF);
6807 ttraw.c_iflag |= IGNBRK;
6808 #ifdef IMAXBEL
6809 ttraw.c_iflag &= ~IMAXBEL;
6810 #endif /* IMAXBEL */
6811 #ifdef IXANY
6812 ttraw.c_iflag &= ~IXANY;
6813 #endif /* IXANY */
6814 #ifdef IUCLC
6815 ttraw.c_iflag &= ~IUCLC;
6816 #endif /* IUCLC */
6817
6818 /* oflags */
6819 ttraw.c_oflag &= ~OPOST;
6820 #ifdef OXTABS
6821 ttraw.c_oflag &= ~OXTABS;
6822 #endif /* OXTABS */
6823 #ifdef ONOCR
6824 ttraw.c_oflag &= ~ONOCR;
6825 #endif /* ONOCR */
6826 #ifdef ONLRET
6827 ttraw.c_oflag &= ~ONLRET;
6828 #endif /* ONLRET */
6829 #ifdef ONLCR
6830 ttraw.c_oflag &= ~ONLCR;
6831 #endif /* ONLCR */
6832
6833 /* lflags */
6834 ttraw.c_lflag &= ~ECHO;
6835 #ifdef ECHOE
6836 ttraw.c_lflag &= ~ECHOE;
6837 #endif /* ECHOE */
6838 #ifdef ECHONL
6839 ttraw.c_lflag &= ~ECHONL;
6840 #endif /* ECHONL */
6841 #ifdef ECHOPRT
6842 ttraw.c_lflag &= ~ECHOPRT;
6843 #endif /* ECHOPRT */
6844 #ifdef ECHOKE
6845 ttraw.c_lflag &= ~ECHOKE;
6846 #endif /* ECHOKE */
6847 #ifdef ECHOCTL
6848 ttraw.c_lflag &= ~ECHOCTL;
6849 #endif /* ECHOCTL */
6850 #ifdef ALTWERASE
6851 ttraw.c_lflag &= ~ALTWERASE;
6852 #endif /* ALTWERASE */
6853 #ifdef EXTPROC
6854 ttraw.c_lflag &= ~EXTPROC;
6855 #endif /* EXTPROC */
6856 ttraw.c_lflag &= ~(ICANON|ISIG|IEXTEN|TOSTOP|FLUSHO|PENDIN);
6857 #ifdef NOKERNINFO
6858 ttraw.c_lflag |= NOKERNINFO;
6859 #endif /* NOKERNINFO */
6860 /* ttraw.c_lflag |= NOFLSH; */
6861 ttraw.c_lflag &= ~NOFLSH;
6862
6863 /* cflags */
6864 ttraw.c_cflag &= ~(CSIZE|PARENB|PARODD);
6865 ttraw.c_cflag |= CS8|CREAD;
6866 #ifdef VMIN
6867 ttraw.c_cc[VMIN] = 1; /* Supposedly needed for AIX */
6868 #endif /* VMIN */
6869
6870 }
6871 #endif /* TESTING234 */
6872
6873 debug(F100,"ttpkt calling tcsetattr(TCSETAW)","",0);
6874 x = tcsetattr(ttyfd,TCSADRAIN,&ttraw);
6875 debug(F101,"ttpkt BSD44ORPOSIX tcsetattr","",x);
6876 if (x < 0) {
6877 debug(F101,"ttpkt BSD44ORPOSIX tcsetattr errno","",errno);
6878 return(-1);
6879 }
6880 #else /* BSD44ORPOSIX */
6881 x = ioctl(ttyfd,TCSETAW,&ttraw);
6882 debug(F101,"ttpkt ATTSV ioctl TCSETAW","",x);
6883 if (x < 0) { /* set new modes . */
6884 debug(F101,"ttpkt ATTSV ioctl TCSETAW errno","",errno);
6885 return(-1);
6886 }
6887 #endif /* BSD44ORPOSIX */
6888 #endif /* Plan9 */
6889 tvtflg = 0;
6890 debug(F100,"ttpkt ok","",0);
6891 return(0);
6892 #endif /* ATTSV */
6893
6894 #ifdef COHERENT
6895 #undef SVORPOSIX
6896 #endif /* COHERENT */
6897
6898 }
6899
6900 /* T T S E T F L O W -- Set flow control immediately. */
6901
6902 #ifdef COHERENT
6903 #define SVORPOSIX
6904 #endif /* COHERENT */
6905
6906 int
ttsetflow(flow)6907 ttsetflow(flow) int flow; {
6908 if (ttyfd < 0) /* A channel must be open */
6909 return(-1);
6910
6911 debug(F101,"ttsetflow flow","",flow);
6912
6913 #ifdef TN_COMPORT
6914 if (netconn && istncomport()) {
6915 debug(F101,"ttsetflow net modem","",ttmdm);
6916 return(tnsetflow(flow));
6917 }
6918 #endif /* TN_COMPORT */
6919 #ifdef NETCMD
6920 if (ttpipe) return(0);
6921 #endif /* NETCMD */
6922 #ifdef NETPTY
6923 if (ttpty) return(0);
6924 #endif /* NETPTY */
6925
6926 #ifdef COMMENT
6927 /* This seems to hurt... */
6928 if (flow == FLO_KEEP)
6929 return(0);
6930 #endif /* COMMENT */
6931
6932 if (flow == FLO_RTSC || /* Hardware flow control... */
6933 flow == FLO_DTRC ||
6934 flow == FLO_DTRT) {
6935 tthflow(flow, 1, &ttraw);
6936 #ifndef SVORPOSIX
6937 ttraw.sg_flags &= ~TANDEM; /* Turn off software flow control */
6938 #else
6939 ttraw.c_iflag &= ~(IXON|IXOFF);
6940 #endif /* SVORPOSIX */
6941
6942 } else if (flow == FLO_XONX) { /* Xon/Xoff... */
6943
6944 #ifndef SVORPOSIX
6945 ttraw.sg_flags |= TANDEM;
6946 #else
6947 ttraw.c_iflag |= (IXON|IXOFF);
6948 #endif /* SVORPOSIX */
6949 tthflow(FLO_RTSC, 0, &ttraw); /* Turn off hardware flow control */
6950
6951 } else if (flow == FLO_NONE) { /* No flow control */
6952
6953 #ifndef SVORPOSIX
6954 ttraw.sg_flags &= ~TANDEM; /* Turn off software flow control */
6955 #else
6956 ttraw.c_iflag &= ~(IXON|IXOFF);
6957 #endif /* SVORPOSIX */
6958 tthflow(FLO_RTSC, 0, &ttraw); /* Turn off any hardware f/c too */
6959 }
6960
6961 /* Set the new modes... */
6962
6963 #ifndef SVORPOSIX /* BSD and friends */
6964 #ifdef BELLV10
6965 if (ioctl(ttyfd,TIOCSETP,&ttraw) < 0)
6966 return(-1);
6967 #else
6968 #ifndef MINIX2
6969 if (stty(ttyfd,&ttraw) < 0)
6970 return(-1);
6971 #endif /* MINIX2 */
6972 #endif /* BELLV10 */
6973 #else
6974 #ifdef BSD44ORPOSIX /* POSIX */
6975 if (tcsetattr(ttyfd,TCSADRAIN,&ttraw) < 0)
6976 return(-1);
6977 #else /* System V */
6978 if (ioctl(ttyfd,TCSETAW,&ttraw) < 0)
6979 return(-1);
6980 #endif /* BSD44ORPOSIX */
6981 #endif /* SVORPOSIX */
6982 return(0);
6983 }
6984 #ifdef COHERENT
6985 #undef SVORPOSIX
6986 #endif /* COHERENT */
6987
6988 /* T T V T -- Condition communication device for use as virtual terminal. */
6989
6990 int
6991 #ifdef CK_ANSIC
ttvt(long speed,int flow)6992 ttvt(long speed, int flow)
6993 #else
6994 ttvt(speed,flow) long speed; int flow;
6995 #endif /* CK_ANSIC */
6996 /* ttvt */ {
6997 int s, s2, x;
6998
6999 debug(F101,"ttvt ttyfd","",ttyfd);
7000 debug(F101,"ttvt tvtflg","",tvtflg);
7001 debug(F111,"ttvt speed",ckitoa(ttspeed),speed);
7002 debug(F111,"ttvt flow",ckitoa(ttflow),flow);
7003 debug(F111,"ttvt curcarr",ckitoa(ttcarr),curcarr);
7004
7005 /* Note: NetBSD and maybe other BSD44s have cfmakeraw() */
7006 /* Maybe it would be simpler to use it... */
7007
7008 ttpmsk = 0xff;
7009 #ifdef NOLOCAL
7010 return(conbin((char)escchr));
7011 #else
7012 if (ttyfd < 0) { /* Not open. */
7013 if (ttchk() < 0)
7014 return(-1);
7015 else /* But maybe something buffered. */
7016 return(0);
7017 }
7018 #ifdef NETCMD
7019 if (ttpipe) return(0);
7020 #endif /* NETCMD */
7021 #ifdef NETPTY
7022 if (ttpty) return(0);
7023 #endif /* NETPTY */
7024 #ifdef NETCONN
7025 if (netconn) {
7026 #ifdef TCPSOCKET
7027 #ifdef TCP_NODELAY
7028 {
7029 extern int tcp_nodelay;
7030 if (ttnet == NET_TCPB) {
7031 if (nodelay_sav > -1) {
7032 no_delay(ttyfd,nodelay_sav);
7033 nodelay_sav = -1;
7034 }
7035 }
7036 }
7037 #endif /* TCP_NODELAY */
7038 #ifdef TN_COMPORT
7039 if (istncomport()) {
7040 int rc = -1;
7041 if (tvtflg != 0 && speed == ttspeed && flow == ttflow
7042 /* && ttcarr == curcarr */ ) {
7043 debug(F100,"ttvt modes already set, skipping...","",0);
7044 return(0); /* Already been called. */
7045 }
7046 if (flow != ttflow) {
7047 if ((rc = tnsetflow(flow)) < 0)
7048 return(rc);
7049 ttflow = flow;
7050 }
7051 if (speed != ttspeed) {
7052 if (speed <= 0)
7053 speed = tnc_get_baud();
7054 else if ((rc = tnc_set_baud(speed)) < 0)
7055 return(rc);
7056 ttspeed = speed;
7057 }
7058 tnc_set_datasize(8);
7059 tnc_set_stopsize(stopbits);
7060
7061 #ifdef HWPARITY
7062 if (hwparity) {
7063 switch (hwparity) {
7064 case 'e': /* Even */
7065 debug(F100,"ttres 8 bits + even parity","",0);
7066 tnc_set_parity(3);
7067 break;
7068 case 'o': /* Odd */
7069 debug(F100,"ttres 8 bits + odd parity","",0);
7070 tnc_set_parity(2);
7071 break;
7072 case 'm': /* Mark */
7073 debug(F100,"ttres 8 bits + invalid parity: mark","",0);
7074 tnc_set_parity(4);
7075 break;
7076 case 's': /* Space */
7077 debug(F100,"ttres 8 bits + invalid parity: space","",0);
7078 tnc_set_parity(5);
7079 break;
7080 }
7081 } else
7082 #endif /* HWPARITY */
7083 {
7084 tnc_set_parity(1); /* None */
7085 }
7086 tvtflg = 1;
7087 return(0);
7088 }
7089 #endif /* TN_COMPORT */
7090 #endif /* TCPSOCKET */
7091 tvtflg = 1; /* Network connections... */
7092 debug(F100,"ttvt network connection, skipping...","",0);
7093 return(0); /* ... require no special setup */
7094 }
7095 #endif /* NETCONN */
7096
7097 if (tvtflg != 0 && speed == ttspeed && flow == ttflow
7098 /* && ttcarr == curcarr */ )
7099 {
7100 debug(F100,"ttvt modes already set, skipping...","",0);
7101 return(0); /* Already been called. */
7102 }
7103
7104 if (ttfdflg
7105 #ifndef Plan9
7106 && !isatty(ttyfd)
7107 #endif /* Plan9 */
7108 ) {
7109 debug(F100,"ttvt using external fd, skipping...","",0);
7110 return(0);
7111 }
7112
7113 debug(F100,"ttvt setting modes...","",0);
7114
7115 if (xlocal) { /* For external lines... */
7116 s2 = (int) (speed / 10L);
7117 s = ttsspd(s2); /* Check/set the speed */
7118 carrctl(&tttvt, flow != FLO_DIAL /* Do carrier control */
7119 && (ttcarr == CAR_ON || (ttcarr == CAR_AUT && ttmdm != 0)));
7120 } else
7121 s = s2 = -1;
7122
7123 #ifdef COHERENT
7124 #define SVORPOSIX
7125 #endif /* COHERENT */
7126
7127 #ifndef SVORPOSIX
7128 /* Berkeley, V7, etc */
7129 if (flow == FLO_RTSC || /* Hardware flow control */
7130 flow == FLO_DTRC ||
7131 flow == FLO_DTRT) {
7132 tthflow(flow, 1, &tttvt);
7133 debug(F100,"ttvt hard flow, TANDEM off","",0);
7134 tttvt.sg_flags &= ~TANDEM; /* Turn off software flow control */
7135 } else if (flow == FLO_XONX) { /* Xon/Xoff flow control */
7136 debug(F100,"ttvt TANDEM on","",0);
7137 tttvt.sg_flags |= TANDEM; /* Ask for it. */
7138 tthflow(flow, 0, &tttvt); /* Turn off hardware f/c */
7139 } else if (flow == FLO_NONE) {
7140 debug(F100,"ttvt no flow, TANDEM off, RAW on","",0);
7141 tttvt.sg_flags &= ~TANDEM; /* Turn off software flow control */
7142 tthflow(flow, 0, &tttvt); /* Turn off any hardware f/c too */
7143 tttvt.sg_flags |= RAW; /* Enter raw mode */
7144 } else if (flow == FLO_KEEP) { /* Keep device's original setting */
7145 debug(F100,"ttvt keeping original TANDEM","",0);
7146 tttvt.sg_flags &= ~TANDEM;
7147 tttvt.sg_flags |= (ttold.sg_flags & TANDEM);
7148 /* NOTE: We should also handle hardware flow control here! */
7149 }
7150 tttvt.sg_flags |= RAW; /* Raw mode in all cases */
7151 #ifdef TOWER1
7152 tttvt.sg_flags &= ~(ECHO|ANYP); /* No echo or parity */
7153 #else
7154 tttvt.sg_flags &= ~ECHO; /* No echo */
7155 #endif /* TOWER1 */
7156
7157 #ifdef BELLV10
7158 if (ioctl(ttyfd,TIOCSETP,&tttvt) < 0) /* Set the new modes */
7159 return(-1);
7160 #else
7161 if (stty(ttyfd,&tttvt) < 0) /* Set the new modes */
7162 return(-1);
7163 #endif /* BELLV10 */
7164
7165 #else /* It is ATTSV or POSIX */
7166
7167 if (flow == FLO_XONX) { /* Software flow control */
7168 tttvt.c_iflag |= (IXON|IXOFF); /* On if requested. */
7169 tthflow(flow, 0, &tttvt); /* Turn off hardware f/c */
7170 debug(F100,"ttvt SVORPOSIX flow XON/XOFF","",0);
7171 } else if (flow == FLO_NONE) { /* NONE */
7172 tttvt.c_iflag &= ~(IXON|IXOFF); /* Turn off Xon/Xoff */
7173 tthflow(flow, 0, &tttvt); /* Turn off hardware f/c */
7174 debug(F100,"ttvt SVORPOSIX flow NONE","",0);
7175 } else if (flow == FLO_KEEP) {
7176 tttvt.c_iflag &= ~(IXON|IXOFF); /* Turn off Xon/Xoff flags */
7177 tttvt.c_iflag |= (ttold.c_iflag & (IXON|IXOFF)); /* OR in old ones */
7178 #ifdef POSIX_CRTSCTS
7179 tttvt.c_cflag &= ~CRTSCTS; /* Turn off RTS/CTS flag */
7180 tttvt.c_cflag |= (ttold.c_cflag & CRTSCTS); /* OR in old one */
7181 #endif /* POSIX_CRTSCTS */
7182 debug(F100,"ttvt SVORPOSIX flow KEEP","",0);
7183 } else if (flow == FLO_RTSC || /* Hardware flow control */
7184 flow == FLO_DTRC ||
7185 flow == FLO_DTRT) {
7186 tttvt.c_iflag &= ~(IXON|IXOFF); /* (196) */
7187 tthflow(flow, 1, &tttvt);
7188 debug(F100,"ttvt SVORPOSIX flow HARD","",0);
7189 }
7190 #ifndef OXOS
7191 #ifdef COHERENT
7192 tttvt.c_lflag &= ~(ISIG|ICANON|ECHO);
7193 #else
7194 tttvt.c_lflag &= ~(ISIG|ICANON|ECHO|IEXTEN);
7195 #endif /* COHERENT */
7196 #ifdef QNX
7197 /* Needed for hwfc */
7198 if (flow == FLO_RTSC || flow == FLO_DTRC || flow == FLO_DTRT)
7199 tttvt.c_lflag |= IEXTEN;
7200 #endif /* QNX */
7201 #else /* OXOS */
7202 tttvt.c_lflag &= ~(ISIG|ICANON|ECHO);
7203 tttvt.c_cc[VDISCARD] = tttvt.c_cc[VLNEXT] = CDISABLE;
7204 #endif /* OXOS */
7205
7206 tttvt.c_iflag |= (IGNBRK|IGNPAR);
7207
7208 /* Stop bits */
7209
7210 #ifdef CSTOPB
7211 if (xlocal) {
7212 if (stopbits == 2) {
7213 tttvt.c_cflag |= CSTOPB; /* 2 stop bits */
7214 debug(F100,"ttvt 2 stopbits","",0);
7215 } else if (stopbits == 1) {
7216 tttvt.c_cflag &= ~(CSTOPB); /* 1 stop bit */
7217 debug(F100,"ttvt 1 stopbit","",0);
7218 }
7219 }
7220 #endif /* CSTOPB */
7221
7222 /* Parity */
7223
7224 #ifdef HWPARITY
7225 if (hwparity && xlocal) { /* Hardware parity */
7226 #ifdef COMMENT
7227 /* Uncomment this only if needed -- I don't think it is */
7228 ttraw.c_cflag &= ~(CSIZE); /* Clear out character-size mask */
7229 ttraw.c_cflag |= CS8; /* And set it to 8 */
7230 #endif /* COMMENT */
7231 #ifdef IGNPAR
7232 debug(F101,"ttvt hwparity IGNPAR","",IGNPAR);
7233 tttvt.c_iflag |= IGNPAR; /* Don't discard incoming bytes */
7234 #endif /* IGNPAR */
7235 tttvt.c_cflag |= PARENB; /* Enable parity */
7236
7237 switch (hwparity) {
7238 case 'e': /* Even */
7239 tttvt.c_cflag &= ~(PARODD);
7240 debug(F100,"ttvt 8 bits + even parity","",0);
7241 break;
7242 case 'o': /* Odd */
7243 tttvt.c_cflag |= PARODD;
7244 debug(F100,"ttvt 8 bits + odd parity","",0);
7245 break;
7246 case 'm': /* Mark */
7247 case 's': /* Space */
7248 /* PAREXT is mentioned in SVID but the details are not given. */
7249 /* PAREXT is not included in POSIX ISO/IEC 9945-1. */
7250 debug(F100,"ttvt 8 bits + invalid parity","",0);
7251 break;
7252 }
7253 } else { /* We handle parity ourselves */
7254 #endif /* HWPARITY */
7255 tttvt.c_cflag &= ~(PARENB); /* Don't enable parity */
7256 #ifdef HWPARITY
7257 }
7258 #endif /* HWPARITY */
7259
7260 #ifdef ATTSV
7261 #ifdef BSD44
7262 /* Things not to do... */
7263 tttvt.c_iflag &= ~(INLCR|IGNCR|ICRNL|INPCK|ISTRIP|IXANY);
7264 #else
7265 tttvt.c_iflag &= ~(INLCR|IGNCR|ICRNL|IUCLC|INPCK|ISTRIP|IXANY);
7266 #endif /* BSD44 */
7267 #else /* POSIX */
7268 tttvt.c_iflag &= ~(INLCR|IGNCR|ICRNL|INPCK|ISTRIP);
7269 #endif /* ATTSV */
7270 tttvt.c_cflag &= ~(CSIZE); /* Zero out the char size field */
7271 tttvt.c_cflag |= (CS8|CREAD|HUPCL); /* Char size 8, enable receiver, hup */
7272 tttvt.c_oflag &= ~OPOST; /* Don't postprocess output */
7273 #ifndef VEOF /* DGUX termio has VEOF at entry 4, see comment above */
7274 tttvt.c_cc[4] = 1;
7275 #else
7276 #ifndef OXOS
7277 #ifdef VMIN
7278 tttvt.c_cc[VMIN] = 1;
7279 #endif /* VMIN */
7280 #else /* OXOS */
7281 tttvt.c_min = 1;
7282 #endif /* OXOS */
7283 #endif /* VEOF */
7284 #ifndef VEOL /* DGUX termio has VEOL at entry 5, see comment above */
7285 tttvt.c_cc[5] = 0;
7286 #else
7287 #ifndef OXOS
7288 #ifdef VTIME
7289 tttvt.c_cc[VTIME] = 0;
7290 #endif /* VTIME */
7291 #else /* OXOS */
7292 tttvt.c_time = 0;
7293 #endif /* OXOS */
7294 #endif /* VEOL */
7295
7296 #ifdef Plan9
7297 if (p9ttyparity('n') < 0)
7298 return -1;
7299 #else
7300 #ifdef BSD44ORPOSIX
7301 errno = 0;
7302 #ifdef BEOSORBEBOX
7303 tttvt.c_cc[VMIN] = 0; /* DR7 can only poll. */
7304 #endif /* BEOSORBEBOX */
7305
7306 x = tcsetattr(ttyfd,TCSADRAIN,&tttvt);
7307 debug(F101,"ttvt BSD44ORPOSIX tcsetattr","",x);
7308 if (x < 0) {
7309 debug(F101,"ttvt BSD44ORPOSIX tcsetattr errno","",errno);
7310 return(-1);
7311 }
7312 #else /* ATTSV */
7313 x = ioctl(ttyfd,TCSETAW,&tttvt);
7314 debug(F101,"ttvt ATTSV ioctl TCSETAW","",x);
7315 if (x < 0) { /* set new modes . */
7316 debug(F101,"ttvt ATTSV ioctl TCSETAW errno","",errno);
7317 return(-1);
7318 }
7319 #endif /* BSD44ORPOSIX */
7320 #endif /* Plan9 */
7321 #endif /* ATTSV */
7322
7323 ttspeed = speed; /* Done, remember how we were */
7324 ttflow = flow; /* called, so we can decide how to */
7325 tvtflg = 1; /* respond next time. */
7326 debug(F100,"ttvt ok","",0);
7327 return(0);
7328
7329 #ifdef COHERENT
7330 #undef SVORPOSIX
7331 #endif /* COHERENT */
7332
7333 #endif /* NOLOCAL */
7334 }
7335
7336 #ifndef NOLOCAL
7337
7338 /* Serial speed department . . . */
7339
7340 /*
7341 SCO OSR5.0.x might or might not support high speeds. Sometimes they are not
7342 defined in the header files but they are supported (e.g. when building with
7343 UDK compiler rather than /bin/cc), sometimes vice versa. Even though 5.0.4
7344 was the first release that came with high serial speeds standard, releases
7345 back to 5.0.0 could use them if certain patches (or "supplements") were
7346 applied to the SIO driver. Plus a lot of SCO installations run third-party
7347 drivers.
7348 */
7349 #ifdef CK_SCOV5
7350 #ifndef B38400
7351 #define B38400 0000017
7352 #endif /* B38400 */
7353 #ifndef B57600
7354 #define B57600 0000021
7355 #endif /* B57600 */
7356 #ifndef B76800
7357 #define B76800 0000022
7358 #endif /* B76800 */
7359 #ifndef B115200
7360 #define B115200 0000023
7361 #endif /* B115200 */
7362 #ifndef B230400
7363 #define B230400 0000024
7364 #endif /* B230400 */
7365 #ifndef B460800
7366 #define B460800 0000025
7367 #endif /* B460800 */
7368 #ifndef B921600
7369 #define B921600 0000026
7370 #endif /* B921600 */
7371 #endif /* CK_SCOV5 */
7372 /*
7373 Plan 9's native speed setting interface lets you set anything you like,
7374 but will fail if the hardware doesn't like it, so we allow all the common
7375 speeds.
7376 */
7377 #ifdef Plan9
7378 #ifndef B50
7379 #define B50 50
7380 #endif /* B50 */
7381 #ifndef B75
7382 #define B75 75
7383 #endif /* B75 */
7384 #ifndef B110
7385 #define B110 110
7386 #endif /* B110 */
7387 #ifndef B134
7388 #define B134 134
7389 #endif /* B134 */
7390 #ifndef B200
7391 #define B200 200
7392 #endif /* B200 */
7393 #ifndef B300
7394 #define B300 300
7395 #endif /* B300 */
7396 #ifndef B1200
7397 #define B1200 1200
7398 #endif /* B1200 */
7399 #ifndef B1800
7400 #define B1800 1800
7401 #endif /* B1800 */
7402 #ifndef B2400
7403 #define B2400 2400
7404 #endif /* B2400 */
7405 #ifndef B4800
7406 #define B4800 4800
7407 #endif /* B4800 */
7408 #ifndef B9600
7409 #define B9600 9600
7410 #endif /* B9600 */
7411 #ifndef B14400
7412 #define B14400 14400
7413 #endif /* B14400 */
7414 #ifndef B19200
7415 #define B19200 19200
7416 #endif /* B19200 */
7417 #ifndef B28800
7418 #define B28800 28800
7419 #endif /* B28800 */
7420 #ifndef B38400
7421 #define B38400 38400
7422 #endif /* B38400 */
7423 #ifndef B57600
7424 #define B57600 57600
7425 #endif /* B57600 */
7426 #ifndef B76800
7427 #define B76800 76800
7428 #endif /* B76800 */
7429 #ifndef B115200
7430 #define B115200 115200
7431 #endif /* B115200 */
7432 #ifndef B230400
7433 #define B230400 230400
7434 #endif /* B230400 */
7435 #ifndef B460800
7436 #define B460800 460800
7437 #endif /* B460800 */
7438 #ifndef B921600
7439 #define B921600 921600
7440 #endif /* B921600 */
7441 #endif /* Plan9 */
7442
7443 /* T T S S P D -- Checks and sets transmission rate. */
7444
7445 /* Call with speed in characters (not bits!) per second. */
7446 /* Returns -1 on failure, 0 if it did nothing, 1 if it changed the speed. */
7447
7448 #ifdef USETCSETSPEED
7449 /*
7450 The tcsetspeed() / tcgetspeed() interface lets you pass any number at all
7451 to be used as a speed to be set, rather than forcing a choice from a
7452 predefined list. It seems to be peculiar to UnixWare 7.
7453
7454 These are the function codes to be passed to tc[gs]etspeed(),
7455 but for some reason they don't seem to be picked up from termios.h.
7456 */
7457 #ifndef TCS_ALL
7458 #define TCS_ALL 0
7459 #endif /* TCS_ALL */
7460 #ifndef TCS_IN
7461 #define TCS_IN 1
7462 #endif /* TCS_IN */
7463 #ifndef TCS_OUT
7464 #define TCS_OUT 2
7465 #endif /* TCS_OUT */
7466 #endif /* USETCSETSPEED */
7467
7468 int
ttsspd(cps)7469 ttsspd(cps) int cps; {
7470 int x;
7471 #ifdef POSIX
7472 /* Watch out, speed_t should be unsigned, so don't compare with -1, etc... */
7473 speed_t
7474 #else
7475 int
7476 #endif /* POSIX */
7477 s, s2;
7478 int ok = 1; /* Speed check result, assume ok */
7479
7480 #ifdef OLINUXHISPEED
7481 unsigned int spd_flags = 0;
7482 struct serial_struct serinfo;
7483 #endif /* OLINUXHISPEED */
7484
7485 debug(F101,"ttsspd cps","",cps);
7486 debug(F101,"ttsspd ttyfd","",ttyfd);
7487 debug(F101,"ttsspd xlocal","",xlocal);
7488
7489 if (ttyfd < 0 || xlocal == 0) /* Don't set speed on console */
7490 return(0);
7491
7492 #ifdef NETCONN
7493 if (netconn) {
7494 #ifdef TN_COMPORT
7495 if (istncomport())
7496 return(tnc_set_baud(cps * 10));
7497 else
7498 #endif /* TN_COMPORT */
7499 return(0);
7500 }
7501 #endif /* NETCONN */
7502 #ifdef NETCMD
7503 if (ttpipe) return(0);
7504 #endif /* NETCMD */
7505 #ifdef NETPTY
7506 if (ttpty) return(0);
7507 #endif /* NETPTY */
7508
7509 if (cps < 0) return(-1);
7510 s = s2 = 0; /* NB: s and s2 might be unsigned */
7511
7512 #ifdef USETCSETSPEED
7513
7514 s = cps * 10L;
7515
7516 x = tcgetattr(ttyfd,&ttcur); /* Get current speed */
7517 debug(F101,"ttsspd tcgetattr","",x);
7518 if (x < 0)
7519 return(-1);
7520 debug(F101,"ttsspd TCSETSPEED speed","",s);
7521
7522 errno = 0;
7523 if (s == 8880L) { /* 75/1200 split speed requested */
7524 tcsetspeed(TCS_IN, &ttcur, 1200L);
7525 tcsetspeed(TCS_OUT, &ttcur, 75L);
7526 } else
7527 tcsetspeed(TCS_ALL, &ttcur, s); /* Put new speed in structs */
7528 #ifdef DEBUG
7529 if (errno & deblog) {
7530 debug(F101,"ttsspd TCSETSPEED errno","",errno);
7531 }
7532 #endif /* DEBUG */
7533
7534 #ifdef COMMENT
7535 tcsetspeed(TCS_ALL, &ttraw, s);
7536 tcsetspeed(TCS_ALL, &tttvt, s);
7537 tcsetspeed(TCS_ALL, &ttold, s);
7538 #else
7539 if (s == 8880L) { /* 75/1200 split speed requested */
7540 tcsetspeed(TCS_IN, &ttraw, 1200L);
7541 tcsetspeed(TCS_OUT, &ttraw, 75L);
7542 tcsetspeed(TCS_IN, &tttvt, 1200L);
7543 tcsetspeed(TCS_OUT, &tttvt, 75L);
7544 tcsetspeed(TCS_IN, &ttold, 1200L);
7545 tcsetspeed(TCS_OUT, &ttold, 75L);
7546 } else {
7547 tcsetspeed(TCS_ALL, &ttraw, s);
7548 tcsetspeed(TCS_ALL, &tttvt, s);
7549 tcsetspeed(TCS_ALL, &ttold, s);
7550 }
7551 #endif /* COMMENT */
7552
7553 x = tcsetattr(ttyfd,TCSADRAIN,&ttcur); /* Set the speed */
7554 debug(F101,"ttsspd tcsetattr","",x);
7555 if (x < 0)
7556 return(-1);
7557
7558 #else /* Not USETCSETSPEED */
7559
7560 /* First check that the given speed is valid. */
7561
7562 switch (cps) {
7563 #ifndef MINIX
7564 case 0: s = B0; break;
7565 case 5: s = B50; break;
7566 case 7: s = B75; break;
7567 #endif /* MINIX */
7568 case 11: s = B110; break;
7569 #ifndef MINIX
7570 case 13: s = B134; break;
7571 case 15: s = B150; break;
7572 case 20: s = B200; break;
7573 #endif /* MINIX */
7574 case 30: s = B300; break;
7575 #ifndef MINIX
7576 case 60: s = B600; break;
7577 #endif /* MINIX */
7578 case 120: s = B1200; break;
7579 #ifndef MINIX
7580 case 180: s = B1800; break;
7581 #endif /* MINIX */
7582 case 240: s = B2400; break;
7583 case 480: s = B4800; break;
7584 #ifndef MINIX
7585 case 888: s = B75; s2 = B1200; break; /* 888 = 75/1200 split speed */
7586 #endif /* MINIX */
7587 #ifdef B7200
7588 case 720: s = B7200; break;
7589 #endif /* B7200 */
7590 case 960: s = B9600; break;
7591 #ifdef B14400
7592 case 1440: s = B14400; break;
7593 #endif /* B14400 */
7594 #ifdef B19200
7595 case 1920: s = B19200; break;
7596 #else
7597 #ifdef EXTA
7598 case 1920: s = EXTA; break;
7599 #endif /* EXTA */
7600 #endif /* B19200 */
7601 #ifdef B28800
7602 case 2880: s = B28800; break;
7603 #endif /* B28800 */
7604 #ifdef B38400
7605 case 3840: s = B38400;
7606 #ifdef OLINUXHISPEED
7607 spd_flags = ~ASYNC_SPD_MASK; /* Nonzero, but zero flags */
7608 #endif /* OLINUXHISPEED */
7609 break;
7610 #else /* B38400 not defined... */
7611 #ifdef EXTB
7612 case 3840: s = EXTB; break;
7613 #endif /* EXTB */
7614 #endif /* B38400 */
7615
7616 #ifdef HPUX
7617 #ifdef _B57600
7618 case 5760: s = _B57600; break;
7619 #endif /* _B57600 */
7620 #ifdef _B115200
7621 case 11520: s = _B115200; break;
7622 #endif /* _B115200 */
7623 #else
7624 #ifdef OLINUXHISPEED
7625 /*
7626 This bit from <carlo@sg.tn.tudelft.nl>:
7627 "Only note to make is maybe this: When the ASYNC_SPD_CUST flags are set then
7628 setting the speed to 38400 will set the custom speed (and ttgspd returns
7629 38400), but speeds 57600 and 115200 won't work any more because I didn't
7630 want to mess up the speed flags when someone is doing sophisticated stuff
7631 like custom speeds..."
7632 */
7633 case 5760: s = B38400; spd_flags = ASYNC_SPD_HI; break;
7634 case 11520: s = B38400; spd_flags = ASYNC_SPD_VHI; break;
7635 #else
7636 #ifdef B57600
7637 case 5760: s = B57600; break;
7638 #endif /* B57600 */
7639 #ifdef B76800
7640 case 7680: s = B76800; break;
7641 #endif /* B76800 */
7642 #ifdef B115200
7643 case 11520: s = B115200; break;
7644 #endif /* B115200 */
7645 #endif /* OLINUXHISPEED */
7646 #ifdef B153600
7647 case 15360: s = B153600; break;
7648 #endif /* B153600 */
7649 #ifdef B230400
7650 case 23040: s = B230400; break;
7651 #endif /* B230400 */
7652 #ifdef B307200
7653 case 30720: s = B307200; break;
7654 #endif /* B307200 */
7655 #ifdef B460800
7656 case 46080: s = B460800; break;
7657 #endif /* 460800 */
7658 #ifdef B921600
7659 case 92160: s = B921600; break;
7660 #endif /* B921600 */
7661 #endif /* HPUX */
7662 default:
7663 ok = 0; /* Good speed not found, so not ok */
7664 break;
7665 }
7666 debug(F101,"ttsspd ok","",ok);
7667 debug(F101,"ttsspd s","",s);
7668
7669 if (!ok) {
7670 debug(F100,"ttsspd fails","",0);
7671 return(-1);
7672 } else {
7673 if (!s2) s2 = s; /* Set input speed */
7674 #ifdef Plan9
7675 if (p9ttsspd(cps) < 0)
7676 return(-1);
7677 #else
7678 #ifdef BSD44ORPOSIX
7679 x = tcgetattr(ttyfd,&ttcur); /* Get current speed */
7680 debug(F101,"ttsspd tcgetattr","",x);
7681 if (x < 0)
7682 return(-1);
7683 #ifdef OLINUXHISPEED
7684 debug(F101,"ttsspd spd_flags","",spd_flags);
7685 if (spd_flags && spd_flags != ASYNC_SPD_CUST) {
7686 if (ioctl(ttyfd, TIOCGSERIAL, &serinfo) < 0) {
7687 debug(F100,"ttsspd: TIOCGSERIAL failed","",0);
7688 return(-1);
7689 } else debug(F100,"ttsspd: TIOCGSERIAL ok","",0);
7690 serinfo.flags &= ~ASYNC_SPD_MASK;
7691 serinfo.flags |= (spd_flags & ASYNC_SPD_MASK);
7692 if (ioctl(ttyfd, TIOCSSERIAL, &serinfo) < 0)
7693 return(-1);
7694 }
7695 #endif /* OLINUXHISPEED */
7696 cfsetospeed(&ttcur,s);
7697 cfsetispeed(&ttcur,s2);
7698 cfsetospeed(&ttraw,s);
7699 cfsetispeed(&ttraw,s2);
7700 cfsetospeed(&tttvt,s);
7701 cfsetispeed(&tttvt,s2);
7702 cfsetospeed(&ttold,s);
7703 cfsetispeed(&ttold,s2);
7704 x = tcsetattr(ttyfd,TCSADRAIN,&ttcur);
7705 debug(F101,"ttsspd tcsetattr","",x);
7706 if (x < 0) return(-1);
7707 #else
7708 #ifdef ATTSV
7709 if (cps == 888) return(-1); /* No split speeds, sorry. */
7710 x = ioctl(ttyfd,TCGETA,&ttcur);
7711 debug(F101,"ttsspd TCGETA ioctl","",x);
7712 if (x < 0) return(-1);
7713 ttcur.c_cflag &= ~CBAUD;
7714 ttcur.c_cflag |= s;
7715 tttvt.c_cflag &= ~CBAUD;
7716 tttvt.c_cflag |= s;
7717 ttraw.c_cflag &= ~CBAUD;
7718 ttraw.c_cflag |= s;
7719 ttold.c_cflag &= ~CBAUD;
7720 ttold.c_cflag |= s;
7721 x = ioctl(ttyfd,TCSETAW,&ttcur);
7722 debug(F101,"ttsspd TCSETAW ioctl","",x);
7723 if (x < 0) return(-1);
7724 #else
7725 #ifdef BELLV10
7726 x = ioctl(ttyfd,TIOCGDEV,&tdcur);
7727 debug(F101,"ttsspd TIOCGDEV ioctl","",x);
7728 if (x < 0) return(-1);
7729 tdcur.ispeed = s2;
7730 tdcur.ospeed = s;
7731 errno = 0;
7732 ok = ioctl(ttyfd,TIOCSDEV,&tdcur);
7733 debug(F101,"ttsspd BELLV10 ioctl","",ok);
7734 if (ok < 0) {
7735 perror(ttnmsv);
7736 debug(F101,"ttsspd BELLV10 errno","",ok);
7737 return(-1);
7738 }
7739 #else
7740 x = gtty(ttyfd,&ttcur);
7741 debug(F101,"ttsspd gtty","",x);
7742 if (x < 0) return(-1);
7743 ttcur.sg_ospeed = s; ttcur.sg_ispeed = s2;
7744 tttvt.sg_ospeed = s; tttvt.sg_ispeed = s2;
7745 ttraw.sg_ospeed = s; ttraw.sg_ispeed = s2;
7746 ttold.sg_ospeed = s; ttold.sg_ispeed = s2;
7747 x = stty(ttyfd,&ttcur);
7748 debug(F101,"ttsspd stty","",x);
7749 if (x < 0) return(-1);
7750 #endif /* BELLV10 */
7751 #endif /* ATTSV */
7752 #endif /* BSD44ORPOSIX */
7753 #endif /* Plan9 */
7754 }
7755 return(1); /* Return 1 = success. */
7756 #endif /* USETCSETSPEED */
7757 }
7758
7759 #endif /* NOLOCAL */
7760
7761 /* C O N G S P D - Get speed of console terminal */
7762
7763 long
congspd()7764 congspd() {
7765 /*
7766 This is a disgusting hack. The right way to do this would be to pass an
7767 argument to ttgspd(), but then we'd need to change the Kermit API and
7768 all of the ck?tio.c modules. (Currently used only for rlogin.)
7769 */
7770 int t1;
7771 long spd;
7772 #ifdef NETCONN
7773 int t2 = netconn;
7774 netconn = 0;
7775 #endif /* NETCONN */
7776 t1 = ttyfd;
7777 ttyfd = -1;
7778 spd = ttgspd();
7779 debug(F101,"congspd","",spd);
7780 #ifdef NETCONN
7781 netconn = t2;
7782 #endif /* NETCONN */
7783 ttyfd = t1;
7784 return(spd);
7785 }
7786
7787 /* T T S P D L I S T -- Get list of serial speeds allowed on this platform */
7788
7789 #define NSPDLIST 64
7790 static long spdlist[NSPDLIST];
7791 /*
7792 As written, this picks up the speeds known at compile time, and thus
7793 apply to the system where C-Kermit was built, rather than to the one where
7794 it is running. Suggestions for improvement are always welcome.
7795 */
7796 long *
ttspdlist()7797 ttspdlist() {
7798 int i;
7799 for (i = 0; i < NSPDLIST; i++) /* Initialize the list */
7800 spdlist[i] = -1L;
7801 i = 1;
7802
7803 #ifdef USETCSETSPEED /* No way to find out what's legal */
7804 debug(F100,"ttspdlist USETCSETSPEED","",0);
7805 spdlist[i++] = 50L;
7806 #ifndef UW7
7807 spdlist[i++] = 75L;
7808 #endif /* UW7 */
7809 spdlist[i++] = 110L;
7810 #ifndef UW7
7811 spdlist[i++] = 134L;
7812 #endif /* UW7 */
7813 spdlist[i++] = 150L;
7814 spdlist[i++] = 200L;
7815 spdlist[i++] = 300L;
7816 spdlist[i++] = 600L;
7817 spdlist[i++] = 1200L;
7818 spdlist[i++] = 1800L;
7819 spdlist[i++] = 2400L;
7820 spdlist[i++] = 4800L;
7821 spdlist[i++] = 8880L;
7822 spdlist[i++] = 9600L;
7823 spdlist[i++] = 14400L;
7824 spdlist[i++] = 19200L;
7825 spdlist[i++] = 28800L;
7826 #ifndef UW7
7827 spdlist[i++] = 33600L;
7828 #endif /* UW7 */
7829 spdlist[i++] = 38400L;
7830 spdlist[i++] = 57600L;
7831 spdlist[i++] = 76800L;
7832 spdlist[i++] = 115200L;
7833 #ifndef UW7
7834 spdlist[i++] = 153600L;
7835 spdlist[i++] = 230400L;
7836 spdlist[i++] = 307200L;
7837 spdlist[i++] = 460800L;
7838 spdlist[i++] = 921600L;
7839 #endif /* UW7 */
7840
7841 #else /* USETCSETSPEED */
7842
7843 debug(F100,"ttspdlist no USETCSETSPEED","",0);
7844
7845 #ifdef B50
7846 debug(F101,"ttspdlist B50","",B50);
7847 spdlist[i++] = 50L;
7848 #endif /* B50 */
7849 #ifdef B75
7850 debug(F101,"ttspdlist B75","",B75);
7851 spdlist[i++] = 75L;
7852 #endif /* B75 */
7853 #ifdef B110
7854 debug(F101,"ttspdlist B110","",B110);
7855 spdlist[i++] = 110L;
7856 #endif /* B110 */
7857 #ifdef B134
7858 debug(F101,"ttspdlist B134","",B134);
7859 spdlist[i++] = 134L;
7860 #endif /* B134 */
7861 #ifdef B150
7862 debug(F101,"ttspdlist B150","",B150);
7863 spdlist[i++] = 150L;
7864 #endif /* B150 */
7865 #ifdef B200
7866 debug(F101,"ttspdlist B200","",B200);
7867 spdlist[i++] = 200L;
7868 #endif /* B200 */
7869 #ifdef B300
7870 debug(F101,"ttspdlist B300","",B300);
7871 spdlist[i++] = 300L;
7872 #endif /* B300 */
7873 #ifdef B600
7874 debug(F101,"ttspdlist B600","",B600);
7875 spdlist[i++] = 600L;
7876 #endif /* B600 */
7877 #ifdef B1200
7878 debug(F101,"ttspdlist B1200","",B1200);
7879 spdlist[i++] = 1200L;
7880 #endif /* B1200 */
7881 #ifdef B1800
7882 debug(F101,"ttspdlist B1800","",B1800);
7883 spdlist[i++] = 1800L;
7884 #endif /* B1800 */
7885 #ifdef B2400
7886 debug(F101,"ttspdlist B2400","",B2400);
7887 spdlist[i++] = 2400L;
7888 #endif /* B2400 */
7889 #ifdef B4800
7890 debug(F101,"ttspdlist B4800","",B4800);
7891 spdlist[i++] = 4800L;
7892 #endif /* B4800 */
7893 #ifdef B9600
7894 debug(F101,"ttspdlist B9600","",B9600);
7895 spdlist[i++] = 9600L;
7896 #endif /* B9600 */
7897 #ifdef B14400
7898 debug(F101,"ttspdlist B14400","",B14400);
7899 spdlist[i++] = 14400L;
7900 #endif /* B14400 */
7901 #ifdef B19200
7902 debug(F101,"ttspdlist B19200","",B19200);
7903 spdlist[i++] = 19200L;
7904 #else
7905 #ifdef EXTA
7906 debug(F101,"ttspdlist EXTA","",EXTA);
7907 spdlist[i++] = 19200L;
7908 #endif /* EXTA */
7909 #endif /* B19200 */
7910 #ifdef B28800
7911 debug(F101,"ttspdlist B28800","",B28800);
7912 spdlist[i++] = 28800L;
7913 #endif /* B28800 */
7914 #ifdef B33600
7915 debug(F101,"ttspdlist B33600","",B33600);
7916 spdlist[i++] = 33600L;
7917 #endif /* B33600 */
7918 #ifdef B38400
7919 debug(F101,"ttspdlist B38400","",B38400);
7920 spdlist[i++] = 38400L;
7921 #else
7922 #ifdef EXTB
7923 debug(F101,"ttspdlist EXTB","",EXTB);
7924 spdlist[i++] = 38400L;
7925 #endif /* EXTB */
7926 #endif /* B38400 */
7927 #ifdef _B57600
7928 debug(F101,"ttspdlist _B57600","",_B57600);
7929 spdlist[i++] = 57600L;
7930 #else
7931 #ifdef B57600
7932 debug(F101,"ttspdlist B57600","",B57600);
7933 spdlist[i++] = 57600L;
7934 #endif /* B57600 */
7935 #endif /* _B57600 */
7936 #ifdef B76800
7937 debug(F101,"ttspdlist B76800","",B76800);
7938 spdlist[i++] = 76800L;
7939 #endif /* B76800 */
7940 #ifdef _B115200
7941 debug(F101,"ttspdlist _B115200","",_B115200);
7942 spdlist[i++] = 115200L;
7943 #else
7944 #ifdef B115200
7945 debug(F101,"ttspdlist B115200","",B115200);
7946 spdlist[i++] = 115200L;
7947 #endif /* B115200 */
7948 #endif /* _B115200 */
7949 #ifdef B153600
7950 debug(F101,"ttspdlist B153600","",B153600);
7951 spdlist[i++] = 153600L;
7952 #endif /* B153600 */
7953 #ifdef B230400
7954 debug(F101,"ttspdlist B230400","",B230400);
7955 spdlist[i++] = 230400L;
7956 #endif /* B230400 */
7957 #ifdef B307200
7958 debug(F101,"ttspdlist B307200","",B307200);
7959 spdlist[i++] = 307200L;
7960 #endif /* B307200 */
7961 #ifdef B460800
7962 debug(F101,"ttspdlist B460800","",B460800);
7963 spdlist[i++] = 460800L;
7964 #endif /* B460800 */
7965 #ifdef B921600
7966 debug(F101,"ttspdlist B921600","",B921600);
7967 spdlist[i++] = 921600L;
7968 #endif /* B921600 */
7969 #endif /* USETCSETSPEED */
7970 spdlist[0] = i - 1; /* Return count in 0th element */
7971 debug(F111,"ttspdlist spdlist","0",spdlist[0]);
7972 return((long *)spdlist);
7973 }
7974
7975 /* T T G S P D - Get speed of currently selected tty line */
7976
7977 /*
7978 Unreliable. After SET LINE, it returns an actual speed, but not necessarily
7979 the real speed. On some systems, it returns the line's nominal speed, from
7980 /etc/ttytab. Even if you SET SPEED to something else, this function might
7981 not notice.
7982 */
7983 long
ttgspd()7984 ttgspd() { /* Get current serial device speed */
7985 #ifdef NOLOCAL
7986 return(-1L);
7987 #else
7988 #ifdef POSIX
7989 speed_t /* Should be unsigned */
7990 #else
7991 int /* Isn't unsigned */
7992 #endif /* POSIX */
7993 s;
7994 int x;
7995 long ss;
7996 #ifdef OLINUXHISPEED
7997 unsigned int spd_flags = 0;
7998 struct serial_struct serinfo;
7999 #endif /* OLINUXHISPEED */
8000
8001 #ifdef NETCONN
8002 if (netconn) {
8003 #ifdef TN_COMPORT
8004 if (istncomport())
8005 return(tnc_get_baud());
8006 else
8007 #endif /* TN_COMPORT */
8008 return(-1); /* -1 if network connection */
8009 }
8010 #endif /* NETCONN */
8011 #ifdef NETCMD
8012 if (ttpipe) return(-1);
8013 #endif /* NETCMD */
8014 #ifdef NETPTY
8015 if (ttpty) return(-1);
8016 #endif /* NETPTY */
8017
8018 debug(F101,"ttgspd ttyfd","",ttyfd);
8019
8020 #ifdef USETCSETSPEED
8021
8022 x = tcgetattr(ttyfd,&ttcur); /* Get current speed */
8023 debug(F101,"ttgspd tcgetattr","",x);
8024 if (x < 0)
8025 return(-1);
8026 errno = 0;
8027 s = tcgetspeed(TCS_ALL, &ttcur);
8028 debug(F101,"ttsspd TCGETSPEED speed","",s);
8029 if (s == 0) {
8030 long s1, s2;
8031 s1 = tcgetspeed(TCS_IN, &ttcur);
8032 s2 = tcgetspeed(TCS_OUT, &ttcur);
8033 if (s1 == 1200L && s2 == 75L)
8034 return(8880L);
8035 }
8036 #ifdef DEBUG
8037 if (errno & deblog) {
8038 debug(F101,"ttsspd TCGETSPEED errno","",errno);
8039 }
8040 #endif /* DEBUG */
8041 return(s);
8042
8043 #else /* Not USETCSETSPEED */
8044
8045 #ifdef Plan9
8046 if (ttyfd < 0)
8047 ss = -1;
8048 else
8049 ss = ttylastspeed;
8050 #else
8051 #ifdef OLINUXHISPEED
8052 debug(F100,"ttgspd Linux OLINUXHISPEED","",0);
8053 #endif /* OLINUXHISPEED */
8054
8055 if (ttyfd < 0) {
8056 #ifdef BSD44ORPOSIX
8057 s = cfgetospeed(&ccold);
8058 debug(F101,"ttgspd cfgetospeed 1 POSIX","",s);
8059 #else
8060 #ifdef ATTSV
8061 s = ccold.c_cflag & CBAUD;
8062 debug(F101,"ttgspd c_cflag CBAUD 1 ATTSV","",s);
8063 #else
8064 s = ccold.sg_ospeed; /* (obtained by congm()) */
8065 debug(F101,"ttgspd sg_ospeed 1","",s);
8066 #endif /* ATTSV */
8067 #endif /* BSD44POSIX */
8068
8069 } else {
8070 #ifdef BSD44ORPOSIX
8071 if (tcgetattr(ttyfd,&ttcur) < 0) return(-1);
8072 s = cfgetospeed(&ttcur);
8073 debug(F101,"ttgspd cfgetospeed 2 BSDORPOSIX","",s);
8074 #ifdef OLINUXHISPEED
8075 if (ioctl(ttyfd,TIOCGSERIAL,&serinfo) > -1)
8076 spd_flags = serinfo.flags & ASYNC_SPD_MASK;
8077 debug(F101,"ttgspd spd_flags","",spd_flags);
8078 #endif /* OLINUXHISPEED */
8079 #else
8080 #ifdef ATTSV
8081 x = ioctl(ttyfd,TCGETA,&ttcur);
8082 debug(F101,"ttgspd ioctl 2 ATTSV x","",x);
8083 debug(F101,"ttgspd ioctl 2 ATTSV errno","",errno);
8084 if (x < 0) return(-1);
8085 s = ttcur.c_cflag & CBAUD;
8086 debug(F101,"ttgspd ioctl 2 ATTSV speed","",s);
8087 #else
8088 #ifdef BELLV10
8089 x = ioctl(ttyfd,TIOCGDEV,&tdcur);
8090 debug(F101,"ttgspd ioctl 2 BELLV10 x","",x);
8091 if (x < 0) return(-1);
8092 s = tdcur.ospeed;
8093 debug(F101,"ttgspd ioctl 2 BELLV10 speed","",s);
8094 #else
8095 x = gtty(ttyfd,&ttcur);
8096 debug(F101,"ttgspd gtty 2 x","",x);
8097 debug(F101,"ttgspd gtty 2 errno","",errno);
8098 if (x < 0) return(-1);
8099 s = ttcur.sg_ospeed;
8100 debug(F101,"ttgspd gtty 2 speed","",s);
8101 #endif /* BELLV10 */
8102 #endif /* ATTSV */
8103 #endif /* BSD44ORPOSIX */
8104 }
8105 debug(F101,"ttgspd code","",s);
8106 #ifdef OLINUXHISPEED
8107 debug(F101,"ttgspd spd_flags","",spd_flags);
8108 #endif /* OLINUXHISPEED */
8109 switch (s) {
8110 #ifdef B0
8111 case B0: ss = 0L; break;
8112 #endif /* B0 */
8113
8114 #ifndef MINIX
8115 /*
8116 MINIX defines the Bxx symbols to be bps/100, so B50==B75, B110==B134==B150,
8117 etc, making for many "duplicate case in switch" errors, which are fatal.
8118 */
8119 #ifdef B50
8120 case B50: ss = 50L; break;
8121 #endif /* B50 */
8122 #ifdef B75
8123 case B75: ss = 75L; break;
8124 #endif /* B75 */
8125 #endif /* MINIX */
8126
8127 #ifdef B110
8128 case B110: ss = 110L; break;
8129 #endif /* B110 */
8130
8131 #ifndef MINIX
8132 #ifdef B134
8133 case B134: ss = 134L; break;
8134 #endif /* B134 */
8135 #ifdef B150
8136 case B150: ss = 150L; break;
8137 #endif /* B150 */
8138 #endif /* MINIX */
8139
8140 #ifdef B200
8141 case B200: ss = 200L; break;
8142 #endif /* B200 */
8143
8144 #ifdef B300
8145 case B300: ss = 300L; break;
8146 #endif /* B300 */
8147
8148 #ifdef B600
8149 case B600: ss = 600L; break;
8150 #endif /* B600 */
8151
8152 #ifdef B1200
8153 case B1200: ss = 1200L; break;
8154 #endif /* B1200 */
8155
8156 #ifdef B1800
8157 case B1800: ss = 1800L; break;
8158 #endif /* B1800 */
8159
8160 #ifdef B2400
8161 case B2400: ss = 2400L; break;
8162 #endif /* B2400 */
8163
8164 #ifdef B4800
8165 case B4800: ss = 4800L; break;
8166 #endif /* B4800 */
8167
8168 #ifdef B7200
8169 case B7200: ss = 7200L; break;
8170 #endif /* B7200 */
8171
8172 #ifdef B9600
8173 case B9600: ss = 9600L; break;
8174 #endif /* B9600 */
8175
8176 #ifdef B19200
8177 case B19200: ss = 19200L; break;
8178 #else
8179 #ifdef EXTA
8180 case EXTA: ss = 19200L; break;
8181 #endif /* EXTA */
8182 #endif /* B19200 */
8183
8184 #ifndef MINIX
8185 #ifdef B38400
8186 case B38400:
8187 ss = 38400L;
8188 #ifdef OLINUXHISPEED
8189 switch(spd_flags) {
8190 case ASYNC_SPD_HI: ss = 57600L; break;
8191 case ASYNC_SPD_VHI: ss = 115200L; break;
8192 }
8193 #endif /* OLINUXHISPEED */
8194 break;
8195 #else
8196 #ifdef EXTB
8197 case EXTB: ss = 38400L; break;
8198 #endif /* EXTB */
8199 #endif /* B38400 */
8200 #endif /* MINIX */
8201
8202 #ifdef HPUX
8203 #ifdef _B57600
8204 case _B57600: ss = 57600L; break;
8205 #endif /* _B57600 */
8206 #ifdef _B115200
8207 case _B115200: ss = 115200L; break;
8208 #endif /* _B115200 */
8209 #else
8210 #ifdef B57600
8211 case B57600: ss = 57600L; break;
8212 #endif /* B57600 */
8213 #ifdef B76800
8214 case B76800: ss = 76800L; break;
8215 #endif /* B76800 */
8216 #ifdef B115200
8217 case B115200: ss = 115200L; break;
8218 #endif /* B115200 */
8219 #ifdef B153600
8220 case B153600: ss = 153600L; break;
8221 #endif /* B153600 */
8222 #ifdef B230400
8223 case B230400: ss = 230400L; break;
8224 #endif /* B230400 */
8225 #ifdef B307200
8226 case B307200: ss = 307200L; break;
8227 #endif /* B307200 */
8228 #ifdef B460800
8229 case B460800: ss = 460800L; break;
8230 #endif /* B460800 */
8231 #endif /* HPUX */
8232 #ifdef B921600
8233 case B921600: ss = 921600L; break;
8234 #endif /* B921600 */
8235 default:
8236 ss = -1; break;
8237 }
8238 #endif /* Plan9 */
8239 debug(F101,"ttgspd speed","",ss);
8240 return(ss);
8241
8242 #endif /* USETCSETSPEED */
8243 #endif /* NOLOCAL */
8244 }
8245 #ifdef MINIX2 /* Another hack alert */
8246 #define MINIX
8247 #endif /* MINIX2 */
8248
8249 /*
8250 FIONREAD data type... This has been defined as "long" for many, many
8251 years, and it worked OK until 64-bit platforms appeared. Thus we use
8252 int for 64-bit platforms, but keep long for the others. If we changed
8253 the default PEEKTYPE to int, this would probably break 16-bit builds
8254 (note that sizeof(long) == sizeof(int) on most 32-bit platforms), many
8255 of which we have no way of testing any more. Therefore, do not change
8256 the default definition of PEEKTYPE -- only add exceptions to it as needed.
8257 */
8258 #ifdef COHERENT
8259 #ifdef FIONREAD
8260 #undef FIONREAD
8261 #endif /* FIONREAD */
8262 /* #define FIONREAD TIOCQUERY */
8263 /* #define PEEKTYPE int */
8264 #else /* Not COHERENT... */
8265
8266 #ifdef OSF32 /* Digital UNIX 3.2 or higher */
8267 #define PEEKTYPE int
8268 #else
8269 #define PEEKTYPE long /* Elsewhere (see notes above) */
8270 #endif /* OSF32 */
8271 #endif /* COHERENT */
8272
8273 /* ckumyr.c by Kristoffer Eriksson, ske@pkmab.se, 15 Mar 1990. */
8274
8275 #ifdef MYREAD
8276
8277 /* Private buffer for myread() and its companions. Not for use by anything
8278 * else. ttflui() is allowed to reset them to initial values. ttchk() is
8279 * allowed to read my_count.
8280 *
8281 * my_item is an index into mybuf[]. Increment it *before* reading mybuf[].
8282 *
8283 * A global parity mask variable could be useful too. We could use it to
8284 * let myread() strip the parity on its own, instead of stripping sign
8285 * bits as it does now.
8286 */
8287 #ifdef BIGBUFOK
8288 #define MYBUFLEN 32768
8289 #else
8290 #ifdef pdp11
8291 #define MYBUFLEN 256
8292 #else
8293 #define MYBUFLEN 1024
8294 #endif /* pdp11 */
8295 #endif /* BIGBUFOK */
8296
8297 #ifdef ANYX25
8298 #undef MYBUFLEN
8299 #define MYBUFLEN 256
8300 /*
8301 On X.25 connections, there is an extra control byte at the beginning.
8302 */
8303 static CHAR x25buf[MYBUFLEN+1]; /* Communication device input buffer */
8304 static CHAR *mybuf = x25buf+1;
8305 #else
8306 static CHAR mybuf[MYBUFLEN];
8307 #endif /* ANYX25 */
8308
8309 static int my_count = 0; /* Number of chars still in mybuf */
8310 static int my_item = -1; /* Last index read from mybuf[] */
8311
8312 /* T T P E E K -- Peek into our internal communications input buffers. */
8313
8314 /*
8315 NOTE: This routine is peculiar to UNIX, and is used only by the
8316 select()-based CONNECT module, ckucns.c. It need not be replicated in
8317 the ck?tio.c of other platforms.
8318 */
8319 int
ttpeek()8320 ttpeek() {
8321 #ifdef TTLEBUF
8322 int rc = 0;
8323 if (ttpush >= 0)
8324 rc++;
8325 rc += le_inbuf();
8326 if (rc > 0)
8327 return(rc);
8328 else
8329 #endif /* TTLEBUF */
8330
8331 #ifdef MYREAD
8332 return(my_count);
8333 #else
8334 return(0);
8335 #endif /* MYREAD */
8336 }
8337
8338 /* myread() -- Efficient read of one character from communications line.
8339 *
8340 * NOTE: myread() and its helpers mygetbuf() and myfillbuf() return raw
8341 * bytes from connection, so when the connection is encrypted, these bytes
8342 * must be decrypted.
8343 *
8344 * Uses a private buffer to minimize the number of expensive read() system
8345 * calls. Essentially performs the equivalent of read() of 1 character, which
8346 * is then returned. By reading all available input from the system buffers
8347 * to the private buffer in one chunk, and then working from this buffer, the
8348 * number of system calls is reduced in any case where more than one character
8349 * arrives during the processing of the previous chunk, for instance high
8350 * baud rates or network type connections where input arrives in packets.
8351 * If the time needed for a read() system call approaches the time for more
8352 * than one character to arrive, then this mechanism automatically compensates
8353 * for that by performing bigger read()s less frequently. If the system load
8354 * is high, the same mechanism compensates for that too.
8355 *
8356 * myread() is a macro that returns the next character from the buffer. If the
8357 * buffer is empty, mygetbuf() is called. See mygetbuf() for possible error
8358 * returns.
8359 *
8360 * This should be efficient enough for any one-character-at-a-time loops.
8361 * For even better efficiency you might use memcpy()/bcopy() or such between
8362 * buffers (since they are often better optimized for copying), but it may not
8363 * be worth it if you have to take an extra pass over the buffer to strip
8364 * parity and check for CTRL-C anyway.
8365 *
8366 * Note that if you have been using myread() from another program module, you
8367 * may have some trouble accessing this macro version and the private variables
8368 * it uses. In that case, just add a function in this module, that invokes the
8369 * macro.
8370 */
8371 #define myread() (--my_count < 0 ? mygetbuf() : 255 & (int)mybuf[++my_item])
8372
8373 /* Specification: Push back up to one character onto myread()'s queue.
8374 *
8375 * This implementation: Push back characters into mybuf. At least one character
8376 * must have been read through myread() before myunrd() may be used. After
8377 * EOF or read error, again, myunrd() can not be used. Sometimes more than
8378 * one character can be pushed back, but only one character is guaranteed.
8379 * Since a previous myread() must have read its character out of mybuf[],
8380 * that guarantees that there is space for at least one character. If push
8381 * back was really needed after EOF, a small addition could provide that.
8382 *
8383 * As of 02/2007 myunrd() is used by ttinl().
8384 */
8385 VOID
8386 #ifdef CK_ANSIC
myunrd(CHAR ch)8387 myunrd(CHAR ch)
8388 #else
8389 myunrd(ch) CHAR ch;
8390 #endif /* CK_ANSIC */
8391 {
8392 if (my_item >= 0) {
8393 mybuf[my_item--] = ch;
8394 ++my_count;
8395 }
8396 }
8397
8398 /* T T P U S H B A C K -- Put n bytes back into the myread buffer */
8399
8400 static CHAR * pushbuf = NULL;
8401 /* static int pushed = 0; */
8402
8403 int
ttpushback(s,n)8404 ttpushback(s,n) CHAR * s; int n; {
8405 debug(F101,"ttpushback n","",n);
8406 if (pushbuf || n > MYBUFLEN || n < 1)
8407 return(-1);
8408 debug(F101,"ttpushback my_count","",my_count);
8409 if (my_count > 0) {
8410 if (!(pushbuf = (CHAR *)malloc(n+1)))
8411 return(-1);
8412 memcpy(pushbuf,mybuf,my_count);
8413 /* pushed = my_count; */ /* (set but never used) */
8414 }
8415 memcpy(mybuf,s,n);
8416 my_count = n;
8417 my_item = -1;
8418 return(0);
8419 }
8420
8421 /* mygetbuf() -- Fill buffer for myread() and return first character.
8422 *
8423 * This function is what myread() uses when it can't get the next character
8424 * directly from its buffer. First, it calls a system dependent myfillbuf()
8425 * to read at least one new character into the buffer, and then it returns
8426 * the first character just as myread() would have done. This function also
8427 * is responsible for all error conditions that myread() can indicate.
8428 *
8429 * Returns: When OK => a positive character, 0 or greater.
8430 * When EOF => -2.
8431 * When error => -3, error code in errno.
8432 *
8433 * Older myread()s additionally returned -1 to indicate that there was nothing
8434 * to read, upon which the caller would call myread() again until it got
8435 * something. The new myread()/mygetbuf() always gets something. If it
8436 * doesn't, then make it do so! Any program that actually depends on the old
8437 * behaviour will break.
8438 *
8439 * The older version also used to return -2 both for EOF and other errors,
8440 * and used to set errno to 9999 on EOF. The errno stuff is gone, EOF and
8441 * other errors now return different results, although Kermit currently never
8442 * checks to see which it was. It just disconnects in both cases.
8443 *
8444 * Kermit lets the user use the quit key to perform some special commands
8445 * during file transfer. This causes read(), and thus also mygetbuf(), to
8446 * finish without reading anything and return the EINTR error. This should
8447 * be checked by the caller. Mygetbuf() could retry the read() on EINTR,
8448 * but if there is nothing to read, this could delay Kermit's reaction to
8449 * the command, and make Kermit appear unresponsive.
8450 *
8451 * The debug() call should be removed for optimum performance.
8452 */
8453 int
mygetbuf()8454 mygetbuf() {
8455 int x;
8456 errno = 0;
8457 #ifdef DEBUG
8458 if (deblog && my_count > 0)
8459 debug(F101,"mygetbuf IMPROPERLY CALLED with my_count","",my_count);
8460 #endif /* DEBUG */
8461 if (my_count <= 0)
8462 my_count = myfillbuf();
8463
8464 #ifdef DEBUG
8465 #ifdef COMMENT
8466 if (deblog) debug(F101, "mygetbuf read", "", my_count);
8467 #else /* COMMENT */
8468 ckhexdump("mygetbuf read", mybuf, my_count);
8469 #endif /* COMMENT */
8470 #endif /* DEBUG */
8471 x = my_count;
8472 if (my_count <= 0) {
8473 my_count = 0;
8474 my_item = -1;
8475 debug(F101,"mygetbuf errno","",errno);
8476 #ifdef TCPSOCKET
8477 if (netconn && ttnet == NET_TCPB && errno != 0) {
8478 if (errno != EINTR) {
8479 debug(F101,"mygetbuf TCP error","",errno);
8480 ttclos(0); /* Close the connection. */
8481 }
8482 return(-3);
8483 }
8484 #endif /* TCPSOCKET */
8485 if (!netconn && xlocal && errno) {
8486 if (errno != EINTR) {
8487 debug(F101,"mygetbuf SERIAL error","",errno);
8488 x = -3;
8489 ttclos(0); /* Close the connection. */
8490 }
8491 }
8492 return((x < 0) ? -3 : -2);
8493 }
8494 --my_count;
8495 return((unsigned)(0xff & mybuf[my_item = 0]));
8496 }
8497
8498 /* myfillbuf():
8499 * System-dependent read() into mybuf[], as many characters as possible.
8500 *
8501 * Returns: OK => number of characters read, always more than zero.
8502 * EOF => 0
8503 * Error => -1, error code in errno.
8504 *
8505 * If there is input available in the system's buffers, all of it should be
8506 * read into mybuf[] and the function return immediately. If no input is
8507 * available, it should wait for a character to arrive, and return with that
8508 * one in mybuf[] as soon as possible. It may wait somewhat past the first
8509 * character, but be aware that any such delay lengthens the packet turnaround
8510 * time during kermit file transfers. Should never return with zero characters
8511 * unless EOF or irrecoverable read error.
8512 *
8513 * Correct functioning depends on the correct tty parameters being used.
8514 * Better control of current parameters is required than may have been the
8515 * case in older Kermit releases. For instance, O_NDELAY (or equivalent) can
8516 * no longer be sometimes off and sometimes on like it used to, unless a
8517 * special myfillbuf() is written to handle that. Otherwise the ordinary
8518 * myfillbuf()s may think they have come to EOF.
8519 *
8520 * If your system has a facility to directly perform the functioning of
8521 * myfillbuf(), then use it. If the system can tell you how many characters
8522 * are available in its buffers, then read that amount (but not less than 1).
8523 * If the system can return a special indication when you try to read without
8524 * anything to read, while allowing you to read all there is when there is
8525 * something, you may loop until there is something to read, but probably that
8526 * is not good for the system load.
8527 */
8528
8529 #ifdef SVORPOSIX
8530 /* This is for System III/V with VMIN>0, VTIME=0 and O_NDELAY off,
8531 * and CLOCAL set any way you like. This way, read() will do exactly
8532 * what is required by myfillbuf(): If there is data in the buffers
8533 * of the O.S., all available data is read into mybuf, up to the size
8534 * of mybuf. If there is none, the first character to arrive is
8535 * awaited and returned.
8536 */
8537 int
myfillbuf()8538 myfillbuf() {
8539 int fd, n;
8540 #ifdef NETCMD
8541 if (ttpipe)
8542 fd = fdin;
8543 else
8544 #endif /* NETCMD */
8545 fd = ttyfd;
8546
8547 #ifdef sxaE50
8548 /* From S. Dezawa at Fujifilm in Japan. I don't know why this is */
8549 /* necessary for the sxa E50, but it is. */
8550 return read(fd, mybuf, 255);
8551 #else
8552 #ifdef BEOSORBEBOX
8553 while (1) {
8554 #ifdef NETCONN
8555 if (netconn) {
8556 n = netxin(sizeof(mybuf), (char *)mybuf);
8557 debug(F101,"BEBOX SVORPOSIX network myfillbuf","",n);
8558 }
8559 else
8560 #endif /* NETCONN */
8561 n = read(fd, mybuf, sizeof(mybuf));
8562 debug(F101,"BEBOX SVORPOSIX notnet myfillbuf","",n);
8563 if (n > 0)
8564 return(n);
8565 snooze(1000.0);
8566 }
8567 #else /* BEOSORBEBOX */
8568 errno = 0;
8569 /* debug(F101,"SVORPOSIX myfillbuf calling read() fd","",fd); */
8570 #ifdef IBMX25
8571 if (netconn && (nettype == NET_IX25)) {
8572 /* can't use sizeof because mybuf is a pointer, and not an array! */
8573 n = x25xin( MYBUFLEN, mybuf );
8574 } else
8575 #endif /* IBMX25 */
8576
8577 #ifdef CK_SSL
8578 if (ssl_active_flag || tls_active_flag) {
8579 int error, n = 0;
8580 debug(F100,"myfillbuf calling SSL_read() fd","",0);
8581 while (n == 0) {
8582 if (ssl_active_flag)
8583 n = SSL_read(ssl_con, (char *)mybuf, sizeof(mybuf));
8584 else if (tls_active_flag)
8585 n = SSL_read(tls_con, (char *)mybuf, sizeof(mybuf));
8586 else
8587 break;
8588 switch (SSL_get_error(ssl_active_flag?ssl_con:tls_con,n)) {
8589 case SSL_ERROR_NONE:
8590 if (n > 0)
8591 return(n);
8592 if (n < 0)
8593 return(-2);
8594 msleep(50);
8595 break;
8596 case SSL_ERROR_WANT_WRITE:
8597 case SSL_ERROR_WANT_READ:
8598 return(-1);
8599 case SSL_ERROR_SYSCALL:
8600 if (n != 0)
8601 return(-1);
8602 case SSL_ERROR_WANT_X509_LOOKUP:
8603 case SSL_ERROR_SSL:
8604 case SSL_ERROR_ZERO_RETURN:
8605 default:
8606 ttclos(0);
8607 return(-3);
8608 }
8609 }
8610 }
8611 #endif /* CK_SSL */
8612 #ifdef CK_KERBEROS
8613 #ifdef KRB4
8614 #ifdef RLOGCODE
8615 if (ttnproto == NP_EK4LOGIN) {
8616 debug(F101,"myfillbuf calling krb4_des_read() fd","",ttyfd);
8617 if ((n = krb4_des_read(ttyfd,(char *)mybuf,sizeof(mybuf))) < 0)
8618 return(-3);
8619 else
8620 return(n);
8621 }
8622 #endif /* RLOGCODE */
8623 #endif /* KRB4 */
8624 #ifdef KRB5
8625 #ifdef RLOGCODE
8626 if (ttnproto == NP_EK5LOGIN) {
8627 debug(F101,"myfillbuf calling krb5_des_read() fd","",ttyfd);
8628 if ((n = krb5_des_read(ttyfd,(char *)mybuf,sizeof(mybuf),0)) < 0)
8629 return(-3);
8630 else
8631 return(n);
8632 }
8633 #endif /* RLOGCODE */
8634 #ifdef KRB5_U2U
8635 if (ttnproto == NP_K5U2U) {
8636 debug(F101,"myfillbuf calling krb5_u2u_read() fd","",ttyfd);
8637 if ((n = krb5_u2u_read(ttyfd,(char *)mybuf,sizeof(mybuf))) < 0)
8638 return(-3);
8639 else
8640 return(n);
8641 }
8642 #endif /* KRB5_U2U */
8643 #endif /* KRB5 */
8644 #endif /* CK_KERBEROS */
8645
8646 #ifdef NETPTY
8647 #ifdef HAVE_PTYTRAP
8648 /* Special handling for HP-UX pty i/o */
8649 ptyread:
8650 if (ttpty && pty_trap_pending(ttyfd) > 0) {
8651 debug(F101,"myfillbuf calling pty_trap_handler() fd","",ttyfd);
8652 if (pty_trap_handler(ttyfd) > 0) {
8653 ttclos(0);
8654 return(-3);
8655 }
8656 }
8657 #endif /* HAVE_PTYTRAP */
8658 #endif /* NETPTY */
8659 debug(F101,"myfillbuf calling read() fd","",ttyfd);
8660 n = read(fd, mybuf, sizeof(mybuf));
8661 debug(F101,"SVORPOSIX myfillbuf read","",n);
8662 debug(F101,"SVORPOSIX myfillbuf errno","",errno);
8663 debug(F101,"SVORPOSIX myfillbuf ttcarr","",ttcarr);
8664 if (n < 1) {
8665 #ifdef NETPTY
8666 #ifdef HAVE_PTYTRAP
8667 /* When we have a PTY trap in place the connection cannot */
8668 /* be closed until the trap receives a close indication. */
8669 if (n == 0 && ttpty)
8670 goto ptyread;
8671 #endif /* HAVE_PTYTRAP */
8672 #endif /* NETPTY */
8673 return(-3);
8674 }
8675 return(n);
8676 #endif /* BEOSORBEBOX */
8677 #endif /* sxaE50 */
8678 }
8679
8680 #else /* not AT&T or POSIX */
8681
8682 #ifdef aegis
8683 /* This is quoted from the old myread(). The semantics seem to be
8684 * alright, but maybe errno would not need to be set even when
8685 * there is no error? I don't know aegis.
8686 */
8687 int
myfillbuf()8688 myfillbuf() {
8689 int count;
8690 #ifdef NETCMD
8691 if (ttpipe)
8692 fd = fdin;
8693 else
8694 #endif /* NETCMD */
8695 fd = ttyfd;
8696
8697 count = ios_$get((short)fd, ios_$cond_opt, mybuf, 256L, st);
8698 errno = EIO;
8699 if (st.all == ios_$get_conditional_failed) /* get at least one */
8700 count = ios_$get((short)fd, 0, mybuf, 1L, st);
8701 if (st.all == ios_$end_of_file)
8702 return(-3);
8703 else if (st.all != status_$ok) {
8704 errno = EIO;
8705 return(-1);
8706 }
8707 return(count > 0 ? count : -3);
8708 }
8709 #else /* !aegis */
8710
8711 #ifdef FIONREAD
8712 /* This is for systems with FIONREAD. FIONREAD returns the number
8713 * of characters available for reading. If none are available, wait
8714 * until something arrives, otherwise return all there is.
8715 */
8716 int
myfillbuf()8717 myfillbuf() {
8718 PEEKTYPE avail = 0;
8719 int x, fd;
8720 #ifdef NETCMD
8721 if (ttpipe)
8722 fd = fdin;
8723 else
8724 #endif /* NETCMD */
8725 fd = ttyfd;
8726
8727 #ifdef SUNX25
8728 /*
8729 SunLink X.25 support in this routine from Stefaan A. Eeckels, Eurostat (CEC).
8730 Depends on SunOS having FIONREAD, not because we use it, but just so this
8731 code is grouped correctly within the #ifdefs. Let's hope Solaris keeps it.
8732
8733 We call x25xin() instead of read() so that Q-Bit packets, which contain
8734 X.25 service-level information (e.g. PAD parameter changes), can be processed
8735 transparently to the upper-level code. This is a blocking read, and so
8736 we depend on higher-level code (such as ttinc()) to set any necessary alarms.
8737 */
8738 extern int nettype;
8739 if (netconn && nettype == NET_SX25) {
8740 while ((x = x25xin(sizeof(x25buf), x25buf)) < 1) ;
8741 return(x - 1); /* "-1" compensates for extra status byte */
8742 }
8743 #endif /* SUNX25 */
8744
8745 #ifdef CK_SSL
8746 if (ssl_active_flag || tls_active_flag) {
8747 int error, n = 0;
8748 while (n == 0) {
8749 if (ssl_active_flag)
8750 n = SSL_read(ssl_con, (char *)mybuf, sizeof(mybuf));
8751 else
8752 n = SSL_read(tls_con, (char *)mybuf, sizeof(mybuf));
8753 switch (SSL_get_error(ssl_active_flag?ssl_con:tls_con,n)) {
8754 case SSL_ERROR_NONE:
8755 if (n > 0)
8756 return(n);
8757 if (n < 0)
8758 return(-2);
8759 msleep(50);
8760 break;
8761 case SSL_ERROR_WANT_WRITE:
8762 case SSL_ERROR_WANT_READ:
8763 return(-1);
8764 case SSL_ERROR_SYSCALL:
8765 if (n != 0)
8766 return(-1);
8767 case SSL_ERROR_WANT_X509_LOOKUP:
8768 case SSL_ERROR_SSL:
8769 case SSL_ERROR_ZERO_RETURN:
8770 default:
8771 ttclos(0);
8772 return(-2);
8773 }
8774 }
8775 }
8776 #endif /* CK_SSL */
8777 #ifdef CK_KERBEROS
8778 #ifdef KRB4
8779 #ifdef RLOGCODE
8780 if (ttnproto == NP_EK4LOGIN) {
8781 if ((x = krb4_des_read(ttyfd,mybuf,sizeof(mybuf))) < 0)
8782 return(-1);
8783 else
8784 return(x);
8785 }
8786 #endif /* RLOGCODE */
8787 #endif /* KRB4 */
8788 #ifdef KRB5
8789 #ifdef RLOGCODE
8790 if (ttnproto == NP_EK5LOGIN) {
8791 if ((x = krb5_des_read(ttyfd,mybuf,sizeof(mybuf),0)) < 0)
8792 return(-1);
8793 else
8794 return(x);
8795 }
8796 #endif /* RLOGCODE */
8797 #ifdef KRB5_U2U
8798 if (ttnproto == NP_K5U2U) {
8799 if ((x = krb5_u2u_read(ttyfd,mybuf,sizeof(mybuf))) < 0)
8800 return(-1);
8801 else
8802 return(x);
8803 }
8804 #endif /* KRB5_U2U */
8805 #endif /* KRB5 */
8806 #endif /* CK_KERBEROS */
8807
8808 errno = 0;
8809 debug(F101,"myfillbuf calling FIONREAD ioctl","",xlocal);
8810 x = ioctl(fd, FIONREAD, &avail);
8811 #ifdef DEBUG
8812 if (deblog) {
8813 debug(F101,"myfillbuf FIONREAD","",x);
8814 debug(F101,"myfillbuf FIONREAD avail","",avail);
8815 debug(F101,"myfillbuf FIONREAD errno","",errno);
8816 }
8817 #endif /* DEBUG */
8818 if (x < 0 || avail == 0)
8819 avail = 1;
8820
8821 if (avail > MYBUFLEN)
8822 avail = MYBUFLEN;
8823
8824 errno = 0;
8825
8826 x = read(fd, mybuf, (int) avail);
8827 #ifdef DEBUG
8828 if (deblog) {
8829 debug(F101,"myfillbuf avail","",avail);
8830 debug(F101,"myfillbuf read","",x);
8831 debug(F101,"myfillbuf read errno","",errno);
8832 if (x > 0)
8833 ckhexdump("myfillbuf mybuf",mybuf,x);
8834 }
8835 #endif /* DEBUG */
8836 if (x < 1) x = -3; /* read 0 == connection loss */
8837 return(x);
8838 }
8839
8840 #else /* !FIONREAD */
8841 /* Add other systems here, between #ifdef and #else, e.g. NETCONN. */
8842 /* When there is no other possibility, read 1 character at a time. */
8843 int
myfillbuf()8844 myfillbuf() {
8845 int x;
8846
8847 #ifdef CK_SSL
8848 if (ssl_active_flag || tls_active_flag) {
8849 int error, n = 0;
8850 while (n == 0) {
8851 if (ssl_active_flag)
8852 n = SSL_read(ssl_con, (char *)mybuf, sizeof(mybuf));
8853 else
8854 count = SSL_read(tls_con, (char *)mybuf, sizeof(mybuf));
8855 switch (SSL_get_error(ssl_active_flag?ssl_con:tls_con,n)) {
8856 case SSL_ERROR_NONE:
8857 if (n > 0)
8858 return(n);
8859 if (n < 0)
8860 return(-2);
8861 msleep(50);
8862 break;
8863 case SSL_ERROR_WANT_WRITE:
8864 case SSL_ERROR_WANT_READ:
8865 return(-1);
8866 case SSL_ERROR_SYSCALL:
8867 if (n != 0)
8868 return(-1);
8869 case SSL_ERROR_WANT_X509_LOOKUP:
8870 case SSL_ERROR_SSL:
8871 case SSL_ERROR_ZERO_RETURN:
8872 default:
8873 ttclos(0);
8874 return(-2);
8875 }
8876 }
8877 }
8878 #endif /* CK_SSL */
8879 #ifdef CK_KERBEROS
8880 #ifdef KRB4
8881 #ifdef RLOGCODE
8882 if (ttnproto == NP_EK4LOGIN) {
8883 if ((len = krb4_des_read(ttyfd,mybuf,sizeof(mybuf))) < 0)
8884 return(-1);
8885 else
8886 return(len);
8887 }
8888 #endif /* RLOGCODE */
8889 #endif /* KRB4 */
8890 #ifdef KRB5
8891 #ifdef RLOGCODE
8892 if (ttnproto == NP_EK5LOGIN) {
8893 if ((len = krb5_des_read(ttyfd,mybuf,sizeof(mybuf),0)) < 0)
8894 return(-1);
8895 else
8896 return(len);
8897 }
8898 #endif /* RLOGCODE */
8899 #ifdef KRB5_U2U
8900 if (ttnproto == NP_K5U2U) {
8901 if ((len = krb5_u2u_read(ttyfd,mybuf,sizeof(mybuf))) < 0)
8902 return(-1);
8903 else
8904 return(len);
8905 }
8906 #endif /* KRB5_U2U */
8907 #endif /* KRB5 */
8908 #endif /* CK_KERBEROS */
8909
8910 #ifdef NETCMD
8911 if (ttpipe)
8912 fd = fdin;
8913 else
8914 #endif /* NETCMD */
8915 fd = ttyfd;
8916 x = read(fd, mybuf, 1);
8917 return(x > 0 ? x : -3);
8918 }
8919
8920 #endif /* !FIONREAD */
8921 #endif /* !aegis */
8922 #endif /* !ATTSV */
8923
8924 #endif /* MYREAD */
8925
8926 /* T T _ T N O P T -- Handle Telnet negotions in incoming data */
8927 /*
8928 Call with the IAC that was encountered.
8929 Returns:
8930 -3: If connection has dropped or gone bad.
8931 -2: On Telnet protocol error resulting in inconsistent states.
8932 0: If negotiation OK and caller has nothing to do.
8933 1: If packet start character has changed (new value is in global stchr).
8934 255: If there was a quoted IAC as data.
8935 or: Not at all if we got a legitimate Telnet Logout request.
8936 */
8937 #ifdef TCPSOCKET
8938 static int
tt_tnopt(n)8939 tt_tnopt(n) int n; { /* Handle Telnet options */
8940 /* In case caller did not already check these conditions... */
8941 if (n == IAC &&
8942 ((xlocal && netconn && IS_TELNET()) ||
8943 (!xlocal && sstelnet))) {
8944 extern int server;
8945 int tx = 0;
8946 debug(F100,"ttinl calling tn_doop()","",0);
8947 tx = tn_doop((CHAR)(n & 0xff),duplex,ttinc);
8948 debug(F111,"ttinl tn_doop() returned","tx",tx);
8949 switch (tx) {
8950 case 0:
8951 return(0);
8952 case -1: /* I/O error */
8953 ttimoff(); /* Turn off timer */
8954 return(-3);
8955 case -2: /* Connection failed. */
8956 case -3:
8957 ttimoff(); /* Turn off timer */
8958 ttclos(0);
8959 return(-3);
8960 case 1: /* ECHO change */
8961 duplex = 1;
8962 return(0);
8963 case 2: /* ECHO change */
8964 duplex = 0;
8965 return(0);
8966 case 3: /* Quoted IAC */
8967 n = 255;
8968 return((unsigned)255);
8969 #ifdef IKS_OPTION
8970 case 4: {
8971 if (TELOPT_SB(TELOPT_KERMIT).kermit.u_start && server
8972 #ifdef IKSD
8973 && !inserver
8974 #endif /* IKSD */
8975 ) { /* Remote in Server mode */
8976 ttimoff(); /* Turn off timer */
8977 debug(F100,"u_start and !inserver","",0);
8978 return(-2); /* End server mode */
8979 } else if (!TELOPT_SB(TELOPT_KERMIT).kermit.me_start &&
8980 server
8981 ) { /* I'm no longer in Server Mode */
8982 debug(F100,"me_start and server","",0);
8983 ttimoff();
8984 return(-2);
8985 }
8986 return(0);
8987 }
8988 case 5: { /* Start character change */
8989 /* extern CHAR stchr; */
8990 /* start = stchr; */
8991 return(1);
8992 }
8993 #endif /* IKS_OPTION */
8994 case 6: /* Remote Logout */
8995 ttimoff();
8996 ttclos(0);
8997 #ifdef IKSD
8998 if (inserver && !local)
8999 doexit(GOOD_EXIT,0);
9000 else
9001 #endif /* IKSD */
9002 return(-2);
9003 default:
9004 return(0);
9005 }
9006 } else
9007 return(0);
9008 }
9009 #endif /* TCPSOCKET */
9010
9011 /* T T F L U I -- Flush tty input buffer */
9012
9013 void
ttflux()9014 ttflux() { /* But first... */
9015 #ifdef MYREAD
9016 /*
9017 Flush internal MYREAD buffer.
9018 */
9019 #ifdef TCPSOCKET
9020 int dotnopts, x;
9021 dotnopts = (((xlocal && netconn && IS_TELNET()) ||
9022 (!xlocal && sstelnet)));
9023 #endif /* TCPSOCKET */
9024 debug(F101,"ttflux my_count","",my_count);
9025 #ifdef TCPSOCKET
9026 if (dotnopts) {
9027 CHAR ch = '\0';
9028 while (my_count > 0) {
9029 ch = myread();
9030 #ifdef CK_ENCRYPTION
9031 if (TELOPT_U(TELOPT_ENCRYPTION))
9032 ck_tn_decrypt((char *)&ch,1);
9033 #endif /* CK_ENCRYPTION */
9034 if (ch == IAC)
9035 x = tt_tnopt(ch);
9036 }
9037 } else
9038 #endif /* TCPSOCKET */
9039 #ifdef COMMENT
9040 #ifdef CK_ENCRYPTION
9041 if (TELOPT_U(TELOPT_ENCRYPTION) && my_count > 0)
9042 ck_tn_decrypt(&mybuf[my_item+1],my_count);
9043 #endif /* CK_ENCRYPTION */
9044 #endif /* COMMENT */
9045 my_count = 0; /* Reset count to zero */
9046 my_item = -1; /* And buffer index to -1 */
9047 #endif /* MYREAD */
9048 }
9049
9050 int
ttflui()9051 ttflui() {
9052 int n, fd;
9053 #ifdef TCPSOCKET
9054 int dotnopts;
9055 dotnopts = (((xlocal && netconn && IS_TELNET()) ||
9056 (!xlocal && sstelnet)));
9057 #endif /* TCPSOCKET */
9058
9059 #ifdef NETCMD
9060 if (ttpipe)
9061 fd = fdin;
9062 else
9063 #endif /* NETCMD */
9064 fd = ttyfd;
9065
9066 #ifdef TTLEBUF
9067 ttpush = -1; /* Clear the peek-ahead char */
9068 while (le_data && (le_inbuf() > 0)) {
9069 CHAR ch = '\0';
9070 if (le_getchar(&ch) > 0) { /* Clear any more... */
9071 debug(F101,"ttflui le_inbuf ch","",ch);
9072 }
9073 }
9074 #endif /* TTLEBUF */
9075 debug(F101,"ttflui ttpipe","",ttpipe);
9076
9077 #ifdef MYREAD
9078 /*
9079 Flush internal MYREAD buffer *NEXT*, in all cases.
9080 */
9081 ttflux();
9082 #endif /* MYREAD */
9083
9084 #ifdef NETCONN
9085 /* Network flush is done specially, in the network support module. */
9086 if ((netconn || sstelnet) && !ttpipe && !ttpty) {
9087 debug(F100,"ttflui netflui","",0);
9088 #ifdef COMMENT
9089 #ifdef TN_COMPORT
9090 if (istncomport())
9091 tnc_send_purge_data(TNC_PURGE_RECEIVE);
9092 #endif /* TN_COMPORT */
9093 #endif /* COMMENT */
9094 return(netflui());
9095 }
9096 #endif /* NETCONN */
9097
9098 debug(F101,"ttflui ttyfd","",ttyfd); /* Not network */
9099 if (ttyfd < 0)
9100 return(-1);
9101
9102 #ifdef aegis
9103 sio_$control((short)yfd, sio_$flush_in, true, st);
9104 if (st.all != status_$ok) {
9105 fprintf(stderr, "flush failed: "); error_$print(st);
9106 } else { /* sometimes the flush doesn't work */
9107 for (;;) {
9108 char buf[256];
9109 /* eat all the characters that shouldn't be available */
9110 ios_$get((short)fd, ios_$cond_opt, buf, 256L, st); /* (void) */
9111 if (st.all == ios_$get_conditional_failed) break;
9112 fprintf(stderr, "flush failed(2): "); error_$print(st);
9113 }
9114 }
9115 #else
9116 #ifdef BSD44 /* 4.4 BSD */
9117 n = FREAD; /* Specify read queue */
9118 debug(F100,"ttflui BSD44","",0);
9119 ioctl(fd,TIOCFLUSH,&n);
9120 #else
9121 #ifdef Plan9
9122 #undef POSIX /* Uh oh... */
9123 #endif /* Plan9 */
9124 #ifdef POSIX /* POSIX */
9125 debug(F100,"ttflui POSIX","",0);
9126 tcflush(fd,TCIFLUSH);
9127 #else
9128 #ifdef ATTSV /* System V */
9129 #ifndef VXVE
9130 debug(F100,"ttflui ATTSV","",0);
9131 ioctl(fd,TCFLSH,0);
9132 #endif /* VXVE */
9133 #else /* Not BSD44, POSIX, or Sys V */
9134 #ifdef TIOCFLUSH /* Those with TIOCFLUSH defined */
9135 #ifdef ANYBSD /* Berkeley */
9136 n = FREAD; /* Specify read queue */
9137 debug(F100,"ttflui TIOCFLUSH ANYBSD","",0);
9138 ioctl(fd,TIOCFLUSH,&n);
9139 #else /* Others (V7, etc) */
9140 debug(F100,"ttflui TIOCFLUSH","",0);
9141 ioctl(fd,TIOCFLUSH,0);
9142 #endif /* ANYBSD */
9143 #else /* All others... */
9144 /*
9145 No system call (that we know about) for input buffer flushing.
9146 So see how many there are and read them in a loop, using ttinc().
9147 ttinc() is buffered, so we're not getting charged with a system call
9148 per character, just a function call.
9149 */
9150 if ((n = ttchk()) > 0) {
9151 debug(F101,"ttflui read loop","",n);
9152 while ((n--) && ttinc(0) > 0) ;
9153 }
9154 #endif /* TIOCFLUSH */
9155 #endif /* ATTSV */
9156 #endif /* POSIX */
9157 #ifdef Plan9
9158 #define POSIX
9159 #endif /* Plan9 */
9160 #endif /* BSD44 */
9161 #endif /* aegis */
9162 return(0);
9163 }
9164
9165 int
ttfluo()9166 ttfluo() { /* Flush output buffer */
9167 int fd;
9168 #ifdef NETCMD
9169 if (ttpipe)
9170 fd = fdout;
9171 else
9172 #endif /* NETCMD */
9173 fd = ttyfd;
9174
9175 #ifdef Plan9
9176 return 0;
9177 #else
9178 #ifdef POSIX
9179 return(tcflush(fd,TCOFLUSH));
9180 #else
9181 #ifdef OXOS
9182 return(ioctl(fd,TCFLSH,1));
9183 #else
9184 return(0); /* All others, nothing */
9185 #endif /* OXOS */
9186 #endif /* POSIX */
9187 #endif /* Plan9 */
9188 }
9189
9190 /* Interrupt Functions */
9191
9192 /* Set up terminal interrupts on console terminal */
9193
9194 #ifndef FIONREAD /* We don't need esctrp() */
9195 #ifndef SELECT /* if we have any of these... */
9196 #ifndef CK_POLL
9197 #ifndef RDCHK
9198
9199 #ifndef OXOS
9200 #ifdef SVORPOSIX
9201 SIGTYP
esctrp(foo)9202 esctrp(foo) int foo; { /* trap console escapes (^\) */
9203 signal(SIGQUIT,SIG_IGN); /* ignore until trapped */
9204 conesc = 1;
9205 debug(F101,"esctrp caught SIGQUIT","",conesc);
9206 }
9207 #endif /* SVORPOSIX */
9208 #endif /* OXOS */
9209
9210 #ifdef V7
9211 #ifndef MINIX2
9212 SIGTYP
esctrp(foo)9213 esctrp(foo) int foo; { /* trap console escapes (^\) */
9214 signal(SIGQUIT,SIG_IGN); /* ignore until trapped */
9215 conesc = 1;
9216 debug(F101,"esctrp caught SIGQUIT","",conesc);
9217 }
9218 #endif /* MINIX2 */
9219 #endif /* V7 */
9220
9221 #ifdef C70
9222 SIGTYP
esctrp(foo)9223 esctrp(foo) int foo; { /* trap console escapes (^\) */
9224 conesc = 1;
9225 signal(SIGQUIT,SIG_IGN); /* ignore until trapped */
9226 }
9227 #endif /* C70 */
9228
9229 #endif /* RDCHK */
9230 #endif /* CK_POLL */
9231 #endif /* SELECT */
9232 #endif /* FIONREAD */
9233
9234 /* C O N B G T -- Background Test */
9235
9236 static int jc = 0; /* 0 = no job control */
9237
9238 /*
9239 Call with flag == 1 to prevent signal test, which can not be expected
9240 to work during file transfer, when SIGINT probably *is* set to SIG_IGN.
9241
9242 Call with flag == 0 to use the signal test, but only if the process-group
9243 test fails, as it does on some UNIX systems, where getpgrp() is buggy,
9244 requires an argument when the man page says it doesn't, or vice versa.
9245
9246 If flag == 0 and the process-group test fails, then we determine background
9247 status simply (but not necessarily reliably) from isatty().
9248
9249 conbgt() sets the global backgrd = 1 if we appear to be in the background,
9250 and to 0 if we seem to be in the foreground. conbgt() is highly prone to
9251 misbehavior.
9252 */
9253 VOID
conbgt(flag)9254 conbgt(flag) int flag; {
9255 int x = -1, /* process group or SIGINT test */
9256 y = 0; /* isatty() test */
9257 /*
9258 Check for background operation, even if not running on real tty, so that
9259 background flag can be set correctly. If background status is detected,
9260 then Kermit will not issue its interactive prompt or most messages.
9261 If your prompt goes away, you can blame (and fix?) this function.
9262 */
9263
9264 /* Use process-group test if possible. */
9265
9266 #ifdef POSIX /* We can do it in POSIX */
9267 #define PGROUP_T
9268 #else
9269 #ifdef BSD4 /* and in BSD 4.x. */
9270 #define PGROUP_T
9271 #else
9272 #ifdef HPUXJOBCTL /* and in most HP-UX's */
9273 #define PGROUP_T
9274 #else
9275 #ifdef TIOCGPGRP /* and anyplace that has this ioctl. */
9276 #define PGROUP_T
9277 #endif /* TIOCGPGRP */
9278 #endif /* HPUXJOBCTL */
9279 #endif /* BSD4 */
9280 #endif /* POSIX */
9281
9282 #ifdef MIPS /* Except if it doesn't work... */
9283 #undef PGROUP_T
9284 #endif /* MIPS */
9285
9286 #ifdef MINIX
9287 #undef PGROUP_T
9288 #endif /* MINIX */
9289
9290 #ifdef PGROUP_T
9291 /*
9292 Semi-reliable process-group test. Check whether this process's group is
9293 the same as the controlling terminal's process group. This works if the
9294 getpgrp() call doesn't lie (as it does in the SUNOS System V environment).
9295 */
9296 PID_T mypgrp = (PID_T)0; /* Kermit's process group */
9297 PID_T ctpgrp = (PID_T)0; /* The terminal's process group */
9298 #ifndef _POSIX_SOURCE
9299 /*
9300 The getpgrp() prototype is obtained from system header files for POSIX
9301 and Sys V R4 compilations. Other systems, who knows. Some complain about
9302 a duplicate declaration here, others don't, so it's safer to leave it in
9303 if we don't know for certain.
9304 */
9305 #ifndef SVR4
9306 #ifndef PS2AIX10
9307 #ifndef HPUX9
9308 extern PID_T getpgrp();
9309 #endif /* HPUX9 */
9310 #endif /* PS2AIX10 */
9311 #endif /* SVR4 */
9312 #endif /* _POSIX_SOURCE */
9313
9314 /* Get my process group. */
9315
9316 #ifdef SVR3 /* Maybe this should be ATTSV? */
9317 /* This function is not described in SVID R2 */
9318 mypgrp = getpgrp();
9319 /* debug(F101,"ATTSV conbgt process group","",(int) mypgrp); */
9320 #else
9321 #ifdef POSIX
9322 mypgrp = getpgrp();
9323 /* debug(F101,"POSIX conbgt process group","",(int) mypgrp); */
9324 #else
9325 #ifdef OSFPC
9326 mypgrp = getpgrp();
9327 /* debug(F101,"OSF conbgt process group","",(int) mypgrp); */
9328 #else
9329 #ifdef QNX
9330 mypgrp = getpgrp();
9331 /* debug(F101,"QNX conbgt process group","",(int) mypgrp); */
9332 #else
9333 #ifdef OSF32 /* (was OSF40) */
9334 mypgrp = getpgrp();
9335 /* debug(F101,"Digital UNIX conbgt process group","",(int) mypgrp); */
9336 #else /* BSD, V7, etc */
9337 #ifdef MINIX2
9338 mypgrp = getpgrp();
9339 #else
9340 mypgrp = getpgrp(0);
9341 #endif /* MINIX2 */
9342 /* debug(F101,"BSD conbgt process group","",(int) mypgrp); */
9343 #endif /* OSF32 */
9344 #endif /* QNX */
9345 #endif /* OSFPC */
9346 #endif /* POSIX */
9347 #endif /* SVR3 */
9348
9349 #ifdef MINIX
9350 /* MINIX does not support job control so Kermit is always in foreground */
9351 x = 0;
9352
9353 #else /* Not MINIX */
9354
9355 /* Now get controlling tty's process group */
9356 #ifdef BSD44ORPOSIX
9357 ctpgrp = tcgetpgrp(1); /* The POSIX way */
9358 /* debug(F101,"POSIX conbgt terminal process group","",(int) ctpgrp); */
9359 #else
9360 ioctl(1, TIOCGPGRP, &ctpgrp); /* Or the BSD way */
9361 /* debug(F101,"non-POSIX conbgt terminal process group","",(int) ctpgrp); */
9362 #endif /* BSD44ORPOSIX */
9363
9364 if ((mypgrp > (PID_T) 0) && (ctpgrp > (PID_T) 0))
9365 x = (mypgrp == ctpgrp) ? 0 : 1; /* If they differ, then background. */
9366 else x = -1; /* If error, remember. */
9367 debug(F101,"conbgt process group test","",x);
9368 #endif /* PGROUP_T */
9369 #endif /* MINIX */
9370
9371 /* Try to see if job control is available */
9372
9373 #ifdef NOJC /* User override */
9374 jc = 0; /* No job control allowed */
9375 debug(F111,"NOJC","jc",jc);
9376 #else
9377 #ifdef BSD44
9378 jc = 1;
9379 #else
9380 #ifdef SVR4ORPOSIX /* POSIX actually tells us */
9381 debug(F100,"SVR4ORPOSIX jc test...","",0);
9382 #ifdef _SC_JOB_CONTROL
9383 #ifdef __bsdi__
9384 jc = 1;
9385 #else
9386 #ifdef __386BSD__
9387 jc = 1;
9388 #else
9389 jc = sysconf(_SC_JOB_CONTROL); /* Whatever system says */
9390 if (jc < 0) {
9391 debug(F101,"sysconf fails, jcshell","",jcshell);
9392 jc = (jchdlr == SIG_DFL) ? 1 : 0;
9393 } else
9394 debug(F111,"sysconf(_SC_JOB_CONTROL)","jc",jc);
9395 #endif /* __386BSD__ */
9396 #endif /* __bsdi__ */
9397 #else
9398 #ifdef _POSIX_JOB_CONTROL
9399 jc = 1; /* By definition */
9400 debug(F111,"_POSIX_JOB_CONTROL is defined","jc",jc);
9401 #else
9402 jc = 0; /* Assume job control not allowed */
9403 debug(F111,"SVR4ORPOSIX _SC/POSIX_JOB_CONTROL not defined","jc",jc);
9404 #endif /* _POSIX_JOB_CONTROL */
9405 #endif /* _SC_JOB_CONTROL */
9406 #else
9407 #ifdef BSD4
9408 jc = 1; /* Job control allowed */
9409 debug(F111,"BSD job control","jc",jc);
9410 #else
9411 #ifdef SVR3JC
9412 jc = 1; /* JC allowed */
9413 debug(F111,"SVR3 job control","jc",jc);
9414 #else
9415 #ifdef OXOS
9416 jc = 1; /* JC allowed */
9417 debug(F111,"X/OS job control","jc",jc);
9418 #else
9419 #ifdef HPUX9
9420 jc = 1; /* JC allowed */
9421 debug(F111,"HP-UX 9.0 job control","jc",jc);
9422 #else
9423 #ifdef HPUX10
9424 jc = 1; /* JC allowed */
9425 debug(F111,"HP-UX 10.0 job control","jc",jc);
9426 #else
9427 jc = 0; /* JC not allowed */
9428 debug(F111,"job control catch-all","jc",jc);
9429 #endif /* HPUX10 */
9430 #endif /* HPUX9 */
9431 #endif /* OXOS */
9432 #endif /* SVR3JC */
9433 #endif /* BSD4 */
9434 #endif /* SVR4ORPOSIX */
9435 #endif /* BSD44 */
9436 #endif /* NOJC */
9437 debug(F101,"conbgt jc","",jc);
9438 #ifndef NOJC
9439 debug(F101,"conbgt jcshell","",jcshell);
9440 /*
9441 At this point, if jc == 1 but jcshell == 0, it means that the OS supports
9442 job control, but the shell or other process we are running under does not
9443 (jcshell is set in sysinit()) and so if we suspend ourselves, nothing good
9444 will come of it. So...
9445 */
9446 if (jc < 0) jc = 0;
9447 if (jc > 0 && jcshell == 0) jc = 0;
9448 #endif /* NOJC */
9449
9450 /*
9451 Another background test.
9452 Test if SIGINT (terminal interrupt) is set to SIG_IGN (ignore),
9453 which is done by the shell (sh) if the program is started with '&'.
9454 Unfortunately, this is NOT done by csh or ksh so watch out!
9455 Note, it's safe to set SIGINT to SIG_IGN here, because further down
9456 we always set it to something else.
9457 Note: as of 16 Jul 1999, we also skip this test if we set SIGINT to
9458 SIG_IGN ourselves.
9459 */
9460 if (x < 0 && !flag && !sigint_ign) { /* Didn't get good results above... */
9461
9462 SIGTYP (*osigint)();
9463
9464 osigint = signal(SIGINT,SIG_IGN); /* What is SIGINT set to? */
9465 sigint_ign = 1;
9466 x = (osigint == SIG_IGN) ? 1 : 0; /* SIG_IGN? */
9467 /* debug(F101,"conbgt osigint","",osigint); */
9468 /* debug(F101,"conbgt signal test","",x); */
9469 }
9470
9471 /* Also check to see if we're running with redirected stdio. */
9472 /* This is not really background operation, but we want to act as though */
9473 /* it were. */
9474
9475 #ifdef IKSD
9476 if (inserver) { /* Internet Kermit Server */
9477 backgrd = 0; /* is not in the background */
9478 return;
9479 }
9480 #endif /* IKSD */
9481
9482 y = (isatty(0) && isatty(1)) ? 1 : 0;
9483 debug(F101,"conbgt isatty test","",y);
9484
9485 #ifdef BSD29
9486 /* The process group and/or signal test doesn't work under these... */
9487 backgrd = !y;
9488 #else
9489 #ifdef sxaE50
9490 backgrd = !y;
9491 #else
9492 #ifdef MINIX
9493 backgrd = !y;
9494 #else
9495 #ifdef MINIX2
9496 backgrd = !y;
9497 #else
9498 if (x > -1)
9499 backgrd = (x || !y) ? 1 : 0;
9500 else backgrd = !y;
9501 #endif /* BSD29 */
9502 #endif /* sxaE50 */
9503 #endif /* MINIX */
9504 #endif /* MINIX2 */
9505 debug(F101,"conbgt backgrd","",backgrd);
9506 }
9507
9508 /* C O N I N T -- Console Interrupt setter */
9509
9510 /*
9511 First arg is pointer to function to handle SIGTERM & SIGINT (like Ctrl-C).
9512 Second arg is pointer to function to handle SIGTSTP (suspend).
9513 */
9514
9515 VOID /* Set terminal interrupt traps. */
9516 #ifdef CK_ANSIC
9517 #ifdef apollo
9518 conint(f,s) SIGTYP (*f)(), (*s)();
9519 #else
9520 conint(SIGTYP (*f)(int), SIGTYP (*s)(int))
9521 #endif /* apollo */
9522 #else
9523 conint(f,s) SIGTYP (*f)(), (*s)();
9524 #endif /* CK_ANSIC */
9525 /* conint */ {
9526
9527 debug(F101,"conint conistate","",conistate);
9528
9529 conbgt(0); /* Do background test. */
9530
9531 /* Set the desired handlers for hangup and software termination. */
9532
9533 #ifdef SIGTERM
9534 signal(SIGTERM,f); /* Software termination */
9535 #endif /* SIGTERM */
9536
9537 /*
9538 Prior to July 1999 we used to call sighup() here but now it's called in
9539 sysinit() so SIGHUP can be caught during execution of the init file or
9540 a kerbang script.
9541 */
9542
9543 /* Now handle keyboard stop, quit, and interrupt signals. */
9544 /* Check if invoked in background -- if so signals set to be ignored. */
9545 /* However, if running under a job control shell, don't ignore them. */
9546 /* We won't be getting any, as we aren't in the terminal's process group. */
9547
9548 debug(F101,"conint backgrd","",backgrd);
9549 debug(F101,"conint jc","",jc);
9550
9551 if (backgrd && !jc) { /* In background, ignore signals */
9552 debug(F101,"conint background ignoring signals, jc","",jc);
9553 #ifdef SIGTSTP
9554 signal(SIGTSTP,SIG_IGN); /* Keyboard stop */
9555 #endif /* SIGTSTP */
9556 signal(SIGQUIT,SIG_IGN); /* Keyboard quit */
9557 signal(SIGINT,SIG_IGN); /* Keyboard interrupt */
9558 sigint_ign = 1;
9559 conistate = CONI_NOI;
9560 } else { /* Else in foreground or suspended */
9561 debug(F101,"conint foreground catching signals, jc","",jc);
9562 signal(SIGINT,f); /* Catch terminal interrupt */
9563 sigint_ign = (f == SIG_IGN) ? 1 : 0;
9564
9565 #ifdef SIGTSTP /* Keyboard stop (suspend) */
9566 /* debug(F101,"conint SIGSTSTP","",s); */
9567 if (s == NULL) s = SIG_DFL;
9568 #ifdef NOJC /* No job control allowed. */
9569 signal(SIGTSTP,SIG_IGN);
9570 #else /* Job control allowed */
9571 if (jc) /* if available. */
9572 signal(SIGTSTP,s);
9573 else
9574 signal(SIGTSTP,SIG_IGN);
9575 #endif /* NOJC */
9576 #endif /* SIGTSTP */
9577
9578 #ifndef OXOS
9579 #ifdef SVORPOSIX
9580 #ifndef FIONREAD /* Watch out, we don't know this... */
9581 #ifndef SELECT
9582 #ifndef CK_POLL
9583 #ifndef RDCHK
9584 signal(SIGQUIT,esctrp); /* Quit signal, Sys III/V. */
9585 #endif /* RDCHK */
9586 #endif /* CK_POLL */
9587 #endif /* SELECT */
9588 #endif /* FIONREAD */
9589 if (conesc) conesc = 0; /* Clear out pending escapes */
9590 #else
9591 #ifdef V7
9592 signal(SIGQUIT,esctrp); /* V7 like Sys III/V */
9593 if (conesc) conesc = 0;
9594 #else
9595 #ifdef aegis
9596 signal(SIGQUIT,f); /* Apollo, catch it like others. */
9597 #else
9598 signal(SIGQUIT,SIG_IGN); /* Others, ignore like 4D & earlier. */
9599 #endif /* aegis */
9600 #endif /* V7 */
9601 #endif /* SVORPOSIX */
9602 #endif /* OXOS */
9603 conistate = CONI_INT;
9604 }
9605 }
9606
9607
9608 /* C O N N O I -- Reset console terminal interrupts */
9609
9610 VOID
connoi()9611 connoi() { /* Console-no-interrupts */
9612
9613 debug(F101,"connoi conistate","",conistate);
9614 #ifdef SIGTSTP
9615 signal(SIGTSTP,SIG_IGN); /* Suspend */
9616 #endif /* SIGTSTP */
9617 conint(SIG_IGN,SIG_IGN); /* Interrupt */
9618 sigint_ign = 1; /* Remember we did this ourselves */
9619 #ifdef SIGQUIT
9620 signal(SIGQUIT,SIG_IGN); /* Quit */
9621 #endif /* SIGQUIT */
9622 #ifdef SIGTERM
9623 signal(SIGTERM,SIG_IGN); /* Term */
9624 #endif /* SIGTERM */
9625 conistate = CONI_NOI;
9626 }
9627
9628 /* I N I T R A W Q -- Set up to read /dev/kmem for character count. */
9629
9630 #ifdef V7
9631 /*
9632 Used in Version 7 to simulate Berkeley's FIONREAD ioctl call. This
9633 eliminates blocking on a read, because we can read /dev/kmem to get the
9634 number of characters available for raw input. If your system can't
9635 or you won't let the world read /dev/kmem then you must figure out a
9636 different way to do the counting of characters available, or else replace
9637 this by a dummy function that always returns 0.
9638 */
9639 /*
9640 * Call this routine as: initrawq(tty)
9641 * where tty is the file descriptor of a terminal. It will return
9642 * (as a char *) the kernel-mode memory address of the rawq character
9643 * count, which may then be read. It has the side-effect of flushing
9644 * input on the terminal.
9645 */
9646 /*
9647 * John Mackin, Physiology Dept., University of Sydney (Australia)
9648 * ...!decvax!mulga!physiol.su.oz!john
9649 *
9650 * Permission is hereby granted to do anything with this code, as
9651 * long as this comment is retained unmodified and no commercial
9652 * advantage is gained.
9653 */
9654 #ifndef MINIX
9655 #ifndef MINIX2
9656 #ifndef COHERENT
9657 #include <a.out.h>
9658 #include <sys/proc.h>
9659 #endif /* COHERENT */
9660 #endif /* MINIX2 */
9661 #endif /* MINIX */
9662
9663 #ifdef COHERENT
9664 #include <l.out.h>
9665 #include <sys/proc.h>
9666 #endif /* COHERENT */
9667
9668 char *
initrawq(tty)9669 initrawq(tty) int tty; {
9670 #ifdef MINIX
9671 return(0);
9672 #else
9673 #ifdef MINIX2
9674 return(0);
9675 #else
9676 #ifdef UTS24
9677 return(0);
9678 #else
9679 #ifdef BSD29
9680 return(0);
9681 #else
9682 long lseek();
9683 static struct nlist nl[] = {
9684 {PROCNAME},
9685 {NPROCNAME},
9686 {""}
9687 };
9688 static struct proc *pp;
9689 char *qaddr, *p, c;
9690 int m;
9691 PID_T pid, me;
9692 NPTYPE xproc; /* Its type is defined in makefile. */
9693 int catch();
9694
9695 me = getpid();
9696 if ((m = open("/dev/kmem", 0)) < 0) err("kmem");
9697 nlist(BOOTNAME, nl);
9698 if (nl[0].n_type == 0) err("proc array");
9699
9700 if (nl[1].n_type == 0) err("nproc");
9701
9702 lseek(m, (long)(nl[1].n_value), 0);
9703 read (m, &xproc, sizeof(xproc));
9704 saval = signal(SIGALRM, catch);
9705 if ((pid = fork()) == 0) {
9706 while(1)
9707 read(tty, &c, 1);
9708 }
9709 alarm(2);
9710
9711 if(setjmp(jjbuf) == 0) {
9712 while(1)
9713 read(tty, &c, 1);
9714 }
9715 signal(SIGALRM, SIG_DFL);
9716
9717 #ifdef DIRECT
9718 pp = (struct proc *) nl[0].n_value;
9719 #else
9720 if (lseek(m, (long)(nl[0].n_value), 0) < 0L) err("seek");
9721 if (read(m, &pp, sizeof(pp)) != sizeof(pp)) err("no read of proc ptr");
9722 #endif
9723 lseek(m, (long)(nl[1].n_value), 0);
9724 read(m, &xproc, sizeof(xproc));
9725
9726 if (lseek(m, (long)pp, 0) < 0L) err("Can't seek to proc");
9727 if ((p = malloc(xproc * sizeof(struct proc))) == NULL) err("malloc");
9728 if (read(m,p,xproc * sizeof(struct proc)) != xproc*sizeof(struct proc))
9729 err("read proc table");
9730 for (pp = (struct proc *)p; xproc > 0; --xproc, ++pp) {
9731 if (pp -> p_pid == (short) pid) goto iout;
9732 }
9733 err("no such proc");
9734
9735 iout:
9736 close(m);
9737 qaddr = (char *)(pp -> p_wchan);
9738 free (p);
9739 kill(pid, SIGKILL);
9740 wait((WAIT_T *)0);
9741 return (qaddr);
9742 #endif
9743 #endif
9744 #endif
9745 #endif
9746 }
9747
9748 /* More V7-support functions... */
9749
9750 static VOID
err(s)9751 err(s) char *s; {
9752 char buf[200];
9753
9754 ckmakmsg(buf,200,"fatal error in initrawq: ", s, NULL, NULL);
9755 perror(buf);
9756 doexit(1,-1);
9757 }
9758
9759 static VOID
catch(foo)9760 catch(foo) int foo; {
9761 longjmp(jjbuf, -1);
9762 }
9763
9764
9765 /* G E N B R K -- Simulate a modem break. */
9766
9767 #ifdef MINIX
9768 #define BSPEED B110
9769 #else
9770 #ifdef MINIX2
9771 #define BSPEED B110
9772 #else
9773 #define BSPEED B150
9774 #endif /* MINIX2 */
9775 #endif /* MINIX */
9776
9777 #ifndef MINIX2
9778 VOID
genbrk(fn,msec)9779 genbrk(fn,msec) int fn, msec; {
9780 struct sgttyb ttbuf;
9781 int ret, sospeed, x, y;
9782
9783 ret = ioctl(fn, TIOCGETP, &ttbuf);
9784 sospeed = ttbuf.sg_ospeed;
9785 ttbuf.sg_ospeed = BSPEED;
9786 ret = ioctl(fn, TIOCSETP, &ttbuf);
9787 y = (int)strlen(brnuls);
9788 x = ( BSPEED * 100 ) / msec;
9789 if (x > y) x = y;
9790 ret = write(fn, brnuls, (( BSPEED * 100 ) / msec ));
9791 ttbuf.sg_ospeed = sospeed;
9792 ret = ioctl(fn, TIOCSETP, &ttbuf);
9793 ret = write(fn, "@", 1);
9794 return;
9795 }
9796 #endif /* MINIX2 */
9797
9798 #ifdef MINIX2
9799 int
genbrk(fn,msec)9800 genbrk(fn,msec) int fn, msec; {
9801 struct termios ttbuf;
9802 int ret, x, y;
9803 speed_t sospeed;
9804
9805 ret = tcgetattr(fn, &ttbuf);
9806 sospeed = ttbuf.c_ospeed;
9807 ttbuf.c_ospeed = BSPEED;
9808 ret = tcsetattr(fn,TCSADRAIN, &ttbuf);
9809 y = (int)strlen(brnuls);
9810 x = ( BSPEED * 100 ) / msec;
9811 if (x > y) x = y;
9812 ret = write(fn, brnuls, (( BSPEED * 100 ) / msec ));
9813 ttbuf.c_ospeed = sospeed;
9814 ret = tcsetattr(fn, TCSADRAIN, &ttbuf);
9815 ret = write(fn, "@", 1);
9816 return ret;
9817 }
9818 #endif /* MINIX2 */
9819 #endif /* V7 */
9820
9821 /*
9822 I N C H K -- Check if chars waiting to be read on given file descriptor.
9823
9824 This routine is a merger of ttchk() and conchk().
9825 Call with:
9826 channel == 0 to check console.
9827 channel == 1 to check communications connection.
9828 and:
9829 fd = file descriptor.
9830 Returns:
9831 >= 0: number of characters waiting, 0 or greater,
9832 -1: on any kind of error,
9833 -2: if there is (definitely) no connection.
9834 Note: In UNIX we don't have to call nettchk() because a socket
9835 file descriptor works just like in serial i/o, ioctls and all.
9836 (But this will change if we add non-file-descriptor channels,
9837 such as IBM X.25 for AIX...)
9838 */
9839 static int
in_chk(channel,fd)9840 in_chk(channel, fd) int channel, fd; {
9841 int x, n = 0; /* Workers, n = return value */
9842 extern int clsondisc; /* Close on disconnect */
9843 /*
9844 The first section checks to make sure we have a connection,
9845 but only if we're in local mode.
9846 */
9847 #ifdef DEBUG
9848 if (deblog) {
9849 debug(F111,"in_chk entry",ckitoa(fd),channel);
9850 debug(F101,"in_chk ttyfd","",ttyfd);
9851 debug(F101,"in_chk ttpty","",ttpty);
9852 }
9853 #endif /* DEBUG */
9854 /*
9855 But don't say connection is gone if we have any buffered-stuff.
9856 */
9857 #ifdef TTLEBUF
9858 debug(F101,"in_chk ttpush","",ttpush);
9859 if (channel == 1) {
9860 if (ttpush >= 0)
9861 n++;
9862 n += le_inbuf();
9863 if (n > 0)
9864 return(n);
9865 }
9866 #endif /* TTLEBUF */
9867
9868 #ifdef NETPTY
9869 #ifdef HAVE_PTYTRAP
9870 /* Special handling for HP-UX pty i/o */
9871 if (ttpty && pty_trap_pending(ttyfd) > 0) {
9872 if (pty_trap_handler(ttyfd) > 0) {
9873 ttclos(0);
9874 return(-2);
9875 }
9876 }
9877 #endif /* HAVE_PTYTRAP */
9878 #endif /* NETPTY */
9879
9880 if (channel) { /* Checking communications channel */
9881 if (ttyfd < 0) { /* No connection */
9882 return(-2); /* That's what this means */
9883 } else if (xlocal && /* In local mode */
9884 (!netconn /* Serial connection or */
9885 #ifdef TN_COMPORT
9886 || istncomport() /* Telnet Com Port */
9887 #endif /* TN_COMPORT */
9888 ) && ttcarr != CAR_OFF /* with CARRIER WATCH ON (or AUTO) */
9889 #ifdef COMMENT
9890 #ifdef MYREAD
9891 /*
9892 Seems like this would be a good idea but it prevents C-Kermit from
9893 popping back to the prompt automatically when carrier drops. However,
9894 commenting this out prevents us from seeing the NO CARRIER message.
9895 Needs more work...
9896 */
9897 && my_count < 1 /* Nothing in our internal buffer */
9898 #endif /* MYREAD */
9899 #endif /* COMMENT */
9900 ) {
9901 int x;
9902 x = ttgmdm(); /* So get modem signals */
9903 debug(F101,"in_chk close-on-disconnect","",clsondisc);
9904 if (x > -1) { /* Check for carrier */
9905 if (!(x & BM_DCD)) { /* No carrier */
9906 debug(F101,"in_chk carrier lost","",x);
9907 if (clsondisc) /* If "close-on-disconnect" */
9908 ttclos(0); /* close device & release lock. */
9909 return(-2); /* This means "disconnected" */
9910 }
9911 /* In case I/O to device after CD dropped always fails */
9912 /* as in Debian Linux 2.1 and Unixware 2.1... */
9913 } else {
9914 debug(F101,"in_chk ttgmdm I/O error","",errno);
9915 debug(F101,"in_chk ttgmdm gotsigs","",gotsigs);
9916 if (gotsigs) { /* If we got signals before... */
9917 if (errno == 5 || errno == 6) { /* I/O error etc */
9918 if (clsondisc) /* like when modem hangs up */
9919 ttclos(0);
9920 return(-2);
9921 }
9922 }
9923 /* If we never got modem signals successfully on this */
9924 /* connection before, we can't conclude that THIS failure */
9925 /* means the connection was lost. */
9926 return(0);
9927 }
9928 }
9929 }
9930
9931 /* We seem to have a connection so now see if any bytes are waiting on it */
9932
9933 #ifdef CK_SSL
9934 if (ssl_active_flag || tls_active_flag) {
9935 n += SSL_pending(ssl_active_flag?ssl_con:tls_con);
9936 debug(F101,"in_chk SSL_pending","",n);
9937 if (n < 0) {
9938 ttclos(0);
9939 return(-1);
9940 } else if (n > 0) {
9941 return(n);
9942 }
9943 }
9944 #endif /* CK_SSL */
9945 #ifdef RLOGCODE
9946 #ifdef CK_KERBEROS
9947 /* It is not safe to read any data when using encrypted Klogin */
9948 if (ttnproto == NP_EK4LOGIN || ttnproto == NP_EK5LOGIN) {
9949 #ifdef KRB4
9950 if (ttnproto == NP_EK4LOGIN) {
9951 n += krb4_des_avail(ttyfd);
9952 debug(F101,"in_chk krb4_des_avail","",n);
9953 }
9954 #endif /* KRB4 */
9955 #ifdef KRB5
9956 if (ttnproto == NP_EK5LOGIN) {
9957 n += krb5_des_avail(ttyfd);
9958 debug(F101,"in_chk krb5_des_avail","",n);
9959 }
9960 #ifdef KRB5_U2U
9961 if (ttnproto == NP_K5U2U) {
9962 n += krb5_u2u_avail(ttyfd);
9963 debug(F101,"in_chk krb5_des_avail","",n);
9964 }
9965 #endif /* KRB5_U2U */
9966 #endif /* KRB5 */
9967 if (n < 0) /* Is this right? */
9968 return(-1);
9969 else
9970 return(n);
9971 }
9972 #endif /* CK_KERBEROS */
9973 #endif /* RLOGCODE */
9974
9975 errno = 0; /* Reset this so we log good info */
9976 #ifdef FIONREAD
9977 x = ioctl(fd, FIONREAD, &n); /* BSD and lots of others */
9978 #ifdef DEBUG /* (the more the better) */
9979 if (deblog) {
9980 debug(F101,"in_chk FIONREAD return code","",x);
9981 debug(F101,"in_chk FIONREAD count","",n);
9982 debug(F101,"in_chk FIONREAD errno","",errno);
9983 }
9984 #endif /* DEBUG */
9985 #else /* FIONREAD not defined */
9986 /*
9987 Here, if (netconn && ttnet == NET_TCPB), we might try calling recvmsg()
9988 with flags MSG_PEEK|MSG_DONTWAIT on the socket (ttyfd), except this is not
9989 portable (MSG_DONTWAIT isn't defined in any of the <sys/socket.h> files
9990 that I looked at, but it is needed to prevent the call from blocking), and
9991 the msghdr struct differs from place to place, so we would need another
9992 avalanche of ifdefs. Still, when FIONREAD is not available, this is the
9993 only other known method of asking the OS for the *number* of characters
9994 available for reading.
9995 */
9996 #ifdef V7 /* UNIX V7: look in kernel memory */
9997 #ifdef MINIX
9998 n = 0; /* But not in MINIX */
9999 #else
10000 #ifdef MINIX2
10001 n = 0;
10002 #else
10003 lseek(kmem[TTY], (long) qaddr[TTY], 0); /* 7th Edition Unix */
10004 x = read(kmem[TTY], &n, sizeof(int));
10005 if (x != sizeof(int))
10006 n = 0;
10007 #endif /* MINIX2 */
10008 #endif /* MINIX */
10009 #else /* Not V7 */
10010 #ifdef PROVX1
10011 x = ioctl(fd, TIOCQCNT, &ttbuf); /* DEC Pro/3xx Venix V.1 */
10012 n = ttbuf.sg_ispeed & 0377; /* Circa 1984 */
10013 if (x < 0) n = 0;
10014 #else
10015 #ifdef MYREAD
10016 /*
10017 Here we skip all the undependable and expensive calls below if we
10018 already have something in our internal buffer. This tends to work quite
10019 nicely, so the only really bad case remaining is the one in which neither
10020 FIONREAD or MYREAD are defined, which is increasingly rare these days.
10021 */
10022 if (channel != 0 && my_count > 0) {
10023 debug(F101,"in_chk buf my_count","",my_count);
10024 n = my_count; /* n was 0 before we got here */
10025 return(n);
10026 }
10027 #endif /* MYREAD */
10028 /*
10029 rdchk(), select(), and poll() tell us *if* data is available to be read, but
10030 not how much, so these should be used only as a final resort. Especially
10031 since these calls tend to add a lot overhead.
10032 */
10033 #ifdef RDCHK /* This mostly SCO-specific */
10034 n = rdchk(fd);
10035 debug(F101,"in_chk rdchk","",n);
10036 #else /* No RDCHK */
10037 #ifdef SELECT
10038 #ifdef Plan9
10039 /* Only allows select on the console ... don't ask */
10040 if (channel == 0)
10041 #endif /* Plan9 */
10042 {
10043 fd_set rfds; /* Read file descriptors */
10044 #ifdef BELLV10
10045 FD_ZERO(rfds); /* Initialize them */
10046 FD_SET(fd,rfds); /* We want to look at this fd */
10047 #else
10048 FD_ZERO(&rfds); /* Initialize them */
10049 FD_SET(fd,&rfds); /* We want to look at this fd */
10050 tv.tv_sec = tv.tv_usec = 0L; /* A 0-valued timeval structure */
10051 #endif /* BELLV10 */
10052 #ifdef Plan9
10053 n = select( FD_SETSIZE, &rfds, (fd_set *)0, (fd_set *)0, &tv );
10054 debug(F101,"in_chk Plan 9 select","",n);
10055 #else
10056 #ifdef BELLV10
10057 n = select( 128, rfds, (fd_set *)0, (fd_set *)0, 0 );
10058 debug(F101,"in_chk BELLV10 select","",n);
10059 #else
10060 #ifdef BSD44
10061 n = select( FD_SETSIZE, &rfds, (fd_set *)0, (fd_set *)0, &tv );
10062 debug(F101,"in_chk BSD44 select","",n);
10063 #else
10064 #ifdef BSD43
10065 n = select( FD_SETSIZE, &rfds, (fd_set *)0, (fd_set *)0, &tv );
10066 debug(F101,"in_chk BSD43 select","",n);
10067 #else
10068 #ifdef SOLARIS
10069 n = select( FD_SETSIZE, &rfds, (fd_set *)0, (fd_set *)0, &tv );
10070 debug(F101,"in_chk SOLARIS select","",n);
10071 #else
10072 #ifdef QNX6
10073 n = select( FD_SETSIZE, &rfds, (fd_set *)0, (fd_set *)0, &tv );
10074 debug(F101,"in_chk QNX6 select","",n);
10075 #else
10076 #ifdef QNX
10077 n = select( FD_SETSIZE, &rfds, (fd_set *)0, (fd_set *)0, &tv );
10078 debug(F101,"in_chk QNX select","",n);
10079 #else
10080 #ifdef COHERENT
10081 n = select( FD_SETSIZE, &rfds, (fd_set *)0, (fd_set *)0, &tv );
10082 debug(F101,"in_chk COHERENT select","",n);
10083 #else
10084 #ifdef SVR4
10085 n = select( FD_SETSIZE, &rfds, (fd_set *)0, (fd_set *)0, &tv );
10086 debug(F101,"in_chk SVR4 select","",n);
10087 #else
10088 #ifdef __linux__
10089 n = select( FD_SETSIZE, &rfds, (fd_set *)0, (fd_set *)0, &tv );
10090 debug(F101,"in_chk LINUX select","",n);
10091 #ifdef OSF
10092 n = select( FD_SETSIZE, &rfds, (fd_set *)0, (fd_set *)0, &tv );
10093 debug(F101,"in_chk OSF select","",n);
10094 #else
10095 n = select( FD_SETSIZE, &rfds, (int *)0, (int *)0, &tv );
10096 debug(F101,"in_chk catchall select","",n);
10097 #endif /* OSF */
10098 #endif /* __linux__ */
10099 #endif /* SVR4 */
10100 #endif /* COHERENT */
10101 #endif /* QNX */
10102 #endif /* QNX6 */
10103 #endif /* SOLARIS */
10104 #endif /* BSD43 */
10105 #endif /* BSD44 */
10106 #endif /* BELLV10 */
10107 #endif /* Plan9 */
10108 }
10109 #else /* Not SELECT */
10110 #ifdef CK_POLL
10111 {
10112 struct pollfd pfd;
10113
10114 pfd.fd = fd;
10115 pfd.events = POLLIN;
10116 pfd.revents = 0;
10117 n = poll(&pfd, 1, 0);
10118 debug(F101,"in_chk poll","",n);
10119 if ((n > 0) && (pfd.revents & POLLIN))
10120 n = 1;
10121 }
10122 #endif /* CK_POLL */
10123 #endif /* SELECT */
10124 #endif /* RDCHK */
10125 #endif /* PROVX1 */
10126 #endif /* V7 */
10127 #endif /* FIONREAD */
10128
10129 /* From here down, treat console and communication device differently... */
10130
10131 if (channel == 0) { /* Console */
10132
10133 #ifdef SVORPOSIX
10134 #ifndef FIONREAD
10135 #ifndef SELECT
10136 #ifndef CK_POLL
10137 #ifndef RDCHK
10138 /*
10139 This is the hideous hack used in System V and POSIX systems that don't
10140 support FIONREAD, rdchk(), select(), poll(), etc, in which the user's
10141 CONNECT-mode escape character is attached to SIGQUIT. Used, obviously,
10142 only on the console.
10143 */
10144 if (conesc) { /* Escape character typed == SIGQUIT */
10145 debug(F100,"in_chk conesc","",conesc);
10146 conesc = 0;
10147 signal(SIGQUIT,esctrp); /* Restore signal */
10148 n += 1;
10149 }
10150 #endif /* RDCHK */
10151 #endif /* CK_POLL */
10152 #endif /* SELECT */
10153 #endif /* FIONREAD */
10154 #endif /* SVORPOSIX */
10155
10156 return(n); /* Done with console */
10157 }
10158
10159 if (channel != 0) { /* Communications connection */
10160
10161 #ifdef MYREAD
10162 #ifndef FIONREAD
10163 /*
10164 select() or rdchk(), etc, has told us that something is waiting, but we
10165 don't know how much. So we do a read to get it and then we know. Note:
10166 This read is NOT nonblocking if nothing is there (because of VMIN=1), but
10167 it should be safe in this case since the OS tells us at least one byte is
10168 waiting to be read, and MYREAD reads return as much as is there without
10169 waiting for any more. Controlled tests on Solaris and Unixware (with
10170 FIONREAD deliberately undefined) show this to be true.
10171 */
10172 debug(F101,"in_chk read my_count","",my_count);
10173 debug(F101,"in_chk read n","",n);
10174 if (n > 0 && my_count == 0) {
10175 /* This also catches disconnects etc */
10176 /* Do what mygetbuf does except don't grab a character */
10177 my_count = myfillbuf();
10178 my_item = -1; /* ^^^ */
10179 debug(F101,"in_chk myfillbuf my_count","",my_count);
10180 if (my_count < 0)
10181 return(-1);
10182 else
10183 n = 0; /* NB: n is replaced by my_count */
10184 }
10185 #endif /* FIONREAD */
10186 /*
10187 Here we add whatever we think is unread to what is still in our
10188 our internal buffer. Thus the importance of setting n to 0 just above.
10189 */
10190 debug(F101,"in_chk my_count","",my_count);
10191 debug(F101,"in_chk n","",n);
10192 if (my_count > 0)
10193 n += my_count;
10194 #endif /* MYREAD */
10195 }
10196 debug(F101,"in_chk result","",n);
10197
10198 /* Errors here don't prove the connection has dropped so just say 0 */
10199
10200 return(n < 0 ? 0 : n);
10201 }
10202
10203
10204 /* T T C H K -- Tell how many characters are waiting in tty input buffer */
10205
10206 int
ttchk()10207 ttchk() {
10208 int fd;
10209 #ifdef NETCMD
10210 if (ttpipe)
10211 fd = fdin;
10212 else
10213 #endif /* NETCMD */
10214 fd = ttyfd;
10215 return(in_chk(1,fd));
10216 }
10217
10218 /* T T X I N -- Get n characters from tty input buffer */
10219
10220 /* Returns number of characters actually gotten, or -1 on failure */
10221
10222 /* Intended for use only when it is known that n characters are actually */
10223 /* Available in the input buffer. */
10224
10225 int
ttxin(n,buf)10226 ttxin(n,buf) int n; CHAR *buf; {
10227 register int x = 0, c = -2;
10228 #ifdef TTLEBUF
10229 register int i = 0;
10230 #endif /* TTLEBUF */
10231 int fd;
10232
10233 if (n < 1) /* Nothing to do */
10234 return(0);
10235
10236 #ifdef TTLEBUF
10237 if (ttpush >= 0) {
10238 buf[0] = ttpush; /* Put pushed char in buffer*/
10239 ttpush = -1; /* Clear the push buffer */
10240 if (ttchk() > 0)
10241 return(ttxin(n-1, &buf[1]) + 1);
10242 else
10243 return(1);
10244 }
10245 if (le_data) {
10246 while (le_inbuf() > 0) {
10247 if (le_getchar(&buf[i])) {
10248 i++;
10249 n--;
10250 }
10251 }
10252 if (ttchk() > 0)
10253 return(ttxin(n,&buf[i])+i);
10254 else
10255 return(i);
10256 }
10257 #endif /* TTLEBUF */
10258
10259 #ifdef NETCMD
10260 if (ttpipe)
10261 fd = fdin;
10262 else
10263 #endif /* NETCMD */
10264 fd = ttyfd;
10265
10266 #ifdef SUNX25
10267 if (netconn && (ttnet == NET_SX25)) /* X.25 connection */
10268 return(x25xin(n,buf));
10269 #endif /* SUNX25 */
10270
10271 #ifdef IBMX25
10272 /* riehm: possibly not needed. Test worked with normal reads and writes */
10273 if (netconn && (ttnet == NET_IX25)) { /* X.25 connection */
10274 x = x25xin(n,buf);
10275 if (x > 0) buf[x] = '\0';
10276 return(x);
10277 }
10278 #endif /* IBMX25 */
10279
10280 #ifdef MYREAD
10281 debug(F101,"ttxin MYREAD","",n);
10282 while (x < n) {
10283 c = myread();
10284 if (c < 0) {
10285 debug(F101,"ttxin myread returns","",c);
10286 if (c == -3) x = -1;
10287 break;
10288 }
10289 buf[x++] = c & ttpmsk;
10290 #ifdef RLOGCODE
10291 #ifdef CK_KERBEROS
10292 /* It is impossible to know how many characters are waiting */
10293 /* to be read when you are using Encrypted Rlogin or SSL */
10294 /* as the transport since the number of real data bytes */
10295 /* can be greater or less than the number of bytes on the */
10296 /* wire which is what ttchk() returns. */
10297 if (netconn && (ttnproto == NP_EK4LOGIN || ttnproto == NP_EK5LOGIN))
10298 if (ttchk() <= 0)
10299 break;
10300 #endif /* CK_KERBEROS */
10301 #endif /* RLOGCODE */
10302 #ifdef CK_SSL
10303 if (ssl_active_flag || tls_active_flag)
10304 if (ttchk() <= 0)
10305 break;
10306 #endif /* CK_SSL */
10307 }
10308 #else
10309 debug(F101,"ttxin READ","",n);
10310 x = read(fd,buf,n);
10311 for (c = 0; c < n; c++) /* Strip any parity */
10312 buf[c] &= ttpmsk;
10313 #endif /* MYREAD */
10314
10315 debug(F101,"ttxin x","",x); /* Done */
10316 if (x > 0) buf[x] = '\0';
10317 if (x < 0) x = -1;
10318 return(x);
10319 }
10320
10321 /* T T O L -- Write string s, length n, to communication device. */
10322 /*
10323 Returns:
10324 >= 0 on success, number of characters actually written.
10325 -1 on failure.
10326 */
10327 #ifdef CK_ENCRYPTION
10328 CHAR * xpacket = NULL;
10329 int nxpacket = 0;
10330 #endif /* CK_ENCRYPTION */
10331
10332 #define TTOLMAXT 5
10333 int
ttol(s,n)10334 ttol(s,n) int n; CHAR *s; {
10335 int x, len, tries, fd;
10336 #ifdef CKXXCHAR
10337 extern int dblflag; /* For SET SEND DOUBLE-CHARACTER */
10338 extern short dblt[];
10339 CHAR *p = NULL, *p2, *s2, c;
10340 int n2 = 0;
10341 #endif /* CKXXCHAR */
10342
10343 if (ttyfd < 0) /* Not open? */
10344 return(-3);
10345 #ifdef DEBUG
10346 if (deblog) {
10347 /* debug(F101,"ttol ttyfd","",ttyfd); */
10348 ckhexdump("ttol s",s,n);
10349 }
10350 #endif /* DEBUG */
10351
10352 #ifdef NETCMD
10353 if (ttpipe)
10354 fd = fdout;
10355 else
10356 #endif /* NETCMD */
10357 fd = ttyfd;
10358
10359 #ifdef CKXXCHAR
10360 /* Double any characters that must be doubled. */
10361 debug(F101,"ttol dblflag","",dblflag);
10362 if (dblflag) {
10363 p = (CHAR *) malloc(n + n + 1);
10364 if (p) {
10365 s2 = s;
10366 p2 = p;
10367 n2 = 0;
10368 while (*s2) {
10369 c = *s2++;
10370 *p2++ = c;
10371 n2++;
10372 if (dblt[(unsigned) c] & 2) {
10373 *p2++ = c;
10374 n2++;
10375 }
10376 }
10377 s = p;
10378 n = n2;
10379 s[n] = '\0';
10380 }
10381 #ifdef DEBUG
10382 ckhexdump("ttol doubled s",s,n);
10383 #endif /* DEBUG */
10384 }
10385 #endif /* CKXXCHAR */
10386
10387 tries = TTOLMAXT; /* Allow up to this many tries */
10388 len = n; /* Remember original length */
10389
10390 #ifdef CK_ENCRYPTION
10391 /*
10392 This is to avoid encrypting a packet that is already encrypted, e.g.
10393 when we resend a packet directly out of the packet buffer, and also to
10394 avoid encrypting a constant (literal) string, which can cause a memory
10395 fault.
10396 */
10397 if (TELOPT_ME(TELOPT_ENCRYPTION)) {
10398 int x;
10399 if (nxpacket < n) {
10400 if (xpacket) {
10401 free(xpacket);
10402 xpacket = NULL;
10403 nxpacket = 0;
10404 }
10405 x = n > 10240 ? n : 10240;
10406 xpacket = (CHAR *)malloc(x);
10407 if (!xpacket) {
10408 fprintf(stderr,"ttol malloc failure\n");
10409 return(-1);
10410 } else
10411 nxpacket = x;
10412 }
10413 memcpy((char *)xpacket,(char *)s,n);
10414 s = xpacket;
10415 ck_tn_encrypt((char *)s,n);
10416 }
10417 #endif /* CK_ENCRYPTION */
10418
10419 while (n > 0 &&
10420 (tries-- > 0
10421 #ifdef CK_ENCRYPTION
10422 /* keep trying if we are encrypting */
10423 || TELOPT_ME(TELOPT_ENCRYPTION)
10424 #endif /* CK_ENCRYPTION */
10425 )) { /* Be persistent */
10426 debug(F101,"ttol try","",TTOLMAXT - tries);
10427 #ifdef BEOSORBEBOX
10428 if (netconn && !ttpipe && !ttpty)
10429 x = nettol((char *)s,n); /* Write string to device */
10430 else
10431 #endif /* BEOSORBEBOX */
10432 #ifdef IBMX25
10433 if (ttnet == NET_IX25)
10434 /*
10435 * this is a more controlled way of writing to X25
10436 * STREAMS, however write should also work!
10437 */
10438 x = x25write(ttyfd, s, n);
10439 else
10440 #endif /* IBMX25 */
10441 #ifdef CK_SSL
10442 if (ssl_active_flag || tls_active_flag) {
10443 int error;
10444 /* Write using SSL */
10445 ssl_retry:
10446 if (ssl_active_flag)
10447 x = SSL_write(ssl_con, s, n);
10448 else
10449 x = SSL_write(tls_con, s, n);
10450 switch (SSL_get_error(ssl_active_flag?ssl_con:tls_con,x)) {
10451 case SSL_ERROR_NONE:
10452 if (x == n)
10453 return(len);
10454 s += x;
10455 n -= x;
10456 goto ssl_retry;
10457 case SSL_ERROR_WANT_WRITE:
10458 case SSL_ERROR_WANT_READ:
10459 x = 0;
10460 break;
10461 case SSL_ERROR_SYSCALL:
10462 if (x != 0)
10463 return(-1);
10464 case SSL_ERROR_WANT_X509_LOOKUP:
10465 case SSL_ERROR_SSL:
10466 case SSL_ERROR_ZERO_RETURN:
10467 default:
10468 ttclos(0);
10469 return(-3);
10470 }
10471 } else
10472 #endif /* CK_SSL */
10473 #ifdef CK_KERBEROS
10474 #ifdef KRB4
10475 #ifdef RLOGCODE
10476 if (ttnproto == NP_EK4LOGIN) {
10477 return(krb4_des_write(ttyfd,s,n));
10478 } else
10479 #endif /* RLOGCODE */
10480 #endif /* KRB4 */
10481 #ifdef KRB5
10482 #ifdef RLOGCODE
10483 if (ttnproto == NP_EK5LOGIN) {
10484 return(krb5_des_write(ttyfd,(char *)s,n,0));
10485 } else
10486 #endif /* RLOGCODE */
10487 #ifdef KRB5_U2U
10488 if (ttnproto == NP_K5U2U) {
10489 return(krb5_u2u_write(ttyfd,(char *)s,n));
10490 } else
10491 #endif /* KRB5_U2U */
10492 #endif /* KRB5 */
10493 #endif /* CK_KERBEROS */
10494 x = write(fd,s,n); /* Write string to device */
10495
10496 if (x == n) { /* Worked? */
10497 debug(F101,"ttol ok","",x); /* OK */
10498 #ifdef CKXXCHAR
10499 if (p) free(p);
10500 #endif /* CKXXCHAR */
10501 return(len); /* Done */
10502 } else if (x < 0) { /* No, got error? */
10503 debug(F101,"ttol write error","",errno);
10504 #ifdef EWOULDBLOCK
10505 if (errno == EWOULDBLOCK) {
10506 msleep(10);
10507 continue;
10508 } else
10509 #endif /* EWOULDBLOCK */
10510 #ifdef TCPSOCKET
10511 if (netconn && ttnet == NET_TCPB) {
10512 debug(F101,"ttol TCP error","",errno);
10513 ttclos(0); /* Close the connection. */
10514 x = -3;
10515 }
10516 #endif /* TCPSOCKET */
10517 #ifdef CKXXCHAR
10518 if (p) free(p);
10519 #endif /* CKXXCHAR */
10520 return(x);
10521 } else { /* No error, so partial success */
10522 debug(F101,"ttol partial","",x); /* This never happens */
10523 s += x; /* Point to part not written yet */
10524 n -= x; /* Adjust length */
10525 if (x > 0) msleep(10); /* Wait 10 msec */
10526 } /* Go back and try again */
10527 }
10528 #ifdef CKXXCHAR
10529 if (p) free(p);
10530 #endif /* CKXXCHAR */
10531 return(n < 1 ? len : -1); /* Return the results */
10532 }
10533
10534 /* T T O C -- Output a character to the communication line */
10535
10536 /*
10537 This function should only be used for interactive, character-mode operations,
10538 like terminal connection, script execution, dialer i/o, where the overhead
10539 of the signals and alarms does not create a bottleneck.
10540 */
10541 int
10542 #ifdef CK_ANSIC
ttoc(char c)10543 ttoc(char c)
10544 #else
10545 ttoc(c) char c;
10546 #endif /* CK_ANSIC */
10547 /* ttoc */ {
10548 #define TTOC_TMO 15 /* Timeout in case we get stuck */
10549 int xx, fd;
10550
10551 if (ttyfd < 0) /* Check for not open. */
10552 return(-1);
10553
10554 #ifdef NETCMD
10555 if (ttpipe)
10556 fd = fdout;
10557 else
10558 #endif /* NETCMD */
10559 fd = ttyfd;
10560
10561 c &= 0xff;
10562 /* debug(F101,"ttoc","",(CHAR) c); */
10563 saval = signal(SIGALRM,timerh); /* Enable timer interrupt */
10564 xx = alarm(TTOC_TMO); /* for this many seconds. */
10565 if (xx < 0) xx = 0; /* Save old alarm value. */
10566 /* debug(F101,"ttoc alarm","",xx); */
10567 if (
10568 #ifdef CK_POSIX_SIG
10569 sigsetjmp(sjbuf,1)
10570 #else
10571 setjmp(sjbuf)
10572 #endif /* CK_POSIX_SIG */
10573 ) { /* Timer went off? */
10574 ttimoff(); /* Yes, cancel this alarm. */
10575 if (xx - TTOC_TMO > 0) alarm(xx - TTOC_TMO); /* Restore previous one */
10576 /* debug(F100,"ttoc timeout","",0); */
10577 #ifdef NETCONN
10578 if (!netconn) {
10579 #endif /* NETCONN */
10580 debug(F101,"ttoc timeout","",c);
10581 if (ttflow == FLO_XONX) {
10582 debug(F101,"ttoc flow","",ttflow); /* Maybe we're xoff'd */
10583 #ifndef Plan9
10584 #ifdef POSIX
10585 /* POSIX way to unstick. */
10586 debug(F100,"ttoc tcflow","",tcflow(ttyfd,TCOON));
10587 #else
10588 #ifdef BSD4 /* Berkeley way to do it. */
10589 #ifdef TIOCSTART
10590 /* .... Used to be "ioctl(ttyfd, TIOCSTART, 0);". Who knows? */
10591 {
10592 int x = 0;
10593 debug(F101,"ttoc TIOCSTART","",ioctl(ttyfd, TIOCSTART, &x));
10594 }
10595 #endif /* TIOCSTART */
10596 #endif /* BSD4 */
10597 /* Is there a Sys V way to do this? */
10598 #endif /* POSIX */
10599 #endif /* Plan9 */
10600 }
10601 #ifdef NETCONN
10602 }
10603 #endif /* NETCONN */
10604 return(-1); /* Return failure code. */
10605 } else {
10606 int rc;
10607 #ifdef BEOSORBEBOX
10608 #ifdef NETCONN
10609 if (netconn && !ttpipe && !ttpty)
10610 rc = nettoc(c);
10611 else
10612 #endif /* BEOSORBEBOX */
10613 #endif /* NETCONN */
10614 #ifdef CK_ENCRYPTION
10615 if (TELOPT_ME(TELOPT_ENCRYPTION))
10616 ck_tn_encrypt(&c,1);
10617 #endif /* CK_ENCRYPTION */
10618 #ifdef IBMX25
10619 /* riehm: maybe this isn't necessary after all. Test program
10620 * worked fine with data being sent and retrieved with normal
10621 * read's and writes!
10622 */
10623 if (ttnet == NET_IX25)
10624 rc = x25write(ttyfd,&c,1); /* as above for X25 streams */
10625 else
10626 #endif /* IBMX25 */
10627 #ifdef CK_SSL
10628 if (ssl_active_flag || tls_active_flag) {
10629 int error;
10630 /* Write using SSL */
10631 if (ssl_active_flag)
10632 rc = SSL_write(ssl_con, &c, 1);
10633 else
10634 rc = SSL_write(tls_con, &c, 1);
10635 switch (SSL_get_error(ssl_active_flag?ssl_con:tls_con,rc)){
10636 case SSL_ERROR_NONE:
10637 break;
10638 case SSL_ERROR_WANT_WRITE:
10639 case SSL_ERROR_WANT_READ:
10640 rc = 0;
10641 break;
10642 case SSL_ERROR_SYSCALL:
10643 if (rc != 0)
10644 return(-1);
10645 case SSL_ERROR_WANT_X509_LOOKUP:
10646 case SSL_ERROR_SSL:
10647 case SSL_ERROR_ZERO_RETURN:
10648 default:
10649 ttclos(0);
10650 return(-1);
10651 }
10652 } else
10653 #endif /* CK_SSL */
10654 #ifdef CK_KERBEROS
10655 #ifdef KRB4
10656 #ifdef RLOGCODE
10657 if (ttnproto == NP_EK4LOGIN) {
10658 rc = (krb4_des_write(ttyfd,(char *)&c,1) == 1);
10659 } else
10660 #endif /* RLOGCODE */
10661 #endif /* KRB4 */
10662 #ifdef KRB5
10663 #ifdef RLOGCODE
10664 if (ttnproto == NP_EK5LOGIN) {
10665 rc = (krb5_des_write(ttyfd,&c,1,0) == 1);
10666 } else
10667 #endif /* RLOGCODE */
10668 #ifdef KRB5_U2U
10669 if (ttnproto == NP_K5U2U) {
10670 rc = (krb5_u2u_write(ttyfd,&c,1) == 1);
10671 } else
10672 #endif /* KRB5_U2U */
10673 #endif /* KRB5 */
10674 #endif /* CK_KERBEROS */
10675 rc = write(fd,&c,1); /* Try to write the character. */
10676 if (rc < 1) { /* Failed */
10677 ttimoff(); /* Turn off the alarm. */
10678 alarm(xx); /* Restore previous alarm. */
10679 debug(F101,"ttoc errno","",errno); /* Log the error, */
10680 return(-1); /* and return the error code. */
10681 }
10682 }
10683 ttimoff(); /* Success, turn off the alarm. */
10684 alarm(xx); /* Restore previous alarm. */
10685 return(0); /* Return good code. */
10686 }
10687
10688 /* T T I N L -- Read a record (up to break character) from comm line. */
10689 /*
10690 Reads up to "max" characters from the connection, terminating on:
10691 (a) the packet length field if the "turn" argument is zero, or
10692 (b) on the packet-end character (eol) if the "turn" argument is nonzero
10693 (c) a certain number of Ctrl-C's in a row
10694
10695 Returns:
10696 >= 0, the number of characters read upon success;
10697 -1 if "max" exceeded, timeout, or other correctable error;
10698 -2 on user interruption (c);
10699 -3 on fatal error like connection lost.
10700
10701 The name of this routine dates from the early days when Kermit packets
10702 were, indeed, always lines of text. That was before control-character
10703 unprefixing and length-driven packet framing were introduced, which this
10704 version handle. NB: this routine is ONLY for reading incoming Kermit
10705 packets, nothing else. To read other kinds of incoming material, use
10706 ttinc() or ttxin().
10707
10708 The bytes that were input are copied into "dest" with their parity bits
10709 stripped if parity was selected. Returns the number of bytes read.
10710 Bytes after the eol are available upon the next call to this function.
10711
10712 The idea is to minimize the number of system calls per packet, and also to
10713 minimize timeouts. This function is the inner loop of the protocol and must
10714 be as efficient as possible. The current strategy is to use myread(), a
10715 macro to manage buffered (and generally nonblocking) reads.
10716
10717 WARNING: This function calls parchk(), which is defined in another module.
10718 Normally, ckutio.c does not depend on code from any other module, but there
10719 is an exception in this case because all the other ck?tio.c modules also
10720 need to call parchk(), so it's better to have it defined in a common place.
10721 */
10722 #ifdef CTRLC
10723 #undef CTRLC
10724 #endif /* CTRLC */
10725 #define CTRLC '\03'
10726 /*
10727 We have four different declarations here because:
10728 (a) to allow Kermit to be built without the automatic parity sensing feature
10729 (b) one of each type for ANSI C, one for non-ANSI.
10730 */
10731 #ifndef NOXFER
10732
10733 static int pushedback = 0;
10734
10735 int
10736 #ifdef PARSENSE
10737 #ifdef CK_ANSIC
ttinl(CHAR * dest,int max,int timo,CHAR eol,CHAR start,int turn)10738 ttinl(CHAR *dest, int max,int timo, CHAR eol, CHAR start, int turn)
10739 #else
10740 ttinl(dest,max,timo,eol,start,turn) int max,timo,turn; CHAR *dest, eol, start;
10741 #endif /* CK_ANSIC */
10742 #else /* not PARSENSE */
10743 #ifdef CK_ANSIC
10744 ttinl(CHAR *dest, int max,int timo, CHAR eol)
10745 #else
10746 ttinl(dest,max,timo,eol) int max,timo; CHAR *dest, eol;
10747 #endif /* CK_ANSIC */
10748 #endif /* PARSENSE */
10749 /* ttinl */ {
10750
10751 #ifndef MYREAD
10752 CHAR ch, dum;
10753 #endif /* MYREAD */
10754 #ifdef PARSENSE
10755 int pktlen = -1;
10756 int lplen = 0;
10757 int havelen = 0;
10758 #endif /* PARSENSE */
10759 int fd;
10760 int sopmask = 0xff; /* Start-Of-Packet mask */
10761 #ifdef CKXXCHAR
10762 extern short dblt[]; /* Ignore-character table */
10763 extern int ignflag;
10764 #endif /* CKXXCHAR */
10765 #ifdef TCPSOCKET
10766 extern CHAR stchr;
10767 #endif /* TCPSOCKET */
10768 int x;
10769 #ifdef STREAMING
10770 extern int streaming;
10771 extern int sndtyp;
10772 #endif /* STREAMING */
10773
10774 if (ttyfd < 0) return(-3); /* Not open. */
10775 /*
10776 In February 2007 I fixed ttinl() to work better under the truly awful
10777 conditions encountered by the AM-APEX oceanographic floats that gather
10778 hurricane data and phone home using Iridium satellite modems, which under
10779 certain conditions, can send two packets back to back after a long pause.
10780 In this case the second packet would be ignored because the SOH was skipped
10781 due to the ttflui() call. But the reworked lookahead/pushback logic broke
10782 Kermit transfers on encrypted connections. This was fixed 12-13 August
10783 2007. All of this happened after 8.0.212 Dev.27 was released and before
10784 Dev.28, so no harm done other than the delay.
10785 */
10786 debug(F101,"ttinl max","",max);
10787 debug(F101,"ttinl timo","",timo);
10788
10789 #ifdef NETCMD
10790 if (ttpipe)
10791 fd = fdin;
10792 else
10793 #endif /* NETCMD */
10794 fd = ttyfd;
10795
10796 #ifdef COMMENT
10797 if (xlocal && conchk() > 0) /* Allow for console interruptions */
10798 return(-1);
10799 #endif /* COMMENT */
10800
10801 *dest = '\0'; /* Clear destination buffer */
10802 if (timo < 0) timo = 0; /* Safety */
10803 if (timo) { /* Don't time out if timo == 0 */
10804 int xx;
10805 saval = signal(SIGALRM,timerh); /* Enable timer interrupt */
10806 xx = alarm(timo); /* Set it. */
10807 debug(F101,"ttinl alarm","",xx);
10808 }
10809 if (
10810 #ifdef CK_POSIX_SIG
10811 sigsetjmp(sjbuf,1)
10812 #else
10813 setjmp(sjbuf)
10814 #endif /* CK_POSIX_SIG */
10815 ) { /* Timer went off? */
10816 debug(F100,"ttinl timout","",0); /* Get here on timeout. */
10817 /* debug(F110," with",(char *) dest,0); */
10818 ttimoff(); /* Turn off timer */
10819 return(-1); /* and return error code. */
10820 } else {
10821 register int i, n = -1; /* local variables */
10822 int ccn = 0;
10823 #ifdef PARSENSE
10824 register int flag = 0;
10825 debug(F000,"ttinl start","",start);
10826 #endif /* PARSENSE */
10827
10828 ttpmsk = ttprty ? 0177 : 0377; /* Set parity stripping mask. */
10829 sopmask = needpchk ? 0177 : ttpmsk; /* And SOP matching mask. */
10830
10831 /* Now read into destination, stripping parity and looking for the */
10832 /* the packet terminator, and also for several Ctrl-C's typed in a row. */
10833
10834 i = 0; /* Destination index */
10835 debug(F101,"ttinl eol","",eol);
10836
10837 while (i < max-1) {
10838 #ifdef MYREAD
10839 errno = 0;
10840 /* On encrypted connections myread returns encrypted bytes */
10841 n = myread();
10842 debug(F000,"TTINL myread char","",n);
10843 if (n < 0) { /* Timeout or i/o error? */
10844 #ifdef DEBUG
10845 if (deblog) {
10846 debug(F101,"ttinl myread failure, n","",n);
10847 debug(F101,"ttinl myread errno","",errno);
10848 }
10849 #endif /* DEBUG */
10850 /* Don't let EINTR break packets. */
10851 if (n == -3) {
10852 if (errno == EINTR && i > 0) {
10853 debug(F111,"ttinl EINTR myread i","continuing",i);
10854 continue;
10855 } else {
10856 debug(F110,"ttinl non-EINTR -3","closing",0);
10857 wasclosed = 1;
10858 ttimoff(); /* Turn off timer */
10859 ttclos(0);
10860 return(n);
10861 }
10862 } else if (n == -2 && netconn /* && timo == 0 */ ) {
10863 /* Here we try to catch broken network connections */
10864 /* even when ioctl() and read() do not catch them */
10865 debug(F111,"ttinl network myread failure","closing",n);
10866 wasclosed = 1;
10867 ttimoff();
10868 ttclos(0);
10869 return(-3);
10870 }
10871 #ifdef STREAMING
10872 /* Streaming and no data to read */
10873 else if (n == 0 && streaming && sndtyp == 'D')
10874 return(0);
10875 #endif /* STREAMING */
10876 break; /* Break out of while loop */
10877 }
10878
10879 #else /* not MYREAD (is this code used anywhere any more?) */
10880 /*
10881 The non-MYREAD code dates from the 1980s and was needed on certain platforms
10882 where there were no nonblocking reads. -fdc, 2007/02/22.
10883 */
10884 if ((n = read(fd, &n, 1)) < 1)
10885 break; /* Error - break out of while loop */
10886
10887 #endif /* MYREAD */
10888
10889 /* Get here with char in n */
10890
10891 #ifdef CK_ENCRYPTION
10892 if (TELOPT_U(TELOPT_ENCRYPTION) && !pushedback) {
10893 CHAR ch = n;
10894 ck_tn_decrypt((char *)&ch,1);
10895 n = ch;
10896 debug(F000,"TTINL decryp char","",n);
10897 }
10898 pushedback = 0;
10899 #endif /* CK_ENCRYPTION */
10900
10901 #ifdef TCPSOCKET
10902 if (n == IAC && /* Handle Telnet options */
10903 ((xlocal && netconn && IS_TELNET()) ||
10904 (!xlocal && sstelnet))) {
10905 n = tt_tnopt(n);
10906 if (n < 0)
10907 return(n);
10908 #ifndef NOPARSEN
10909 else if (n == 1)
10910 start = stchr;
10911 #endif /* NOPARSEN */
10912 if (n != 255) /* No data - go back for next char */
10913 continue;
10914 } /* Quoted IAC - keep going */
10915 #endif /* TCPSOCKET */
10916
10917 #ifdef CKXXCHAR
10918 if (ignflag)
10919 if (dblt[(unsigned) n] & 1) /* Character to ignore? */
10920 continue;
10921 #endif /* CKXXCHAR */
10922 /*
10923 Use parity mask, rather than always stripping parity, to check for
10924 cancellation. Otherwise, runs like \x03\x83\x03 in a packet could cancel
10925 the transfer when parity is NONE. (Note that \x03\x03\x03 is extremely
10926 unlikely due to run-length encoding.)
10927 */
10928 /* Check cancellation */
10929 if (!xlocal && xfrcan && ((n & ttpmsk) == xfrchr)) {
10930 if (++ccn >= xfrnum) { /* If xfrnum in a row, bail out. */
10931 if (timo) { /* Clear timer. */
10932 ttimoff();
10933 }
10934 if (xfrchr < 32)
10935 printf("^%c...\r\n",(char)(xfrchr+64));
10936 else
10937 printf("Canceled...\r\n");
10938 return(-2);
10939 }
10940 } else ccn = 0; /* No cancellation, reset counter, */
10941
10942 #ifdef PARSENSE
10943 /*
10944 Restructured code allows for a new packet to appear somewhere in the
10945 middle of a previous one. -fdc, 24 Feb 2007.
10946 */
10947 if ((n & sopmask) == start) { /* Start of Packet */
10948 debug(F101,"ttinl SOP i","",i);
10949 flag = 1; /* Flag that we are in a packet */
10950 havelen = 0; /* Invalidate previous length */
10951 pktlen = -1; /* (if any) in case we were */
10952 lplen = 0; /* alread processand a packet */
10953 i = 0; /* and reset the dest buffer pointer */
10954 }
10955 if (flag == 0) { /* No SOP yet... */
10956 debug(F000,"ttinl skipping","",n);
10957 continue;
10958 }
10959 dest[i++] = n & ttpmsk;
10960 /*
10961 If we have not been instructed to wait for a turnaround character, we can go
10962 by the packet length field. If turn != 0, we must wait for the end of line
10963 (eol) character before returning. This is an egregious violation of all
10964 principles of layering... (Less egregious in C-Kermit 9.0, in which we go
10965 by the length field but also look for the eol in case it arrives early,
10966 e.g. if the length field was corrupted upwards.)
10967 */
10968 if (!havelen) {
10969 if (i == 2) {
10970 if ((dest[1] & 0x7f) < 32) /* Garbage in length field */
10971 return(-1); /* fdc - 13 Apr 2010 */
10972 pktlen = xunchar(dest[1] & 0x7f);
10973 if (pktlen > 94) /* Rubout in length field */
10974 return(-1); /* fdc - 13 Apr 2010 */
10975 if (pktlen > 1) {
10976 havelen = 1;
10977 debug(F101,"ttinl pktlen value","",pktlen);
10978 }
10979 } else if (i == 5 && pktlen == 0) {
10980 lplen = xunchar(dest[4] & 0x7f);
10981 } else if (i == 6 && pktlen == 0) {
10982 pktlen = lplen * 95 + xunchar(dest[5] & 0x7f) + 5;
10983 havelen = 1;
10984 debug(F101,"ttinl extended length","",pktlen);
10985 }
10986 }
10987
10988 /*
10989 Suppose we looked at the sequence number here and found it was out of
10990 range? This would mean either (a) incoming packets had SOP unprefixed
10991 and we are out of sync, or (b) the packet is damaged. Since (a) is bad
10992 practice, let's ignore it. So what should we do here if we know the
10993 packet is damaged?
10994
10995 1. Nothing -- keep trying to read the packet till we find what we think
10996 is the end, or we time out, and let the upper layer decide what to
10997 do. But since either the packet is corrupt or we are out of sync,
10998 our criterion for finding the end does not apply and we are likely
10999 to time out (or swallow a piece of the next packet) if our assumed
11000 length is too long. (This was the behavior prior to version 7.0.)
11001
11002 2. set flag = 0 and continue? This would force us to wait for the
11003 next packet to come in, and therefore (in the nonwindowing case),
11004 would force a timeout in the other Kermit.
11005
11006 3. set flag = 0 and continue, but only if the window size is > 1 and
11007 the window is not blocked? Talk about cheating!
11008
11009 4. Return a failure code and let the upper layer decide what to do.
11010 This should be equivalent to 3, but without the cheating. So let's
11011 do it that way... But note that we must ignore the parity bit
11012 in case this is the first packet and we have not yet run parchk().
11013 */
11014 if (i == 3) { /* Peek at sequence number */
11015 x = xunchar((dest[i-1] & 0x7f)); /* If it's not in range... */
11016 if (x < 0 || x > 63) {
11017 debug(F111,"ttinl bad seq",dest,x);
11018 if (timo) ttimoff();
11019 return(-1); /* return a nonfatal error */
11020 }
11021 }
11022
11023 #else /* PARSENSE */
11024 dest[i++] = n & ttpmsk;
11025 #endif /* PARSENSE */
11026
11027 /* Check for end of packet */
11028
11029 if (
11030 ((n & ttpmsk) == eol) /* Always break on the eol char */
11031 #ifdef PARSENSE
11032 || /* fdc - see notes of 13 Apr 2010 */
11033 /*
11034 Purely length-driven if SET HANDSHAKE NONE (i.e. turn == 0).
11035 This allows packet terminators and handshake characters to appear
11036 literally inside a packet data field.
11037 */
11038 (havelen && (i > pktlen+1) &&
11039 (!turn || (turn && (n & 0x7f) == turn))) /* (turn, not eol) */
11040
11041 #endif /* PARSENSE */
11042 ) {
11043 /*
11044 Here we have either read the last byte of the packet based on its length
11045 field, or else we have read the packet terminator (eol) or the half-duplex
11046 line-turnaround char (turn).
11047 */
11048 #ifndef PARSENSE
11049 debug(F101,"ttinl got eol","",eol); /* (or turn) */
11050 dest[i] = '\0'; /* Yes, terminate the string, */
11051 /* debug(F101,"ttinl i","",i); */
11052
11053 #else /* PARSENSE */
11054
11055 #ifdef DEBUG
11056 if (deblog) {
11057 if ((n & ttpmsk) != eol) {
11058 debug(F101,"ttinl EOP length","",pktlen);
11059 debug(F000,"ttinl EOP current char","",n);
11060 debug(F101,"ttinl EOP packet buf index","",i);
11061 } else debug(F101,"ttinl got eol","",eol);
11062 }
11063 #endif /* DEBUG */
11064
11065 #ifdef MYREAD
11066 /*
11067 The packet was read based on its length. This leaves the packet terminator
11068 unread, and so ttchk() will always return at least 1 because of this,
11069 possibly giving a false positive to the "is there another packet waiting?"
11070 test. But if we know the terminator (or any other interpacket junk) is
11071 there, we can safely get rid of it.
11072
11073 NOTE: This code reworked to (a) execute even if the debug log isn't active;
11074 and (b) actually work. -fdc, 2007/02/22. And again 2007/08/12-13 to also
11075 work on encrypted connections.
11076 */
11077 debug(F101,"TTINL my_count","",my_count);
11078 if ((n & ttpmsk) != eol) { /* Not the packet terminator */
11079 int x;
11080 while (my_count > 0) {
11081 x = myread(); /* (was ttinc(0) */
11082 debug(F000,"TTINL lkread char","",x);
11083 #ifdef CK_ENCRYPTION
11084 if (TELOPT_U(TELOPT_ENCRYPTION)) {
11085 CHAR ch = x;
11086 ck_tn_decrypt((char *)&ch,1);
11087 x = ch;
11088 debug(F000,"TTINL lkdecr char","",x);
11089 }
11090 #endif /* CK_ENCRYPTION */
11091 /*
11092 Note: while it might seem more elegant to simply
11093 push back the encrypted byte, that desynchronizes
11094 the decryption stream; the flag is necessary so we
11095 don't try to decrypt the same byte twice.
11096 */
11097 if ((x & ttpmsk) == start) { /* Start of next packet */
11098 myunrd(x); /* Push back the decrypted byte */
11099 pushedback = 1; /* And set flag */
11100 debug(F000,"TTINL lkpush char","",x);
11101 break;
11102 }
11103 }
11104 }
11105 #endif /* MYREAD */
11106
11107 dest[i] = '\0'; /* Terminate the string, */
11108 if (needpchk) { /* Parity checked yet? */
11109 if (ttprty == 0) { /* No, check. */
11110 if ((ttprty = parchk(dest,start,i)) > 0) {
11111 int j;
11112 debug(F101,"ttinl senses parity","",ttprty);
11113 debug(F110,"ttinl packet before",dest,0);
11114 ttpmsk = 0x7f;
11115 for (j = 0; j < i; j++)
11116 dest[j] &= 0x7f; /* Strip parity from packet */
11117 debug(F110,"ttinl packet after ",dest,0);
11118 } else ttprty = 0; /* Restore if parchk error */
11119 }
11120 sopmask = ttpmsk;
11121 needpchk = 0;
11122 }
11123 #endif /* PARSENSE */
11124
11125 if (timo) /* Turn off timer if it was on */
11126 ttimoff();
11127 ckhexdump("ttinl got",dest,i);
11128
11129 #ifdef STREAMING
11130 /* ttinl() was called because there was non-packet */
11131 /* data sitting in the back channel. Ignore it. */
11132 if (streaming && sndtyp == 'D')
11133 return(-1);
11134 #endif /* STREAMING */
11135 return(i);
11136 }
11137 } /* End of while() */
11138 ttimoff();
11139 return(n);
11140 }
11141 }
11142 #endif /* NOXFER */
11143
11144 /* T T I N C -- Read a character from the communication line */
11145 /*
11146 On success, returns the character that was read, >= 0.
11147 On failure, returns -1 or other negative myread error code,
11148 or -2 if connection is broken or ttyfd < 0.
11149 or -3 if session limit has expired,
11150 or -4 if something or other...
11151 NOTE: The API does not provide for ttinc() returning a special code
11152 upon timeout, but we need it. So for this we have a global variable,
11153 ttinctimo.
11154 */
11155 static int ttinctimo = 0; /* Yuk */
11156
11157 int
ttinc(timo)11158 ttinc(timo) int timo; {
11159
11160 int n = 0, fd;
11161 int is_tn = 0;
11162 CHAR ch = 0;
11163
11164 ttinctimo = 0;
11165
11166 if (ttyfd < 0) return(-2); /* Not open. */
11167
11168 is_tn = (xlocal && netconn && IS_TELNET()) ||
11169 (!xlocal && sstelnet);
11170
11171 #ifdef TTLEBUF
11172 if (ttpush >= 0) {
11173 debug(F111,"ttinc","ttpush",ttpush);
11174 ch = ttpush;
11175 ttpush = -1;
11176 return(ch);
11177 }
11178 if (le_data) {
11179 if (le_getchar(&ch) > 0) {
11180 debug(F111,"ttinc le_getchar","ch",ch);
11181 return(ch);
11182 }
11183 }
11184 #endif /* TTLEBUF */
11185
11186 #ifdef NETCMD
11187 if (ttpipe)
11188 fd = fdin;
11189 else
11190 #endif /* NETCMD */
11191 fd = ttyfd;
11192
11193 if ((timo <= 0) /* Untimed. */
11194 #ifdef MYREAD
11195 || (my_count > 0) /* Buffered char already waiting. */
11196 #endif /* MYREAD */
11197 ) {
11198 #ifdef MYREAD
11199 /* Comm line failure returns -1 thru myread, so no &= 0377 */
11200 n = myread(); /* Wait for a character... */
11201 /* debug(F000,"ttinc MYREAD n","",n); */
11202 #ifdef CK_ENCRYPTION
11203 /* debug(F101,"ttinc u_encrypt","",TELOPT_U(TELOPT_ENCRYPTION)); */
11204 if (TELOPT_U(TELOPT_ENCRYPTION) && n >= 0) {
11205 ch = n;
11206 ck_tn_decrypt((char *)&ch,1);
11207 n = ch;
11208 }
11209 #endif /* CK_ENCRYPTION */
11210
11211 #ifdef NETPTY
11212 if (ttpty && n < 0) {
11213 debug(F101,"ttinc error on pty","",n);
11214 ttclos(0);
11215 return(n);
11216 }
11217 #endif /* NETPTY */
11218
11219 #ifdef TNCODE
11220 if ((n > -1) && is_tn)
11221 return((unsigned)(n & 0xff));
11222 else
11223 #endif /* TNCODE */
11224 return(n < 0 ? n : (unsigned)(n & ttpmsk));
11225
11226 #else /* MYREAD */
11227
11228 while ((n = read(fd,&ch,1)) == 0) /* Wait for a character. */
11229 /* Shouldn't have to loop in ver 5A. */
11230 #ifdef NETCONN
11231 if (netconn) { /* Special handling for net */
11232 netclos(); /* If read() returns 0 it means */
11233 netconn = 0; /* the connection has dropped. */
11234 errno = ENOTCONN;
11235 return(-2);
11236 }
11237 #endif /* NETCONN */
11238 ;
11239 /* debug(F101,"ttinc","",ch); */
11240 #ifdef TNCODE
11241 if ((n > 0) && is_tn) {
11242 #ifdef CK_ENCRYPTION
11243 if (TELOPT_U(TELOPT_ENCRYPTION)) {
11244 ck_tn_decrypt(&ch,1);
11245 n = ch;
11246 }
11247 #endif /* CK_ENCRYPTION */
11248 return((unsigned)(ch & 0xff));
11249 } else
11250 #endif /* TNCODE */
11251 return((n < 0) ? -4 : ((n == 0) ? -1 : (unsigned)(ch & ttpmsk)));
11252 #endif /* MYREAD */
11253
11254 } else { /* Timed read */
11255
11256 int oldalarm;
11257 saval = signal(SIGALRM,timerh); /* Set up handler, save old one. */
11258 oldalarm = alarm(timo); /* Set alarm, save old one. */
11259 if (
11260 #ifdef CK_POSIX_SIG
11261 sigsetjmp(sjbuf,1)
11262 #else
11263 setjmp(sjbuf)
11264 #endif /* CK_POSIX_SIG */
11265 ) { /* Timer expired */
11266 ttinctimo = 1;
11267 n = -1; /* set flag */
11268 } else {
11269 #ifdef MYREAD
11270 n = myread(); /* If managing own buffer... */
11271 debug(F101,"ttinc myread","",n);
11272 ch = n;
11273 #else
11274 n = read(fd,&ch,1); /* Otherwise call the system. */
11275 if (n == 0) n = -1;
11276 debug(F101,"ttinc read","",n);
11277 #endif /* MYREAD */
11278
11279 #ifdef CK_ENCRYPTION
11280 if (TELOPT_U(TELOPT_ENCRYPTION) && n >= 0) {
11281 ck_tn_decrypt((char *)&ch,1);
11282 }
11283 #endif /* CK_ENCRYPTION */
11284 if (n >= 0)
11285 n = (unsigned) (ch & 0xff);
11286 else
11287 n = (n < 0) ? -4 : -2; /* Special return codes. */
11288 }
11289 ttimoff(); /* Turn off the timer */
11290 if (oldalarm > 0) {
11291 if (n == -1) /* and restore any previous alarm */
11292 oldalarm -= timo;
11293 if (oldalarm < 0) /* adjusted by our timeout interval */
11294 oldalarm = 0;
11295 if (oldalarm) {
11296 debug(F101,"ttinc restoring oldalarm","",oldalarm);
11297 alarm(oldalarm);
11298 }
11299 }
11300 #ifdef NETCONN
11301 if (netconn) {
11302 if (n == -2) { /* read() returns 0 */
11303 netclos(); /* on network read failure */
11304 netconn = 0;
11305 errno = ENOTCONN;
11306 }
11307 }
11308 #endif /* NETCONN */
11309 #ifdef TNCODE
11310 if ((n > -1) && is_tn)
11311 return((unsigned)(n & 0xff));
11312 else
11313 #endif /* TNCODE */
11314 /* Return masked char or neg. */
11315 return( (n < 0) ? n : (unsigned)(n & ttpmsk) );
11316 }
11317 }
11318
11319 /* S N D B R K -- Send a BREAK signal of the given duration */
11320
11321 static int
11322 #ifdef CK_ANSIC
sndbrk(int msec)11323 sndbrk(int msec) { /* Argument is milliseconds */
11324 #else
11325 sndbrk(msec) int msec; {
11326 #endif /* CK_ANSIC */
11327 #ifndef POSIX
11328 int x, n;
11329 #endif /* POSIX */
11330
11331 #ifdef OXOS
11332 #define BSDBREAK
11333 #endif /* OXOS */
11334
11335 #ifdef ANYBSD
11336 #define BSDBREAK
11337 #endif /* ANYBSD */
11338
11339 #ifdef BSD44
11340 #define BSDBREAK
11341 #endif /* BSD44 */
11342
11343 #ifdef COHERENT
11344 #ifdef BSDBREAK
11345 #undef BSDBREAK
11346 #endif /* BSDBREAK */
11347 #endif /* COHERENT */
11348
11349 #ifdef BELLV10
11350 #ifdef BSDBREAK
11351 #undef BSDBREAK
11352 #endif /* BSDBREAK */
11353 #endif /* BELLV10 */
11354
11355 #ifdef PROVX1
11356 char spd;
11357 #endif /* PROVX1 */
11358
11359 debug(F101,"ttsndb ttyfd","",ttyfd);
11360 if (ttyfd < 0) return(-1); /* Not open. */
11361
11362 #ifdef Plan9
11363 return p9sndbrk(msec);
11364 #else
11365 #ifdef NETCONN
11366 #ifdef NETCMD
11367 if (ttpipe) /* Pipe */
11368 return(ttoc('\0'));
11369 #endif /* NETCMD */
11370 #ifdef NETPTY
11371 if (ttpty)
11372 return(ttoc('\0'));
11373 #endif /* NETPTY */
11374 if (netconn) /* Send network BREAK */
11375 return(netbreak());
11376 #endif /* NETCONN */
11377
11378 if (msec < 1 || msec > 5000) return(-1); /* Bad argument */
11379
11380 #ifdef POSIX /* Easy in POSIX */
11381 {
11382 int x;
11383 debug(F111,"sndbrk POSIX",ckitoa(msec),(msec/375));
11384 errno = 0;
11385 x = tcsendbreak(ttyfd,msec / 375);
11386 debug(F111,"sndbrk tcsendbreak",ckitoa(errno),x);
11387 return(x);
11388 }
11389 #else
11390 #ifdef PROVX1
11391 gtty(ttyfd,&ttbuf); /* Get current tty flags */
11392 spd = ttbuf.sg_ospeed; /* Save speed */
11393 ttbuf.sg_ospeed = B50; /* Change to 50 baud */
11394 stty(ttyfd,&ttbuf); /* ... */
11395 n = (int)strlen(brnuls); /* Send the right number of nulls */
11396 x = msec / 91;
11397 if (x > n) x = n;
11398 write(ttyfd,brnuls,n);
11399 ttbuf.sg_ospeed = spd; /* Restore speed */
11400 stty(ttyfd,&ttbuf); /* ... */
11401 return(0);
11402 #else
11403 #ifdef aegis
11404 sio_$control((short)ttyfd, sio_$send_break, msec, st);
11405 return(0);
11406 #else
11407 #ifdef BSDBREAK
11408 n = FWRITE; /* Flush output queue. */
11409 /* Watch out for int vs long problems in &n arg! */
11410 debug(F101,"sndbrk BSDBREAK","",msec);
11411 ioctl(ttyfd,TIOCFLUSH,&n); /* Ignore any errors.. */
11412 if (ioctl(ttyfd,TIOCSBRK,(char *)0) < 0) { /* Turn on BREAK */
11413 perror("Can't send BREAK");
11414 return(-1);
11415 }
11416 x = msleep(msec); /* Sleep for so many milliseconds */
11417 if (ioctl(ttyfd,TIOCCBRK,(char *)0) < 0) { /* Turn off BREAK */
11418 perror("BREAK stuck!!!");
11419 doexit(BAD_EXIT,-1); /* Get out, closing the line. */
11420 /* with bad exit status */
11421 }
11422 return(x);
11423 #else
11424 #ifdef ATTSV
11425 /*
11426 No way to send a long BREAK in Sys V, so send a bunch of regular ones.
11427 (Actually, Sys V R4 is *supposed* to have the POSIX tcsendbreak() function,
11428 but there's no way for this code to know for sure.)
11429 */
11430 debug(F101,"sndbrk ATTSV","",msec);
11431 x = msec / 275;
11432 for (n = 0; n < x; n++) {
11433 /* Reportedly the cast breaks this function on some systems */
11434 /* But then why was it here in the first place? */
11435 if (ioctl(ttyfd,TCSBRK, /* (char *) */ 0) < 0) {
11436 perror("Can't send BREAK");
11437 return(-1);
11438 }
11439 }
11440 return(0);
11441 #else
11442 #ifdef V7
11443 debug(F101,"sndbrk V7","",msec);
11444 return(genbrk(ttyfd,250)); /* Simulate a BREAK */
11445 #else
11446 debug(F101,"sndbrk catchall","",msec);
11447 ttoc(0);ttoc(0);ttoc(0);ttoc(0);
11448 return(0);
11449 #endif /* V7 */
11450 #endif /* BSDBREAK */
11451 #endif /* ATTSV */
11452 #endif /* aegis */
11453 #endif /* PROVX1 */
11454 #endif /* POSIX */
11455 #endif /* Plan9 */
11456 }
11457
11458 /* T T S N D B -- Send a BREAK signal */
11459
11460 int
11461 ttsndb() {
11462 #ifdef TN_COMPORT
11463 if (netconn && istncomport())
11464 return((tnsndb(275L) >= 0) ? 0 : -1);
11465 else
11466 #endif /* TN_COMPORT */
11467 return(sndbrk(275));
11468 }
11469
11470 /* T T S N D L B -- Send a Long BREAK signal */
11471
11472 int
11473 ttsndlb() {
11474 #ifdef TN_COMPORT
11475 if (netconn && istncomport())
11476 return((tnsndb(1800L) >= 0) ? 0 : -1);
11477 else
11478 #endif /* TN_COMPORT */
11479 return(sndbrk(1500));
11480 }
11481
11482 /* M S L E E P -- Millisecond version of sleep(). */
11483
11484 /*
11485 Call with number of milliseconds (thousandths of seconds) to sleep.
11486 Intended only for small intervals. For big ones, just use sleep().
11487 Highly system-dependent.
11488 Returns 0 always, even if it didn't work.
11489 */
11490
11491 /* Define MSLFTIME for systems that must use an ftime() loop. */
11492 #ifdef ANYBSD /* For pre-4.2 BSD versions */
11493 #ifndef BSD4
11494 #define MSLFTIME
11495 #endif /* BSD4 */
11496 #endif /* ANYBSD */
11497
11498 #ifdef TOWER1 /* NCR Tower OS 1.0 */
11499 #define MSLFTIME
11500 #endif /* TOWER1 */
11501
11502 #ifdef COHERENT /* Coherent... */
11503 #ifndef _I386 /* Maybe Coherent/386 should get this, too */
11504 #define MSLFTIME /* Opinions are divided */
11505 #endif /* _I386 */
11506 #endif /* COHERENT */
11507
11508 #ifdef COMMENT
11509 #ifdef GETMSEC
11510
11511 /* Millisecond timer */
11512
11513 static long msecbase = 0L; /* Unsigned long not portable */
11514
11515 long
11516 getmsec() { /* Milliseconds since base time */
11517 struct timeval xv;
11518 struct timezone xz;
11519 long secs, msecs;
11520 if (
11521 #ifdef GTODONEARG
11522 gettimeofday(&tv)
11523 #else
11524 #ifdef PTX
11525 gettimeofday(&tv, NULL)
11526 #else
11527 gettimeofday(&tv, &tz)
11528 #endif /* PTX */
11529 #endif /* GTODONEARG */
11530 < 0)
11531 return(-1);
11532 if (msecbase == 0L) { /* First call, set base time. */
11533 msecbase = tv.tv_sec;
11534 debug(F101,"getmsec base","",msecbase);
11535 }
11536 return(((tv.tv_sec - msecbase) * 1000L) + (tv.tv_usec / 1000L));
11537 }
11538 #endif /* GETMSEC */
11539 #endif /* COMMENT */
11540
11541 #ifdef SELECT
11542 int
11543 ttwait(fd, secs) int fd, secs; {
11544 int x;
11545 fd_set rfds;
11546 FD_ZERO(&rfds);
11547 FD_SET(fd,&rfds);
11548 tv.tv_sec = secs;
11549 tv.tv_usec = 0L;
11550 errno = 0;
11551 if ((x = select(FD_SETSIZE,
11552 #ifdef HPUX9
11553 (int *)
11554 #else
11555 #ifdef HPUX1000
11556 (int *)
11557 #endif /* HPUX1000 */
11558 #endif /* HPUX9 */
11559 &rfds,
11560 0, 0, &tv)) < 0) {
11561 debug(F101,"ttwait select errno","",errno);
11562 return(0);
11563 } else {
11564 debug(F101,"ttwait OK","",errno);
11565 x = FD_ISSET(fd, &rfds);
11566 debug(F101,"ttwait select x","",x);
11567 return(x ? 1 : 0);
11568 }
11569 }
11570 #endif /* SELECT */
11571
11572 int
11573 msleep(m) int m; {
11574 /*
11575 Other possibilities here are:
11576 nanosleep(), reportedly defined in POSIX.4.
11577 sginap(), IRIX only (back to what IRIX version I don't know).
11578 */
11579 #ifdef Plan9
11580 return _SLEEP(m);
11581 #else
11582 #ifdef BEOSORBEBOX
11583 snooze(m*1000);
11584 #else /* BEOSORBEBOX */
11585 #ifdef SELECT
11586 int t1, x;
11587 debug(F101,"msleep SELECT 1","",m);
11588 if (m <= 0) return(0);
11589 if (m >= 1000) { /* Catch big arguments. */
11590 sleep(m/1000);
11591 m = m % 1000;
11592 if (m < 10) return(0);
11593 }
11594 debug(F101,"msleep SELECT 2","",m);
11595 #ifdef BELLV10
11596 x = select( 0, (fd_set *)0, (fd_set *)0, (fd_set *)0, m );
11597 debug(F101,"msleep BELLV10 select","",x);
11598 #else /* BELLV10 */
11599 #ifdef HPUX9
11600 gettimeofday(&tv, &tz);
11601 #else
11602
11603 #ifndef COHERENT
11604 #ifdef GTODONEARG
11605 if (gettimeofday(&tv) < 0)
11606 #else
11607 #ifdef PTX
11608 if (gettimeofday(&tv,NULL) < 0)
11609 #else
11610 #ifdef NOTIMEZONE
11611 if (gettimeofday(&tv, NULL) < 0) /* wonder what this does... */
11612 #else
11613 if (gettimeofday(&tv, &tz) < 0)
11614 #endif /* NOTIMEZONE */
11615 #endif /* PTX */
11616 #endif /* GTODONEARG */
11617 return(-1);
11618 t1 = tv.tv_sec; /* Seconds */
11619 #endif /* COHERENT */
11620 #endif /* HPUX9 */
11621 tv.tv_sec = 0; /* Use select() */
11622 tv.tv_usec = m * 1000L;
11623 #ifdef BSD44
11624 x = select( 0, (fd_set *)0, (fd_set *)0, (fd_set *)0, &tv );
11625 debug(F101,"msleep BSD44 select","",x);
11626 #else /* BSD44 */
11627 #ifdef __linux__
11628 x = select( 0, (fd_set *)0, (fd_set *)0, (fd_set *)0, &tv );
11629 debug(F101,"msleep __linux__ select","",x);
11630 #else /* __linux__ */
11631 #ifdef BSD43
11632 x = select( 0, (fd_set *)0, (fd_set *)0, (fd_set *)0, &tv );
11633 debug(F101,"msleep BSD43 select","",x);
11634 #else /* BSD43 */
11635 #ifdef QNX6
11636 x = select( 0, (fd_set *)0, (fd_set *)0, (fd_set *)0, &tv );
11637 debug(F101,"msleep QNX6 select","",x);
11638 #else /* QNX6 */
11639 #ifdef QNX
11640 x = select( 0, (fd_set *)0, (fd_set *)0, (fd_set *)0, &tv );
11641 debug(F101,"msleep QNX select","",x);
11642 #else /* QNX */
11643 #ifdef COHERENT
11644 x = select( 0, (fd_set *)0, (fd_set *)0, (fd_set *)0, &tv );
11645 debug(F101,"msleep COHERENT select","",x);
11646 #else /* COHERENT */
11647 #ifdef HPUX1000 /* 10.00 only, not 10.10 or later */
11648 x = select( 0, (int *)0, (int *)0, (int *)0, &tv );
11649 debug(F101,"msleep HP-UX 10.00 select","",x);
11650 #else /* HPUX1000 */
11651 #ifdef SVR4
11652 x = select( 0, (fd_set *)0, (fd_set *)0, (fd_set *)0, &tv );
11653 debug(F101,"msleep SVR4 select","",x);
11654 #else /* SVR4 */
11655 #ifdef OSF40
11656 x = select( 0, (fd_set *)0, (fd_set *)0, (fd_set *)0, &tv );
11657 debug(F101,"msleep OSF40 select","",x);
11658 #else /* OSF40 */
11659 #ifdef PTX
11660 x = select( 0, (fd_set *)0, (fd_set *)0, (fd_set *)0, &tv );
11661 debug(F101,"msleep OSF40 select","",x);
11662 #else
11663 x = select( 0, (int *)0, (int *)0, (int *)0, &tv );
11664 debug(F101,"msleep catch-all select","",x);
11665 #endif /* PTX */
11666 #endif /* OSF40 */
11667 #endif /* HP1000 */
11668 #endif /* SVR4 */
11669 #endif /* COHERENT */
11670 #endif /* QNX */
11671 #endif /* QNX6 */
11672 #endif /* BSD43 */
11673 #endif /* __linux__ */
11674 #endif /* BSD44 */
11675 #endif /* BELLV10 */
11676 return(0);
11677
11678 #else /* Not SELECT */
11679 #ifdef CK_POLL /* We have poll() */
11680 struct pollfd pfd; /* Supply a valid address for poll() */
11681
11682 #ifdef ODT30 /* But in SCO ODT 3.0 */
11683 #ifdef NAP /* we should use nap() instead */
11684 debug(F101,"msleep ODT 3.0 NAP","",m); /* because using poll() here */
11685 nap((long)m); /* seems to break dialing. */
11686 return(0);
11687 #else
11688 debug(F101,"msleep ODT 3.0 POLL","",m);
11689 poll(&pfd, 0, m);
11690 return(0);
11691 #endif /* NAP */
11692 #else
11693 debug(F101,"msleep POLL","",m);
11694 poll(&pfd, 0, m);
11695 return(0);
11696 #endif /* ODT30 */
11697
11698 /*
11699 We could handle the above more cleanly by just letting nap() always
11700 take precedence over poll() in this routine, but there is no way to know
11701 whether that would break something else.
11702 */
11703
11704 #else /* Not POLL */
11705 #ifdef USLEEP
11706 /*
11707 "This routine is implemented using setitimer(2); it requires eight
11708 system calls...". In other words, it might take 5 minutes to sleep
11709 10 milliseconds...
11710 */
11711 debug(F101,"msleep USLEEP","",m);
11712 if (m >= 1000) { /* Catch big arguments. */
11713 sleep(m/1000);
11714 m = m % 1000;
11715 if (m < 10) return(0);
11716 }
11717 usleep((unsigned int)(m * 1000));
11718 return(0);
11719 #else
11720 #ifdef aegis
11721 time_$clock_t dur;
11722 debug(F101,"msleep aegis","",m);
11723 dur.c2.high16 = 0;
11724 dur.c2.low32 = 250 * m; /* one millisecond = 250 four microsecond ticks */
11725 time_$wait(time_$relative, dur, st);
11726 return(0);
11727 #else
11728 #ifdef PROVX1
11729 debug(F101,"msleep Venix","",m);
11730 if (m <= 0) return(0);
11731 sleep(-((m * 60 + 500) / 1000));
11732 return(0);
11733 #else
11734 #ifdef NAP
11735 debug(F101,"msleep NAP","",m);
11736 nap((long)m);
11737 return(0);
11738 #else
11739 #ifdef ATTSV
11740 #ifndef BSD44
11741 extern long times(); /* Or #include <times.h> ? */
11742 #endif /* BSD44 */
11743 long t1, t2, tarray[4];
11744 int t3;
11745 char *cp = getenv("HZ");
11746 int CLOCK_TICK;
11747 int hertz;
11748
11749 if (cp && (hertz = atoi(cp))) {
11750 CLOCK_TICK = 1000 / hertz;
11751 } else { /* probably single user mode */
11752 #ifdef HZ
11753 CLOCK_TICK = 1000 / HZ;
11754 #else
11755 static warned = 0;
11756 /* HZ always exists in, for instance, SCO Xenix, so you don't have to
11757 * make special #ifdefs for XENIX here, like in ver 4F. Also, if you
11758 * have Xenix, you have should have nap(), so the best is to use -DNAP
11759 * in the makefile. Most systems have HZ.
11760 */
11761 CLOCK_TICK = 17; /* 1/60 sec */
11762 if (!warned) {
11763 printf("warning: environment variable HZ bad... using HZ=%d\r\n",
11764 1000 / CLOCK_TICK);
11765 warned = 1;
11766 }
11767 #endif /* !HZ */
11768 }
11769 debug(F101,"msleep ATTSV","",m);
11770 if (m <= 0) return(0);
11771 if (m >= 1000) { /* Catch big arguments. */
11772 sleep(m/1000);
11773 m = m % 1000;
11774 if (m < 10) return(0);
11775 }
11776 if ((t1 = times(tarray)) < 0) return(-1);
11777 while (1) {
11778 if ((t2 = times(tarray)) < 0) return(-1);
11779 t3 = ((int)(t2 - t1)) * CLOCK_TICK;
11780 if (t3 > m) return(t3);
11781 }
11782 #else /* Not ATTSV */
11783 #ifdef MSLFTIME /* Use ftime() loop... */
11784 int t1, t3 = 0;
11785 debug(F101,"msleep MSLFTIME","",m);
11786 if (m <= 0) return(0);
11787 if (m >= 1000) { /* Catch big arguments. */
11788 sleep(m/1000);
11789 m = m % 1000;
11790 if (m < 10) return(0);
11791 }
11792 #ifdef QNX
11793 ftime(&ftp); /* void ftime() in QNX */
11794 #else
11795 if (ftime(&ftp) < 0) return(-1); /* Get base time. */
11796 #endif /* QNX */
11797 t1 = ((ftp.time & 0xff) * 1000) + ftp.millitm;
11798 while (1) {
11799 ftime(&ftp); /* Get current time and compare. */
11800 t3 = (((ftp.time & 0xff) * 1000) + ftp.millitm) - t1;
11801 if (t3 > m) return(0);
11802 }
11803 #else
11804 /* This includes true POSIX, which has no way to do this. */
11805 debug(F101,"msleep busy loop","",m);
11806 if (m >= 1000) { /* Catch big arguments. */
11807 sleep(m/1000);
11808 m = m % 1000;
11809 if (m < 10) return(0);
11810 }
11811 if (m > 0) while (m > 0) m--; /* Just a dumb busy loop */
11812 return(0);
11813 #endif /* MSLFTIME */
11814 #endif /* ATTSV */
11815 #endif /* NAP */
11816 #endif /* PROVX1 */
11817 #endif /* aegis */
11818 #endif /* CK_POLL */
11819 #endif /* SELECT */
11820 #endif /* BEOSORBEBOX */
11821 #endif /* USLEEP */
11822 #endif /* Plan9 */
11823 }
11824
11825 /* R T I M E R -- Reset elapsed time counter */
11826
11827 VOID
11828 rtimer() {
11829 tcount = time( (time_t *) 0 );
11830 }
11831
11832
11833 /* G T I M E R -- Get current value of elapsed time counter in seconds */
11834
11835 int
11836 gtimer() {
11837 int x;
11838 x = (int) (time( (time_t *) 0 ) - tcount);
11839 debug(F101,"gtimer","",x);
11840 return( (x < 0) ? 0 : x );
11841 }
11842
11843 #ifdef GFTIMER
11844 /*
11845 Floating-point timers. Require not only floating point support, but
11846 also gettimeofday().
11847 */
11848 static struct timeval tzero;
11849
11850 VOID
11851 rftimer() {
11852 #ifdef GTODONEARG /* Account for Mot's definition */
11853 (VOID) gettimeofday(&tzero);
11854 #else
11855 (VOID) gettimeofday(&tzero, (struct timezone *)0);
11856 #endif /* GTODONEARG */
11857 }
11858
11859 CKFLOAT
11860 gftimer() {
11861 struct timeval tnow, tdelta;
11862 CKFLOAT s;
11863 #ifdef DEBUG
11864 char fpbuf[64];
11865 #endif /* DEBUG */
11866 #ifdef GTODONEARG /* Account for Mot's definition */
11867 (VOID) gettimeofday(&tnow);
11868 #else
11869 (VOID) gettimeofday(&tnow, (struct timezone *)0);
11870 #endif /* GTODONEARG */
11871
11872 tdelta.tv_sec = tnow.tv_sec - tzero.tv_sec;
11873 tdelta.tv_usec = tnow.tv_usec - tzero.tv_usec;
11874
11875 if (tdelta.tv_usec < 0) {
11876 tdelta.tv_sec--;
11877 tdelta.tv_usec += 1000000;
11878 }
11879 s = (CKFLOAT) tdelta.tv_sec + ((CKFLOAT) tdelta.tv_usec / 1000000.0);
11880 if (s < GFMINTIME)
11881 s = GFMINTIME;
11882 #ifdef DEBUG
11883 if (deblog) {
11884 sprintf(fpbuf,"%f",s);
11885 debug(F110,"gftimer",fpbuf,0);
11886 }
11887 #endif /* DEBUG */
11888 return(s);
11889 }
11890 #endif /* GFTIMER */
11891
11892 /* Z T I M E -- Return asctime()-format date/time string */
11893 /*
11894 NOTE: as a side effect of calling this routine, we can also set the
11895 following two variables, giving the micro- and milliseconds (fractions of
11896 seconds) of the clock time. Currently this is done only in BSD-based builds
11897 that use gettimeofday(). When these variables are not filled in, they are
11898 left with a value of -1L.
11899 */
11900 static char asctmbuf[64];
11901
11902 VOID
11903 ztime(s) char **s; {
11904
11905 #ifdef GFTIMER
11906 /*
11907 The gettimeofday() method, which also sets ztmsec and ztusec, works for
11908 all GFTIMER builds. NOTE: ztmsec and ztusec are defined in ckcmai.c,
11909 and extern declarations for them are in ckcdeb.h; thus they are
11910 declared in this file by inclusion of ckcdeb.h.
11911 */
11912 char *asctime();
11913 struct tm *localtime();
11914 struct tm *tp;
11915 ztmsec = -1L;
11916 ztusec = -1L;
11917
11918 if (!s)
11919 debug(F100,"ztime s==NULL","",0);
11920
11921 #ifdef GTODONEARG
11922 /* No 2nd arg in Motorola SV88 and some others */
11923 if (gettimeofday(&tv) > -1)
11924 #else
11925 #ifndef COHERENT
11926 #ifdef PTX
11927 if (gettimeofday(&tv,NULL) > -1)
11928 #else
11929 #ifdef NOTIMEZONE
11930 if (gettimeofday(&tv, NULL) > -1) /* wonder what this does... */
11931 #else
11932 if (gettimeofday(&tv, &tz) > -1)
11933 #endif /* NOTIMEZONE */
11934 #endif /* PTX */
11935 #endif /* COHERENT */
11936 #endif /* GTODONEARG */
11937 { /* Fill in tm struct */
11938 ztusec = tv.tv_usec; /* Microseconds */
11939 ztmsec = ztusec / 1000L; /* Milliseconds */
11940 #ifdef HPUX9
11941 {
11942 time_t zz;
11943 zz = tv.tv_sec;
11944 tp = localtime(&zz); /* Convert to local time */
11945 }
11946 #else
11947 #ifdef HPUX1000
11948 {
11949 time_t zz;
11950 zz = tv.tv_sec;
11951 tp = localtime(&zz);
11952 }
11953 #else
11954 #ifdef LINUX
11955 { /* avoid unaligned access trap on 64-bit platforms */
11956 time_t zz;
11957 zz = tv.tv_sec;
11958 tp = localtime(&zz);
11959 }
11960 #else
11961 #ifdef MACOSX
11962 tp = localtime((time_t *)&tv.tv_sec); /* Convert to local time */
11963 #else
11964 tp = localtime(&tv.tv_sec);
11965 #endif /* MACOSX */
11966 #endif /* LINUX */
11967 #endif /* HPUX1000 */
11968 #endif /* HPUX9 */
11969 if (s) {
11970 char * s2;
11971 s2 = asctime(tp); /* Convert result to ASCII string */
11972 asctmbuf[0] = '\0';
11973 if (s2) ckstrncpy(asctmbuf,s2,64);
11974 *s = asctmbuf;
11975 debug(F111,"ztime GFTIMER gettimeofday",*s,ztusec);
11976 }
11977 }
11978 #else /* Not GFTIMER */
11979
11980 #undef ZTIMEV7 /* Which systems need to use */
11981 #ifdef COHERENT /* old UNIX Version 7 way... */
11982 #define ZTIMEV7
11983 #endif /* COHERENT */
11984 #ifdef TOWER1
11985 #define ZTIMEV7
11986 #endif /* TOWER1 */
11987 #ifdef ANYBSD
11988 #ifndef BSD42
11989 #define ZTIMEV7
11990 #endif /* BSD42 */
11991 #endif /* ANYBSD */
11992 #ifdef V7
11993 #ifndef MINIX
11994 #define ZTIMEV7
11995 #endif /* MINIX */
11996 #endif /* V7 */
11997 #ifdef POSIX
11998 #define ZTIMEV7
11999 #endif /* POSIX */
12000
12001 #ifdef HPUX1020
12002 /*
12003 Prototypes are in <time.h>, included above.
12004 */
12005 time_t clock_storage;
12006 clock_storage = time((void *) 0);
12007 if (s) {
12008 *s = ctime(&clock_storage);
12009 debug(F110,"ztime: HPUX 10.20",*s,0);
12010 }
12011 #else
12012 #ifdef ATTSV /* AT&T way */
12013 /* extern long time(); */ /* Theoretically these should */
12014 char *ctime(); /* already been dcl'd in <time.h> */
12015 time_t clock_storage;
12016 clock_storage = time(
12017 #ifdef IRIX60
12018 (time_t *)
12019 #else
12020 #ifdef BSD44
12021 (time_t *)
12022 #else
12023 (long *)
12024 #endif /* BSD44 */
12025 #endif /* IRIX60 */
12026 0 );
12027 if (s) {
12028 *s = ctime( &clock_storage );
12029 debug(F110,"ztime: ATTSV",*s,0);
12030 }
12031 #else
12032 #ifdef PROVX1 /* Venix 1.0 way */
12033 int utime[2];
12034 time(utime);
12035 if (s) {
12036 *s = ctime(utime);
12037 debug(F110,"ztime: PROVX1",*s,0);
12038 }
12039 #else
12040 #ifdef BSD42 /* 4.2BSD way */
12041 char *asctime();
12042 struct tm *localtime();
12043 struct tm *tp;
12044 gettimeofday(&tv, &tz);
12045 ztusec = tv.tv_usec;
12046 ztmsec = tv.tv_usec / 1000L;
12047 tp = localtime(&tv.tv_sec);
12048 if (s) {
12049 *s = asctime(tp);
12050 debug(F111,"ztime: BSD42",*s,ztusec);
12051 }
12052 #else
12053 #ifdef MINIX /* MINIX way */
12054 #ifdef COMMENT
12055 extern long time(); /* Already got these from <time.h> */
12056 extern char *ctime();
12057 #endif /* COMMENT */
12058 time_t utime[2];
12059 time(utime);
12060 if (s) {
12061 *s = ctime(utime);
12062 debug(F110,"ztime: MINIX",*s,0);
12063 }
12064 #else
12065 #ifdef ZTIMEV7 /* The regular way */
12066 char *asctime();
12067 struct tm *localtime();
12068 struct tm *tp;
12069 long xclock; /* or unsigned long for BeBox? */
12070 time(&xclock);
12071 tp = localtime(&xclock);
12072 if (s) {
12073 *s = asctime(tp);
12074 debug(F110,"ztime: ZTIMEV7",*s,0);
12075 }
12076 #else /* Catch-all for others... */
12077 if (s) {
12078 *s = "Day Mon 00 00:00:00 0000\n"; /* Dummy in asctime() format */
12079 debug(F110,"ztime: catch-all",*s,0);
12080 }
12081 #endif /* ZTIMEV7 */
12082 #endif /* MINIX */
12083 #endif /* BSD42 */
12084 #endif /* PROVX1 */
12085 #endif /* ATTSV */
12086 #endif /* HPUX1020 */
12087 #endif /* GFTIMER */
12088 }
12089
12090 /* C O N G M -- Get console terminal modes. */
12091
12092 /*
12093 Saves initial console mode, and establishes variables for switching
12094 between current (presumably normal) mode and other modes.
12095 Should be called when program starts, but only after establishing
12096 whether program is in the foreground or background.
12097 Returns 1 if it got the modes OK, 0 if it did nothing, -1 on error.
12098 */
12099 int
12100 congm() {
12101 int fd;
12102 if (backgrd || !isatty(0)) { /* If in background. */
12103 cgmf = -1; /* Don't bother, modes are garbage. */
12104 return(-1);
12105 }
12106 if (cgmf > 0) return(0); /* Already did this. */
12107 debug(F100,"congm getting modes","",0); /* Need to do it. */
12108 #ifdef aegis
12109 ios_$inq_type_uid(ios_$stdin, conuid, st);
12110 if (st.all != status_$ok) {
12111 fprintf(stderr, "problem getting stdin objtype: ");
12112 error_$print(st);
12113 }
12114 concrp = (conuid == mbx_$uid);
12115 conbufn = 0;
12116 #endif /* aegis */
12117
12118 #ifndef BEBOX
12119 if ((fd = open(CTTNAM,2)) < 0) { /* Open controlling terminal */
12120 #ifdef COMMENT
12121 fprintf(stderr,"Error opening %s\n", CTTNAM);
12122 perror("congm");
12123 return(-1);
12124 #else
12125 fd = 0;
12126 #endif /* COMMENT */
12127 }
12128 #else
12129 fd = 0;
12130 #endif /* !BEBOX */
12131 #ifdef BSD44ORPOSIX
12132 if (tcgetattr(fd,&ccold) < 0) return(-1);
12133 if (tcgetattr(fd,&cccbrk) < 0) return(-1);
12134 if (tcgetattr(fd,&ccraw) < 0) return(-1);
12135 #else
12136 #ifdef ATTSV
12137 if (ioctl(fd,TCGETA,&ccold) < 0) return(-1);
12138 if (ioctl(fd,TCGETA,&cccbrk) < 0) return(-1);
12139 if (ioctl(fd,TCGETA,&ccraw) < 0) return(-1);
12140 #ifdef VXVE
12141 cccbrk.c_line = 0; /* STTY line 0 for CDC VX/VE */
12142 if (ioctl(fd,TCSETA,&cccbrk) < 0) return(-1);
12143 ccraw.c_line = 0; /* STTY line 0 for CDC VX/VE */
12144 if (ioctl(fd,TCSETA,&ccraw) < 0) return(-1);
12145 #endif /* VXVE */
12146 #else
12147 #ifdef BELLV10
12148 if (ioctl(fd,TIOCGETP,&ccold) < 0) return(-1);
12149 if (ioctl(fd,TIOCGETP,&cccbrk) < 0) return(-1);
12150 if (ioctl(fd,TIOCGETP,&ccraw) < 0) return(-1);
12151 debug(F101,"cccbrk.sg_flags orig","", cccbrk.sg_flags);
12152 #else
12153 if (gtty(fd,&ccold) < 0) return(-1);
12154 if (gtty(fd,&cccbrk) < 0) return(-1);
12155 if (gtty(fd,&ccraw) < 0) return(-1);
12156 #endif /* BELLV10 */
12157 #endif /* ATTSV */
12158 #endif /* BSD44ORPOSIX */
12159 #ifdef sony_news /* Sony NEWS */
12160 if (ioctl(fd,TIOCKGET,&km_con) < 0) { /* Get console Kanji mode */
12161 perror("congm error getting Kanji mode");
12162 debug(F101,"congm error getting Kanji mode","",0);
12163 km_con = -1; /* Make sure this stays undefined. */
12164 return(-1);
12165 }
12166 #endif /* sony_news */
12167 if (fd > 0)
12168 close(fd);
12169 cgmf = 1; /* Flag that we got them. */
12170 return(1);
12171 }
12172
12173
12174 static VOID
12175 congetbuf(x) int x; {
12176 int n;
12177 n = CONBUFSIZ - (conbufp - conbuf); /* How much room left in buffer? */
12178 if (x > n) {
12179 debug(F101,"congetbuf char loss","",x-n);
12180 x = n;
12181 }
12182 x = read(0,conbufp,x);
12183 conbufn += x;
12184 debug(F111,"congetbuf readahead",conbuf,x);
12185 }
12186
12187
12188 /* C O N C B -- Put console in cbreak mode. */
12189
12190 /* Returns 0 if ok, -1 if not */
12191
12192 int
12193 #ifdef CK_ANSIC
12194 concb(char esc)
12195 #else
12196 concb(esc) char esc;
12197 #endif /* CK_ANSIC */
12198 /* concb */ {
12199 int x, y = 0;
12200 debug(F101,"concb constate","",constate);
12201 debug(F101,"concb cgmf","",cgmf);
12202 debug(F101,"concb backgrd","",backgrd);
12203
12204 if (constate == CON_CB)
12205 return(0);
12206
12207 if (cgmf < 1) /* Did we get console modes yet? */
12208 if (!backgrd) /* No, in background? */
12209 congm(); /* No, try to get them now. */
12210 if (cgmf < 1) /* Still don't have them? */
12211 return(0); /* Give up. */
12212 debug(F101,"concb ttyfd","",ttyfd);
12213 debug(F101,"concb ttfdflg","",ttfdflg);
12214 #ifdef COMMENT
12215 /* This breaks returning to prompt after protocol with "-l 0" */
12216 /* Commented out July 1998 */
12217 if (ttfdflg && ttyfd >= 0 && ttyfd < 3)
12218 return(0);
12219 #endif /* COMMENT */
12220 x = isatty(0);
12221 debug(F101,"concb isatty","",x);
12222 if (!x) return(0); /* Only when running on real ttys */
12223 debug(F101,"concb xsuspend","",xsuspend);
12224 if (backgrd) /* Do nothing if in background. */
12225 return(0);
12226 escchr = esc; /* Make this available to other fns */
12227 ckxech = 1; /* Program can echo characters */
12228 #ifdef aegis
12229 conbufn = 0;
12230 if (concrp) return(write(1, "\035\002", 2));
12231 if (conuid == input_pad_$uid) {pad_$raw(ios_$stdin, st); return(0);}
12232 #endif /* aegis */
12233
12234 #ifdef COHERENT
12235 #define SVORPOSIX
12236 #endif /* COHERENT */
12237
12238 #ifdef Plan9
12239 x = p9concb();
12240 #else
12241 #ifndef SVORPOSIX /* BSD, V7, etc */
12242 debug(F101,"cccbrk.sg_flags concb 1","", cccbrk.sg_flags);
12243 debug(F101,"concb stty CBREAK","",0);
12244 cccbrk.sg_flags |= (CBREAK|CRMOD); /* Set to character wakeup, */
12245 cccbrk.sg_flags &= ~ECHO; /* no echo. */
12246 debug(F101,"cccbrk.sg_flags concb 2","", cccbrk.sg_flags);
12247 errno = 0;
12248 /*
12249 BSD stty() clears the console buffer. So if anything is waiting in it,
12250 we have to read it now to avoid losing it.
12251 */
12252 x = conchk();
12253 if (x > 0)
12254 congetbuf(x);
12255
12256 #ifdef BELLV10
12257 x = ioctl(0,TIOCSETP,&cccbrk);
12258 #else
12259 x = stty(0,&cccbrk);
12260 debug(F101,"cccbrk.sg_flags concb x","", x);
12261 #endif /* BELLV10 */
12262 #else /* Sys V and POSIX */
12263 #ifndef OXOS
12264 debug(F101,"concb cccbrk.c_flag","",cccbrk.c_lflag);
12265 #ifdef QNX
12266 /* Don't mess with IEXTEN */
12267 cccbrk.c_lflag &= ~(ICANON|ECHO);
12268 #else
12269 #ifdef COHERENT
12270 cccbrk.c_lflag &= ~(ICANON|ECHO);
12271 #else
12272 cccbrk.c_lflag &= ~(ICANON|ECHO|IEXTEN);
12273 #endif /* COHERENT */
12274 #endif /* QNX */
12275 cccbrk.c_lflag |= ISIG; /* Allow signals in command mode. */
12276 cccbrk.c_iflag |= IGNBRK; /* But ignore BREAK signal */
12277 cccbrk.c_iflag &= ~BRKINT;
12278
12279 #else /* OXOS */
12280 debug(F100,"concb OXOS is defined","",0);
12281 cccbrk.c_lflag &= ~(ICANON|ECHO);
12282 cccbrk.c_cc[VDISCARD] = cccbrk.c_cc[VLNEXT] = CDISABLE;
12283 #endif /* OXOS */
12284 #ifdef COMMENT
12285 /*
12286 Believe it or not, in SCO UNIX, VSUSP is greater than NCC, and so this
12287 array reference is out of bounds. It's only a debug() call so who needs it.
12288 */
12289 #ifdef VSUSP
12290 debug(F101,"concb c_cc[VSUSP]","",cccbrk.c_cc[VSUSP]);
12291 #endif /* VSUSP */
12292 #endif /* COMMENT */
12293 #ifndef VINTR
12294 debug(F101,"concb c_cc[0]","",cccbrk.c_cc[0]);
12295 cccbrk.c_cc[0] = 003; /* Interrupt char is Control-C */
12296 #else
12297 debug(F101,"concb c_cc[VINTR]","",cccbrk.c_cc[0]);
12298 cccbrk.c_cc[VINTR] = 003;
12299 #endif /* VINTR */
12300 #ifndef VQUIT
12301 cccbrk.c_cc[1] = escchr; /* escape during packet modes */
12302 #else
12303 cccbrk.c_cc[VQUIT] = escchr;
12304 #endif /* VQUIT */
12305 #ifndef VEOF
12306 cccbrk.c_cc[4] = 1;
12307 #else
12308 #ifndef OXOS
12309 #ifdef VMIN
12310 cccbrk.c_cc[VMIN] = 1;
12311 #endif /* VMIN */
12312 #else /* OXOS */
12313 cccbrk.c_min = 1;
12314 #endif /* OXOS */
12315 #endif /* VEOF */
12316 #ifdef ZILOG
12317 cccbrk.c_cc[5] = 0;
12318 #else
12319 #ifndef VEOL
12320 cccbrk.c_cc[5] = 1;
12321 #else
12322 #ifndef OXOS
12323 #ifdef VTIME
12324 cccbrk.c_cc[VTIME] = 1;
12325 #endif /* VTIME */
12326 #else /* OXOS */
12327 cccbrk.c_time = 1;
12328 #endif /* OXOS */
12329 #endif /* VEOL */
12330 #endif /* ZILOG */
12331 errno = 0;
12332 #ifdef BSD44ORPOSIX /* Set new modes */
12333 x = tcsetattr(0,TCSADRAIN,&cccbrk);
12334 #else /* ATTSV */ /* or the POSIX way */
12335 x = ioctl(0,TCSETAW,&cccbrk); /* the Sys V way */
12336 #endif /* BSD44ORPOSIX */
12337 #endif /* SVORPOSIX */
12338
12339 #ifdef COHERENT
12340 #undef SVORPOSIX
12341 #endif /* COHERENT */
12342
12343 debug(F101,"concb x","",x);
12344 debug(F101,"concb errno","",errno);
12345
12346 #ifdef V7
12347 #ifndef MINIX
12348 if (kmem[CON] < 0) {
12349 qaddr[CON] = initrawq(0);
12350 if((kmem[CON] = open("/dev/kmem", 0)) < 0) {
12351 fprintf(stderr, "Can't read /dev/kmem in concb.\n");
12352 perror("/dev/kmem");
12353 exit(1);
12354 }
12355 }
12356 #endif /* MINIX */
12357 #endif /* V7 */
12358 #endif /* Plan9 */
12359
12360 if (x > -1)
12361 constate = CON_CB;
12362
12363 debug(F101,"concb returns","",x);
12364 return(x);
12365 }
12366
12367 /* C O N B I N -- Put console in binary mode */
12368
12369 /* Returns 0 if ok, -1 if not */
12370
12371 int
12372 #ifdef CK_ANSIC
12373 conbin(char esc)
12374 #else
12375 conbin(esc) char esc;
12376 #endif /* CK_ANSIC */
12377 /* conbin */ {
12378
12379 int x;
12380
12381 debug(F101,"conbin constate","",constate);
12382
12383 if (constate == CON_BIN)
12384 return(0);
12385
12386 if (!isatty(0)) return(0); /* only for real ttys */
12387 congm(); /* Get modes if necessary. */
12388 debug(F100,"conbin","",0);
12389 escchr = esc; /* Make this available to other fns */
12390 ckxech = 1; /* Program can echo characters */
12391 #ifdef aegis
12392 conbufn = 0;
12393 if (concrp) return(write(1, "\035\002", 2));
12394 if (conuid == input_pad_$uid) {
12395 pad_$raw(ios_$stdin, st);
12396 return(0);
12397 }
12398 #endif /* aegis */
12399
12400 #ifdef COHERENT
12401 #define SVORPOSIX
12402 #endif /* COHERENT */
12403
12404 #ifdef Plan9
12405 return p9conbin();
12406 #else
12407 #ifdef SVORPOSIX
12408 #ifndef OXOS
12409 #ifdef QNX
12410 ccraw.c_lflag &= ~(ISIG|ICANON|ECHO);
12411 #else
12412 #ifdef COHERENT
12413 ccraw.c_lflag &= ~(ISIG|ICANON|ECHO);
12414 #else
12415 ccraw.c_lflag &= ~(ISIG|ICANON|ECHO|IEXTEN);
12416 #endif /* COHERENT */
12417 #endif /* QNX */
12418 #else /* OXOS */
12419 ccraw.c_lflag &= ~(ISIG|ICANON|ECHO);
12420 ccraw.c_cc[VDISCARD] = ccraw.c_cc[VLNEXT] = CDISABLE;
12421 #endif /* OXOS */
12422 ccraw.c_iflag |= IGNPAR;
12423 /*
12424 Note that for terminal sessions we disable Xon/Xoff flow control to allow
12425 the passage ^Q and ^S as data characters for EMACS, and to allow XMODEM
12426 transfers to work when C-Kermit is in the middle, etc. Hardware flow
12427 control, if in use, is not affected.
12428 */
12429 #ifdef ATTSV
12430 #ifdef BSD44
12431 ccraw.c_iflag &= ~(IGNBRK|INLCR|IGNCR|ICRNL|IXON|IXANY|IXOFF
12432 |INPCK|ISTRIP);
12433 #else
12434 ccraw.c_iflag &= ~(IGNBRK|INLCR|IGNCR|ICRNL|IUCLC|IXON|IXANY|IXOFF
12435 |INPCK|ISTRIP);
12436 #endif /* BSD44 */
12437 #else /* POSIX */
12438 ccraw.c_iflag &= ~(IGNBRK|INLCR|IGNCR|ICRNL|IXON|IXOFF|INPCK|ISTRIP);
12439 #endif /* ATTSV */
12440 ccraw.c_oflag &= ~OPOST;
12441 #ifdef COMMENT
12442 /*
12443 WHAT THE HECK WAS THIS FOR?
12444 The B9600 setting (obviously) prevents CONNECT from working at any
12445 speed other than 9600 when you are logged in to the 7300 on a serial
12446 line. Maybe some of the other flags are necessary -- if so, put back
12447 the ones that are needed. This code is supposed to work the same, no
12448 matter whether you are logged in to the 7300 on the real console device,
12449 or through a serial port.
12450 */
12451 #ifdef ATT7300
12452 ccraw.c_cflag = CLOCAL | B9600 | CS8 | CREAD | HUPCL;
12453 #endif /* ATT7300 */
12454 #endif /* COMMENT */
12455
12456 /*** Kermit used to put the console in 8-bit raw mode, but some users have
12457 *** pointed out that this should not be done, since some sites actually
12458 *** use terminals with parity settings on their Unix systems, and if we
12459 *** override the current settings and stop doing parity, then their terminals
12460 *** will display blotches for characters whose parity is wrong. Therefore,
12461 *** the following two lines are commented out (Larry Afrin, Clemson U):
12462 ***
12463 *** ccraw.c_cflag &= ~(PARENB|CSIZE);
12464 *** ccraw.c_cflag |= (CS8|CREAD);
12465 ***
12466 *** Sys III/V sites that have trouble with this can restore these lines.
12467 ***/
12468 #ifndef VINTR
12469 ccraw.c_cc[0] = 003; /* Interrupt char is Ctrl-C */
12470 #else
12471 ccraw.c_cc[VINTR] = 003;
12472 #endif /* VINTR */
12473 #ifndef VQUIT
12474 ccraw.c_cc[1] = escchr; /* Escape during packet mode */
12475 #else
12476 ccraw.c_cc[VQUIT] = escchr;
12477 #endif /* VQUIT */
12478 #ifndef VEOF
12479 ccraw.c_cc[4] = 1;
12480 #else
12481 #ifndef OXOS
12482 #ifdef VMIN
12483 ccraw.c_cc[VMIN] = 1;
12484 #endif /* VMIN */
12485 #else /* OXOS */
12486 ccraw.c_min = 1;
12487 #endif /* OXOS */
12488 #endif /* VEOF */
12489
12490 #ifdef ZILOG
12491 ccraw.c_cc[5] = 0;
12492 #else
12493 #ifndef VEOL
12494 ccraw.c_cc[5] = 1;
12495 #else
12496 #ifndef OXOS
12497 #ifdef VTIME
12498 ccraw.c_cc[VTIME] = 1;
12499 #endif /* VTIME */
12500 #else /* OXOS */
12501 ccraw.c_time = 1;
12502 #endif /* OXOS */
12503 #endif /* VEOL */
12504 #endif /* ZILOG */
12505
12506 #ifdef BSD44ORPOSIX
12507 x = tcsetattr(0,TCSADRAIN,&ccraw); /* Set new modes. */
12508 #else
12509 x = ioctl(0,TCSETAW,&ccraw);
12510 #endif /* BSD44ORPOSIX */
12511 #else /* Berkeley, etc. */
12512 x = conchk(); /* Because stty() is destructive */
12513 if (x > 0)
12514 congetbuf(x);
12515 ccraw.sg_flags |= (RAW|TANDEM); /* Set rawmode, XON/XOFF (ha) */
12516 ccraw.sg_flags &= ~(ECHO|CRMOD); /* Set char wakeup, no echo */
12517 #ifdef BELLV10
12518 x = ioctl(0,TIOCSETP,&ccraw);
12519 #else
12520 x = stty(0,&ccraw);
12521 #endif /* BELLV10 */
12522 #endif /* SVORPOSIX */
12523 #endif /* Plan9 */
12524
12525 if (x > -1)
12526 constate = CON_BIN;
12527
12528 debug(F101,"conbin returns","",x);
12529 return(x);
12530
12531 #ifdef COHERENT
12532 #undef SVORPOSIX
12533 #endif /* COHERENT */
12534
12535 }
12536
12537
12538 /* C O N R E S -- Restore the console terminal */
12539
12540 int
12541 conres() {
12542 int x;
12543 debug(F101,"conres cgmf","",cgmf);
12544 debug(F101,"conres constate","",constate);
12545
12546 if (cgmf < 1) /* Do nothing if modes unchanged */
12547 return(0);
12548 if (constate == CON_RES)
12549 return(0);
12550
12551 if (!isatty(0)) return(0); /* only for real ttys */
12552 debug(F100,"conres isatty ok","",0);
12553 ckxech = 0; /* System should echo chars */
12554
12555 #ifdef aegis
12556 conbufn = 0;
12557 if (concrp) return(write(1, "\035\001", 2));
12558 if (conuid == input_pad_$uid) {
12559 pad_$cooked(ios_$stdin, st);
12560 constate = CON_RES;
12561 return(0);
12562 }
12563 #endif /* aegis */
12564
12565 #ifdef Plan9
12566 p9conres();
12567 #else
12568 #ifdef BSD44ORPOSIX
12569 debug(F100,"conres restoring tcsetattr","",0);
12570 x = tcsetattr(0,TCSADRAIN,&ccold);
12571 #else
12572 #ifdef ATTSV
12573 debug(F100,"conres restoring ioctl","",0);
12574 x = ioctl(0,TCSETAW,&ccold);
12575 #else /* BSD, V7, and friends */
12576 #ifdef sony_news /* Sony NEWS */
12577 if (km_con != -1)
12578 ioctl(0,TIOCKSET,&km_con); /* Restore console Kanji mode */
12579 #endif /* sony_news */
12580 msleep(100);
12581 debug(F100,"conres restoring stty","",0);
12582 x = conchk(); /* Because stty() is destructive */
12583 if (x > 0)
12584 congetbuf(x);
12585 #ifdef BELLV10
12586 x = ioctl(0,TIOCSETP,&ccold);
12587 #else
12588 x = stty(0,&ccold);
12589 #endif /* BELLV10 */
12590 #endif /* ATTSV */
12591 #endif /* BSD44ORPOSIX */
12592 #endif /* Plan9 */
12593 if (x > -1)
12594 constate = CON_RES;
12595
12596 debug(F101,"conres returns","",x);
12597 return(x);
12598 }
12599
12600 /* C O N O C -- Output a character to the console terminal */
12601
12602 int
12603 #ifdef CK_ANSIC
12604 conoc(char c)
12605 #else
12606 conoc(c) char c;
12607 #endif /* CK_ANSIC */
12608 /* conoc */ {
12609
12610 #ifdef IKSD
12611 if (inserver && !local)
12612 return(ttoc(c));
12613
12614 #ifdef CK_ENCRYPTION
12615 if (inserver && TELOPT_ME(TELOPT_ENCRYPTION))
12616 ck_tn_encrypt(&c,1);
12617 #endif /* CK_ENCRYPTION */
12618 #endif /* IKSD */
12619
12620 #ifdef Plan9
12621 return conwrite(&c,1);
12622 #else
12623 return(write(1,&c,1));
12624 #endif /* Plan9 */
12625 }
12626
12627 /* C O N X O -- Write x characters to the console terminal */
12628
12629 int
12630 conxo(x,s) int x; char *s; {
12631
12632 #ifdef IKSD
12633 if (inserver && !local)
12634 return(ttol((CHAR *)s,x));
12635
12636 #ifdef CK_ENCRYPTION
12637 if (inserver && TELOPT_ME(TELOPT_ENCRYPTION))
12638 ck_tn_encrypt(s,x);
12639 #endif /* CK_ENCRYPTION */
12640 #endif /* IKSD */
12641
12642 #ifdef Plan9
12643 return(conwrite(s,x));
12644 #else
12645 return(write(1,s,x));
12646 #endif /* Plan9 */
12647 }
12648
12649 /* C O N O L -- Write a line to the console terminal */
12650
12651 int
12652 conol(s) char *s; {
12653 int len;
12654 if (!s) s = ""; /* Always do this! */
12655 len = strlen(s);
12656 if (len == 0)
12657 return(0);
12658
12659 #ifdef IKSD
12660 if (inserver && !local)
12661 return(ttol((CHAR *)s,len));
12662
12663 #ifdef CK_ENCRYPTION
12664 if (inserver && TELOPT_ME(TELOPT_ENCRYPTION)) {
12665 if (nxpacket < len) {
12666 if (xpacket) {
12667 free(xpacket);
12668 xpacket = NULL;
12669 nxpacket = 0;
12670 }
12671 len = len > 10240 ? len : 10240;
12672 xpacket = (CHAR *)malloc(len);
12673 if (!xpacket) {
12674 fprintf(stderr,"ttol malloc failure\n");
12675 return(-1);
12676 } else
12677 nxpacket = len;
12678 }
12679 memcpy(xpacket,s,len);
12680 s = (char *)xpacket;
12681 ck_tn_encrypt(s,len);
12682 }
12683 #endif /* CK_ENCRYPTION */
12684 #endif /* IKSD */
12685
12686 #ifdef Plan9
12687 return(conwrite(s,len));
12688 #else
12689 return(write(1,s,len));
12690 #endif /* Plan9 */
12691 }
12692
12693 /* C O N O L A -- Write an array of lines to the console terminal */
12694
12695 int
12696 conola(s) char *s[]; {
12697 char * p;
12698 int i, x;
12699
12700
12701 if (!s) return(0);
12702 for (i = 0; ; i++) {
12703 p = s[i];
12704 if (!p) p = ""; /* Let's not dump core shall we? */
12705 if (!*p)
12706 break;
12707 #ifdef IKSD
12708 if (inserver && !local)
12709 x = ttol((CHAR *)p,(int)strlen(p));
12710 else
12711 #endif /* IKSD */
12712 x = conol(p);
12713 if (x < 0)
12714 return(-1);
12715 }
12716 return(0);
12717 }
12718
12719 /* C O N O L L -- Output a string followed by CRLF */
12720
12721 int
12722 conoll(s) char *s; {
12723 CHAR buf[3];
12724 buf[0] = '\r';
12725 buf[1] = '\n';
12726 buf[2] = '\0';
12727 if (!s) s = "";
12728
12729 #ifdef IKSD
12730 if (inserver && !local) {
12731 if (*s) ttol((CHAR *)s,(int)strlen(s));
12732 return(ttol(buf,2));
12733 }
12734 #endif /* IKSD */
12735
12736 if (*s) conol(s);
12737 #ifdef IKSD
12738 #ifdef CK_ENCRYPTION
12739 if (inserver && TELOPT_ME(TELOPT_ENCRYPTION))
12740 ck_tn_encrypt((char *)buf,2);
12741 #endif /* CK_ENCRYPTION */
12742 #endif /* IKSD */
12743
12744 #ifdef Plan9
12745 return(conwrite(buf, 2));
12746 #else
12747 return(write(1,buf,2));
12748 #endif /* Plan9 */
12749 }
12750
12751 /* C O N C H K -- Return how many characters available at console */
12752 /*
12753 We could also use select() here to cover a few more systems that are not
12754 covered by any of the following, e.g. HP-UX 9.0x on the model 800.
12755 */
12756 int
12757 conchk() {
12758 static int contyp = 0; /* +1 for isatty, -1 otherwise */
12759
12760 if (contyp == 0) /* This prevents unnecessary */
12761 contyp = (isatty(0) ? 1 : -1); /* duplicated calls to isatty() */
12762 debug(F101,"conchk contyp","",contyp);
12763 if (backgrd || (contyp < 0))
12764 return(0);
12765
12766 #ifdef aegis
12767 if (conbufn > 0) return(conbufn); /* use old count if nonzero */
12768
12769 /* read in more characters */
12770 conbufn = ios_$get(ios_$stdin,
12771 ios_$cond_opt, conbuf, (long)sizeof(conbuf), st);
12772 if (st.all != status_$ok) conbufn = 0;
12773 conbufp = conbuf;
12774 return(conbufn);
12775 #else
12776 #ifdef IKSD
12777 if (inserver && !local)
12778 return(in_chk(1,ttyfd));
12779 else
12780 #endif /* IKSD */
12781 return(in_chk(0,0));
12782 #endif /* aegis */
12783 }
12784
12785 /* C O N I N C -- Get a character from the console */
12786 /*
12787 Call with timo > 0 to do a timed read, timo == 0 to do an untimed blocking
12788 read. Upon success, returns the character. Upon failure, returns -1.
12789 A timed read that does not complete within the timeout period returns -2.
12790 */
12791 int
12792 coninc(timo) int timo; {
12793 int n = 0; CHAR ch;
12794 int xx;
12795
12796 if (conbufn > 0) { /* If something already buffered */
12797 --conbufn;
12798 return((unsigned)(*conbufp++ & 0xff));
12799 }
12800
12801 errno = 0; /* Clear this */
12802 #ifdef IKSD
12803 if (inserver && !local) {
12804 xx = ttinc(timo);
12805 if (xx < 0)
12806 return(ttinctimo ? -2 : -1);
12807 else
12808 return(xx);
12809 }
12810 #endif /* IKSD */
12811
12812 #ifdef aegis /* Apollo Aegis only... */
12813 debug(F101,"coninc timo","",timo);
12814 fflush(stdout);
12815 if (conchk() > 0) {
12816 --conbufn;
12817 return((unsigned)(*conbufp++ & 0xff));
12818 }
12819 #endif /* aegis */
12820
12821 #ifdef TTLEBUF
12822 if (
12823 #ifdef IKSD
12824 inserver &&
12825 #endif /* IKSD */
12826 !xlocal
12827 ) {
12828 if (ttpush >= 0) {
12829 debug(F111,"ttinc","ttpush",ttpush);
12830 ch = ttpush;
12831 ttpush = -1;
12832 return(ch);
12833 }
12834 if (le_data) {
12835 if (le_getchar(&ch) > 0) {
12836 debug(F111,"ttinc LocalEchoInBuf","ch",ch);
12837 return(ch);
12838 }
12839 }
12840 }
12841 #endif /* TTLEBUF */
12842
12843 if (timo <= 0) { /* Untimed, blocking read. */
12844 while (1) { /* Keep trying till we get one. */
12845 n = read(0, &ch, 1); /* Read a character. */
12846 if (n == 0) continue; /* Shouldn't happen. */
12847 if (n > 0) { /* If read was successful, */
12848 #ifdef IKSD
12849 #ifdef CK_ENCRYPTION
12850 debug(F100,"coninc decrypt 1","",0);
12851 if (inserver && !local && TELOPT_U(TELOPT_ENCRYPTION))
12852 ck_tn_decrypt((char *)&ch,1);
12853 #endif /* CK_ENCRYPTION */
12854 #endif /* IKSD */
12855 return((unsigned)(ch & 0xff)); /* return the character. */
12856 }
12857
12858 /* Come here if read() returned an error. */
12859
12860 debug(F101, "coninc(0) errno","",errno); /* Log the error. */
12861 #ifndef OXOS
12862 #ifdef SVORPOSIX
12863 #ifdef CIE /* CIE Regulus has no EINTR symbol? */
12864 #ifndef EINTR
12865 #define EINTR 4
12866 #endif /* EINTR */
12867 #endif /* CIE */
12868 /*
12869 This routine is used for several different purposes. In CONNECT mode, it is
12870 used to do an untimed, blocking read from the keyboard in the lower CONNECT
12871 fork. During local-mode file transfer, it reads a character from the
12872 console to interrupt the file transfer (like A for a status report, X to
12873 cancel a file, etc). Obviously, we don't want the reads in the latter case
12874 to be blocking, or the file transfer would stop until the user typed
12875 something. Unfortunately, System V does not allow the console device input
12876 buffer to be sampled nondestructively (e.g. by conchk()), so a kludge is
12877 used instead. During local-mode file transfer, the SIGQUIT signal is armed
12878 and trapped by esctrp(), and this routine pretends to have read the quit
12879 character from the keyboard normally. But, kludge or no kludge, the read()
12880 issued by this command, under System V only, can fail if a signal -- ANY
12881 signal -- is caught while the read is pending. This can occur not only when
12882 the user types the quit character, but also during telnet negotiations, when
12883 the lower CONNECT fork signals the upper one about an echoing mode change.
12884 When this happens, we have to post the read() again. This is apparently not
12885 a problem in BSD-based UNIX versions.
12886 */
12887 if (errno == EINTR) /* Read interrupted. */
12888 if (conesc) { /* If by SIGQUIT, */
12889 conesc = 0; /* the conesc variable is set, */
12890 return(escchr); /* so return the escape character. */
12891 } else continue; /* By other signal, try again. */
12892 #else
12893 /*
12894 This might be dangerous, but let's do this on non-System V versions too,
12895 since at least one SunOS 4.1.2 user complains of immediate disconnections
12896 upon first making a TELNET connection.
12897 */
12898 if (errno == EINTR) /* Read interrupted. */
12899 continue;
12900 #endif /* SVORPOSIX */
12901 #else /* OXOS */
12902 if (errno == EINTR) /* Read interrupted. */
12903 continue;
12904 #endif /* OXOS */
12905 return(-1); /* Error */
12906 }
12907 }
12908 #ifdef DEBUG
12909 if (deblog && timo <= 0) {
12910 debug(F100,"coninc timeout logic error","",0);
12911 timo = 1;
12912 }
12913 #endif /* DEBUG */
12914
12915 /* Timed read... */
12916
12917 saval = signal(SIGALRM,timerh); /* Set up timeout handler. */
12918 xx = alarm(timo); /* Set the alarm. */
12919 debug(F101,"coninc alarm set","",timo);
12920 if (
12921 #ifdef CK_POSIX_SIG
12922 sigsetjmp(sjbuf,1)
12923 #else
12924 setjmp(sjbuf)
12925 #endif /* CK_POSIX_SIG */
12926 ) /* The read() timed out. */
12927 n = -2; /* Code for timeout. */
12928 else
12929 n = read(0, &ch, 1);
12930 ttimoff(); /* Turn off timer */
12931 if (n > 0) { /* Got character OK. */
12932 #ifdef IKSD
12933 #ifdef CK_ENCRYPTION
12934 debug(F100,"coninc decrypt 2","",0);
12935 if (inserver && !local && TELOPT_U(TELOPT_ENCRYPTION))
12936 ck_tn_decrypt((char *)&ch,1);
12937 #endif /* CK_ENCRYPTION */
12938 #endif /* IKSD */
12939 return((unsigned)(ch & 0xff)); /* Return it. */
12940 }
12941 /*
12942 read() returned an error. Same deal as above, but without the loop.
12943 */
12944 debug(F101, "coninc(timo) n","",n);
12945 debug(F101, "coninc(timo) errno","",errno);
12946 #ifndef OXOS
12947 #ifdef SVORPOSIX
12948 if (n == -1 && errno == EINTR && conesc != 0) {
12949 conesc = 0;
12950 return(escchr); /* User entered escape character. */
12951 }
12952 #endif /* SVORPOSIX */
12953 if (n == 0 && errno > 0) { /* It's an error */
12954 return(-1);
12955 }
12956 #endif /* ! OXOS */
12957 return(n);
12958 }
12959
12960 /* C O N G K S -- Console Get Keyboard Scancode */
12961
12962 #ifndef congks
12963 /*
12964 This function needs to be filled in with the various system-dependent
12965 system calls used by SUNOS, NeXT OS, Xenix, Aviion, etc, to read a full
12966 keyboard scan code. Unfortunately there aren't any.
12967 */
12968 int
12969 congks(timo) int timo; {
12970
12971 #ifdef IKSD
12972 if (inserver && !local)
12973 return(ttinc(timo));
12974 #endif /* IKSD */
12975
12976 return(coninc(timo));
12977 }
12978 #endif /* congks */
12979
12980 #ifdef ATT7300
12981
12982 /* A T T D I A L -- Dial up the remote system using internal modem
12983 * Purpose: to open and dial a number on the internal modem available on the
12984 * ATT7300 UNIX PC. Written by Joe Doupnik. Superceeds version written by
12985 * Richard E. Hill, Dickinson, TX. which employed dial(3c).
12986 * Uses information in <sys/phone.h> and our status int attmodem.
12987 */
12988 attdial(ttname,speed,telnbr) char *ttname,*telnbr; long speed; {
12989 char *telnum;
12990
12991 attmodem &= ~ISMODEM; /* modem not in use yet */
12992 /* Ensure O_NDELAY is set, else i/o traffic hangs */
12993 /* We turn this flag off once the dial is complete */
12994 fcntl(ttyfd, F_SETFL, fcntl(ttyfd, F_GETFL, 0) | O_NDELAY);
12995
12996 /* Condition line, check availability & DATA mode, turn on speaker */
12997 if (ioctl(ttyfd,PIOCOFFHOOK, &dialer) == -1) {
12998 printf("cannot access phone\n");
12999 ttclos(0);
13000 return (-2);
13001 }
13002 ioctl(ttyfd,PIOCGETP,&dialer); /* get phone dialer parameters */
13003
13004 if (dialer.c_lineparam & VOICE) { /* phone must be in DATA mode */
13005 printf(" Should not dial with modem in VOICE mode.\n");
13006 printf(" Exit Kermit, switch to DATA and retry call.\n");
13007 ttclos(0);
13008 return (-2);
13009 }
13010 #ifdef ATTTONED /* Old way, tone dialing only. */
13011 dialer.c_lineparam = DATA | DTMF; /* Dial with tones, */
13012 dialer.c_lineparam &= ~PULSE; /* not with pulses. */
13013 #else
13014 /* Leave current pulse/tone state alone. */
13015 /* But what about DATA? Add it back if you have trouble. */
13016 /* sys/phone says you get DATA automatically by opening device RDWR */
13017 #endif
13018 dialer.c_waitdialtone = 5; /* wait 5 sec for dialtone */
13019 #ifdef COMMENT
13020 dialer.c_feedback = SPEAKERON|NORMSPK|RINGON; /* control speaker */
13021 #else
13022 /* sys/phone says RINGON used only for incoming voice calls */
13023 dialer.c_feedback &= ~(SOFTSPK|LOUDSPK);
13024 dialer.c_feedback |= SPEAKERON|NORMSPK;
13025 #endif
13026 dialer.c_waitflash = 500; /* 0.5 sec flash hook */
13027 if(ioctl(ttyfd,PIOCSETP,&dialer) == -1) { /* set phone parameters */
13028 printf("Cannot set modem characteristics\n");
13029 ttclos(0);
13030 return (-2);
13031 }
13032 ioctl(ttyfd,PIOCRECONN,0); /* Turns on speaker for pulse */
13033
13034 #ifdef COMMENT
13035 fprintf(stderr,"Phone line status. line_par:%o dialtone_wait:%o \
13036 line_status:%o feedback:%o\n",
13037 dialer.c_lineparam, dialer.c_waitdialtone,
13038 dialer.c_linestatus, dialer.c_feedback);
13039 #endif
13040
13041 attmodem |= ISMODEM; /* modem is now in-use */
13042 sleep(1);
13043 for (telnum = telnbr; *telnum != '\0'; telnum++) /* dial number */
13044 #ifdef ATTTONED
13045 /* Tone dialing only */
13046 if (ioctl(ttyfd,PIOCDIAL,telnum) != 0) {
13047 perror("Error in dialing");
13048 ttclos(0);
13049 return(-2);
13050 }
13051 #else /* Allow Pulse or Tone dialing */
13052 switch (*telnum) {
13053 case 't': case 'T': case '%': /* Tone dialing requested */
13054 dialer.c_lineparam |= DTMF;
13055 dialer.c_lineparam &= ~PULSE;
13056 if (ioctl(ttyfd,PIOCSETP,&dialer) == -1) {
13057 printf("Cannot set modem to tone dialing\n");
13058 ttclos(0);
13059 return(-2);
13060 }
13061 break;
13062 case 'd': case 'D': case 'p': case 'P': case '^':
13063 dialer.c_lineparam |= PULSE;
13064 dialer.c_lineparam &= ~DTMF;
13065 if (ioctl(ttyfd,PIOCSETP,&dialer) == -1) {
13066 printf("Cannot set modem to pulse dialing\n");
13067 ttclos(0);
13068 return(-2);
13069 }
13070 break;
13071 default:
13072 if (ioctl(ttyfd,PIOCDIAL,telnum) != 0) {
13073 perror("Dialing error");
13074 ttclos(0);
13075 return(-2);
13076 }
13077 break;
13078 }
13079 #endif
13080
13081 ioctl(ttyfd,PIOCDIAL,"@"); /* terminator for data call */
13082 do { /* wait for modems to Connect */
13083 if (ioctl(ttyfd,PIOCGETP,&dialer) != 0) { /* get params */
13084 perror("Cannot get modems to connect");
13085 ttclos(0);
13086 return(-2);
13087 }
13088 } while ((dialer.c_linestatus & MODEMCONNECTED) == 0);
13089 /* Turn off O_NDELAY flag now. */
13090 fcntl(ttyfd, F_SETFL, fcntl(ttyfd, F_GETFL, 0) & ~O_NDELAY);
13091 signal(SIGHUP, sighup); /* hangup on loss of carrier */
13092 return(0); /* return success */
13093 }
13094
13095 /*
13096 Offgetty, ongetty functions. These function get the 'getty(1m)' off
13097 and restore it to the indicated line. Shell's return codes are:
13098 0: Can't do it. Probably a user logged on.
13099 1: No need. No getty on that line.
13100 2: Done, you should restore the getty when you're done.
13101 DOGETY System(3), however, returns them as 0, 256, 512, respectively.
13102 Thanks to Kevin O'Gorman, Anarm Software Systems.
13103
13104 getoff.sh looks like: geton.sh looks like:
13105 setgetty $1 0 setgetty $1 1
13106 err=$? exit $?
13107 sleep 2
13108 exit $err
13109 */
13110
13111 /* O F F G E T T Y -- Turn off getty(1m) for the communications tty line
13112 * and get status so it can be restarted after the line is hung up.
13113 */
13114 int
13115 offgetty(ttname) char *ttname; {
13116 char temp[30];
13117 while (*ttname != '\0') ttname++; /* seek terminator of path */
13118 ttname -= 3; /* get last 3 chars of name */
13119 sprintf(temp,"/usr/bin/getoff.sh %s",ttname);
13120 return(zsyscmd(temp));
13121 }
13122
13123 /* O N G E T T Y -- Turn on getty(1m) for the communications tty line */
13124
13125 int
13126 ongetty(ttname) char *ttname; {
13127 char temp[30];
13128 while (*ttname != '\0') ttname++; /* comms tty path name */
13129 ttname -= 3;
13130 sprintf(temp,"/usr/bin/geton.sh %s",ttname);
13131 return(zsyscmd(temp));
13132 }
13133 #endif /* ATT7300 */
13134
13135 /* T T S C A R R -- Set ttcarr variable, controlling carrier handling.
13136 *
13137 * 0 = Off: Always ignore carrier. E.g. you can connect without carrier.
13138 * 1 = On: Heed carrier, except during dialing. Carrier loss gives disconnect.
13139 * 2 = Auto: For "modem direct": The same as "Off".
13140 * For real modem types: Heed carrier during connect, but ignore
13141 * it anytime else. Compatible with pre-5A C-Kermit versions.
13142 *
13143 * As you can see, this setting does not affect dialing, which always ignores
13144 * carrier (unless there is some special exception for some modem type). It
13145 * does affect ttopen() if it is set before ttopen() is used. This setting
13146 * takes effect on the next call to ttopen()/ttpkt()/ttvt(). And they are
13147 * (or should be) always called before any communications is tried, which
13148 * means that, practically speaking, the effect is immediate.
13149 *
13150 * Of course, nothing of this applies to remote mode (xlocal = 0).
13151 *
13152 * Someone has yet to uncover how to manipulate the carrier in the BSD
13153 * environment (or any non-termio using environment). Until that time, this
13154 * will simply be a no-op for BSD.
13155 *
13156 * Note that in previous versions, the carrier was most often left unchanged
13157 * in ttpkt()/ttvt() unless they were called with FLO_DIAL or FLO_DIAX. This
13158 * has changed. Now it is controlled by ttcarr in conjunction with these
13159 * modes.
13160 */
13161 int
13162 ttscarr(carrier) int carrier; {
13163 ttcarr = carrier;
13164 debug(F101, "ttscarr","",ttcarr);
13165 return(ttcarr);
13166 }
13167
13168 /* C A R R C T L -- Set tty modes for carrier treatment.
13169 *
13170 * Sets the appropriate bits in a termio or sgttyb struct for carrier control
13171 * (actually, there are no bits in sgttyb for that), or performs any other
13172 * operations needed to control this on the current system. The function does
13173 * not do the actual TCSETA or stty, since often we want to set other bits too
13174 * first. Don't call this function when xlocal is 0, or the tty is not opened.
13175 *
13176 * We don't know how to do anything like carrier control on non-ATTSV systems,
13177 * except, apparently, ultrix. See above. It is also known that this doesn't
13178 * have much effect on a Xenix system. For Xenix, one should switch back and
13179 * forth between the upper and lower case device files. Maybe later.
13180 * Presently, Xenix will stick to the mode it was opened with.
13181 *
13182 * carrier: 0 = ignore carrier, 1 = require carrier.
13183 * The current state is saved in curcarr, and checked to save labour.
13184 */
13185 #ifdef SVORPOSIX
13186 int
13187 #ifdef BSD44ORPOSIX
13188 carrctl(ttpar, carrier) struct termios *ttpar; int carrier;
13189 #else /* ATTSV */
13190 carrctl(ttpar, carrier) struct termio *ttpar; int carrier;
13191 #endif /* BSD44ORPOSIX */
13192 /* carrctl */ {
13193 debug(F101, "carrctl","",carrier);
13194 if (carrier)
13195 ttpar->c_cflag &= ~CLOCAL;
13196 else
13197 ttpar->c_cflag |= CLOCAL;
13198 return(0);
13199 }
13200 #else /* Berkeley, V7, et al... */
13201 int
13202 carrctl(ttpar, carrier) struct sgttyb *ttpar; int carrier; {
13203 debug(F101, "carrctl","",carrier);
13204 if (carrier == curcarr)
13205 return(0);
13206 curcarr = carrier;
13207 #ifdef ultrix
13208 #ifdef COMMENT
13209 /*
13210 Old code from somebody at DEC that tends to get stuck, time out, etc.
13211 */
13212 if (carrier) {
13213 ioctl(ttyfd, TIOCMODEM, &temp);
13214 ioctl(ttyfd, TIOCHPCL, 0);
13215 } else {
13216 /* (According to the manuals, TIOCNCAR should be preferred */
13217 /* over TIOCNMODEM...) */
13218 ioctl(ttyfd, TIOCNMODEM, &temp);
13219 }
13220 #else
13221 /*
13222 New code from Jamie Watson that, he says, eliminates the problems.
13223 */
13224 if (carrier) {
13225 ioctl(ttyfd, TIOCCAR);
13226 ioctl(ttyfd, TIOCHPCL);
13227 } else {
13228 ioctl(ttyfd, TIOCNCAR);
13229 }
13230 #endif /* COMMENT */
13231 #endif /* ultrix */
13232 return(0);
13233 }
13234 #endif /* SVORPOSIX */
13235
13236
13237 /* T T G M D M -- Get modem signals */
13238 /*
13239 Looks for RS-232 modem signals, and returns those that are on in as its
13240 return value, in a bit mask composed of the BM_xxx values defined in ckcdeb.h.
13241 Returns:
13242 -3 Not implemented
13243 -2 if the communication device does not have modem control (e.g. telnet)
13244 -1 on error.
13245 >= 0 on success, with a bit mask containing the modem signals that are on.
13246 */
13247
13248 /*
13249 Define the symbol K_MDMCTL if we have Sys V R3 / 4.3 BSD style
13250 modem control, namely the TIOCMGET ioctl.
13251 */
13252
13253 #ifdef BSD43
13254 #define K_MDMCTL
13255 #endif /* BSD43 */
13256
13257 #ifdef SUNOS4
13258 #define K_MDMCTL
13259 #endif /* SUNOS4 */
13260
13261 /*
13262 SCO OpenServer R5.0.4. The TIOCMGET definition is hardwired in because it
13263 is skipped in termio.h when _POSIX_SOURCE is defined. But _POSIX_SOURCE
13264 must be defined in order to get the high serial speeds that are new to
13265 5.0.4. However, the regular SCO drivers do not implement TIOCMGET, so the
13266 ioctl() returns -1 with errno 22 (invalid function). But third-party
13267 drivers, e.g. for Digiboard, do implement it, and so it should work on ports
13268 driven by those drivers.
13269 */
13270 #ifdef SCO_OSR504
13271 #ifndef TIOCMGET
13272 #define TIOCMGET (('t'<<8)|29)
13273 #endif /* TIOCMGET */
13274 #endif /* SCO_OSR504 */
13275
13276 #ifdef CK_SCOV5
13277 /* Because POSIX strictness in <sys/termio.h> won't let us see these. */
13278 #ifndef TIOCM_DTR
13279 #define TIOCM_DTR 0x0002 /* data terminal ready */
13280 #define TIOCM_RTS 0x0004 /* request to send */
13281 #define TIOCM_CTS 0x0020 /* clear to send */
13282 #define TIOCM_CAR 0x0040 /* carrier detect */
13283 #define TIOCM_RNG 0x0080 /* ring */
13284 #define TIOCM_DSR 0x0100 /* data set ready */
13285 #define TIOCM_CD TIOCM_CAR
13286 #define TIOCM_RI TIOCM_RNG
13287 #endif /* TIOCM_DTR */
13288 #endif /* CK_SCOV5 */
13289
13290 #ifdef QNX
13291 #define K_MDMCTL
13292 #else
13293 #ifdef TIOCMGET
13294 #define K_MDMCTL
13295 #endif /* TIOCMGET */
13296 #endif /* QNX */
13297 /*
13298 "A serial communication program that can't read modem signals
13299 is like a car without windows."
13300 */
13301 int
13302 ttgmdm() {
13303
13304 #ifdef QNX
13305 #include <sys/qioctl.h>
13306
13307 unsigned long y, mdmbits[2];
13308 int x, z = 0;
13309
13310 if (xlocal && ttyfd < 0)
13311 return(-1);
13312
13313 #ifdef NETCONN
13314 if (netconn) { /* Network connection */
13315 #ifdef TN_COMPORT
13316 if (istncomport()) {
13317 gotsigs = 1;
13318 return(tngmdm());
13319 } else
13320 #endif /* TN_COMPORT */
13321 return(-2); /* No modem signals */
13322 }
13323 #endif /* NETCONN */
13324
13325 #ifdef NETCMD
13326 if (ttpipe) return(-2);
13327 #endif /* NETCMD */
13328 #ifdef NETPTY
13329 if (ttpty) return(-2);
13330 #endif /* NETPTY */
13331
13332 mdmbits[0] = 0L;
13333 mdmbits[1] = 0L;
13334 /*
13335 * From <sys/qioctl.h>:
13336 *
13337 * SERIAL devices (all Dev.ser versions)
13338 * 0 : DTR 8 = Data Bits 0 16 - reserved 24 - reserved
13339 * 1 : RTS 9 = Data Bits 1 17 - reserved 25 - reserved
13340 * 2 = Out 1 10 = Stop Bits 18 - reserved 26 - reserved
13341 * 3 = Int Enable 11 = Par Enable 19 - reserved 27 - reserved
13342 * 4 = Loop 12 = Par Even 20 = CTS 28 - reserved
13343 * 5 - reserved 13 = Par Stick 21 = DSR 29 - reserved
13344 * 6 - reserved 14 : Break 22 = RI 30 - reserved
13345 * 7 - reserved 15 = 0 23 = CD 31 - reserved
13346 */
13347 errno = 0;
13348 x = qnx_ioctl(ttyfd, QCTL_DEV_CTL, &mdmbits[0], 8, &mdmbits[0], 4);
13349 debug(F101,"ttgmdm qnx_ioctl","",x);
13350 debug(F101,"ttgmdm qnx_ioctl errno","",errno);
13351 if (!x) {
13352 debug(F101,"ttgmdm qnx_ioctl mdmbits[0]","",mdmbits[0]);
13353 debug(F101,"ttgmdm qnx_ioctl mdmbits[1]","",mdmbits[1]);
13354 y = mdmbits[0];
13355 if (y & 0x000001L) z |= BM_DTR; /* Bit 0 */
13356 if (y & 0x000002L) z |= BM_RTS; /* Bit 1 */
13357 if (y & 0x100000L) z |= BM_CTS; /* Bit 20 */
13358 if (y & 0x200000L) z |= BM_DSR; /* Bit 21 */
13359 if (y & 0x400000L) z |= BM_RNG; /* Bit 22 */
13360 if (y & 0x800000L) z |= BM_DCD; /* Bit 23 */
13361 debug(F101,"ttgmdm qnx result","",z);
13362 debug(F110,"ttgmdm qnx CD = ",(z & BM_DCD) ? "On" : "Off", 0);
13363 gotsigs = 1;
13364 return(z);
13365 } else return(-1);
13366 #else /* QNX */
13367 #ifdef HPUX /* HPUX has its own way */
13368 int x, z;
13369
13370 #ifdef HPUX10 /* Modem flag word */
13371 mflag y; /* mflag typedef'd in <sys/modem.h> */
13372 #else
13373 #ifdef HPUX9
13374 mflag y;
13375 #else
13376 #ifdef HPUX8
13377 mflag y;
13378 #else
13379 unsigned long y; /* Not sure about pre-8.0... */
13380 #endif /* HPUX8 */
13381 #endif /* HPUX9 */
13382 #endif /* HPUX10 */
13383
13384 if (xlocal && ttyfd < 0)
13385 return(-1);
13386
13387 #ifdef NETCONN
13388 if (netconn) { /* Network connection */
13389 #ifdef TN_COMPORT
13390 if (istncomport()) {
13391 gotsigs = 1;
13392 return(tngmdm());
13393 } else
13394 #endif /* TN_COMPORT */
13395 return(-2); /* No modem signals */
13396 }
13397 #endif /* NETCONN */
13398
13399 #ifdef NETCMD
13400 if (ttpipe) return(-2);
13401 #endif /* NETCMD */
13402 #ifdef NETPTY
13403 if (ttpty) return(-2);
13404 #endif /* NETPTY */
13405
13406 if (xlocal) /* Get modem signals */
13407 x = ioctl(ttyfd,MCGETA,&y);
13408 else
13409 x = ioctl(0,MCGETA,&y);
13410 if (x < 0) return(-1);
13411 debug(F101,"ttgmdm","",y);
13412
13413 z = 0; /* Initialize return value */
13414
13415 /* Now set bits for each modem signal that is reported to be on. */
13416
13417 #ifdef MCTS
13418 /* Clear To Send */
13419 debug(F101,"ttgmdm HPUX CTS","",y & MCTS);
13420 if (y & MCTS) z |= BM_CTS;
13421 #endif
13422 #ifdef MDSR
13423 /* Data Set Ready */
13424 debug(F101,"ttgmdm HPUX DSR","",y & MDSR);
13425 if (y & MDSR) z |= BM_DSR;
13426 #endif
13427 #ifdef MDCD
13428 /* Carrier */
13429 debug(F101,"ttgmdm HPUX DCD","",y & MDCD);
13430 if (y & MDCD) z |= BM_DCD;
13431 #endif
13432 #ifdef MRI
13433 /* Ring Indicate */
13434 debug(F101,"ttgmdm HPUX RI","",y & MRI);
13435 if (y & MRI) z |= BM_RNG;
13436 #endif
13437 #ifdef MDTR
13438 /* Data Terminal Ready */
13439 debug(F101,"ttgmdm HPUX DTR","",y & MDTR);
13440 if (y & MDTR) z |= BM_DTR;
13441 #endif
13442 #ifdef MRTS
13443 /* Request To Send */
13444 debug(F101,"ttgmdm HPUX RTS","",y & MRTS);
13445 if (y & MRTS) z |= BM_RTS;
13446 #endif
13447 gotsigs = 1;
13448 return(z);
13449
13450 #else /* ! HPUX */
13451
13452 #ifdef K_MDMCTL
13453 /*
13454 Note, TIOCMGET might already have been defined in <sys/ioctl.h> or elsewhere.
13455 If not, we try including <sys/ttycom.h> -- if this blows up then more ifdefs
13456 are needed.
13457 */
13458 #ifndef TIOCMGET
13459 #include <sys/ttycom.h>
13460 #endif /* TIOCMGET */
13461
13462 int x, y, z;
13463
13464 debug(F100,"ttgmdm K_MDMCTL defined","",0);
13465
13466 #ifdef NETCONN
13467 if (netconn) { /* Network connection */
13468 #ifdef TN_COMPORT
13469 if (istncomport()) {
13470 gotsigs = 1;
13471 return(tngmdm());
13472 } else
13473 #endif /* TN_COMPORT */
13474 return(-2); /* No modem signals */
13475 }
13476 #endif /* NETCONN */
13477
13478 #ifdef NETCMD
13479 if (ttpipe) return(-2);
13480 #endif /* NETCMD */
13481 #ifdef NETPTY
13482 if (ttpty) return(-2);
13483 #endif /* NETPTY */
13484
13485 if (xlocal && ttyfd < 0)
13486 return(-1);
13487
13488 if (xlocal)
13489 x = ioctl(ttyfd,TIOCMGET,&y); /* Get modem signals. */
13490 else
13491 x = ioctl(0,TIOCMGET,&y);
13492 debug(F101,"ttgmdm TIOCMGET ioctl","",x);
13493 if (x < 0) {
13494 debug(F101,"ttgmdm errno","",errno);
13495 return(-1);
13496 }
13497 debug(F101,"ttgmdm bits","",y);
13498
13499 z = 0; /* Initialize return value. */
13500 #ifdef TIOCM_CTS
13501 /* Clear To Send */
13502 if (y & TIOCM_CTS) z |= BM_CTS;
13503 debug(F101,"ttgmdm TIOCM_CTS defined","",TIOCM_CTS);
13504 #else
13505 debug(F100,"ttgmdm TIOCM_CTS not defined","",0);
13506 #endif
13507 #ifdef TIOCM_DSR
13508 /* Data Set Ready */
13509 if (y & TIOCM_DSR) z |= BM_DSR;
13510 debug(F101,"ttgmdm TIOCM_DSR defined","",TIOCM_DSR);
13511 #else
13512 debug(F100,"ttgmdm TIOCM_DSR not defined","",0);
13513 #endif
13514 #ifdef TIOCM_CAR
13515 /* Carrier */
13516 if (y & TIOCM_CAR) z |= BM_DCD;
13517 debug(F101,"ttgmdm TIOCM_CAR defined","",TIOCM_CAR);
13518 #else
13519 debug(F100,"ttgmdm TIOCM_CAR not defined","",0);
13520 #endif
13521 #ifdef TIOCM_RNG
13522 /* Ring Indicate */
13523 if (y & TIOCM_RNG) z |= BM_RNG;
13524 debug(F101,"ttgmdm TIOCM_RNG defined","",TIOCM_RNG);
13525 #else
13526 debug(F100,"ttgmdm TIOCM_RNG not defined","",0);
13527 #endif
13528 #ifdef TIOCM_DTR
13529 /* Data Terminal Ready */
13530 if (y & TIOCM_DTR) z |= BM_DTR;
13531 debug(F101,"ttgmdm TIOCM_DTR defined","",TIOCM_DTR);
13532 #else
13533 debug(F100,"ttgmdm TIOCM_DTR not defined","",0);
13534 #endif
13535 #ifdef TIOCM_RTS
13536 /* Request To Send */
13537 if (y & TIOCM_RTS) z |= BM_RTS;
13538 debug(F101,"ttgmdm TIOCM_RTS defined","",TIOCM_RTS);
13539 #else
13540 debug(F100,"ttgmdm TIOCM_RTS not defined","",0);
13541 #endif
13542 gotsigs = 1;
13543 return(z);
13544
13545 #else /* !K_MDMCTL catch-All */
13546
13547 debug(F100,"ttgmdm K_MDMCTL not defined","",0);
13548 #ifdef TIOCMGET
13549 debug(F100,"ttgmdm TIOCMGET defined","",0);
13550 #else
13551 debug(F100,"ttgmdm TIOCMGET not defined","",0);
13552 #endif /* TIOCMGET */
13553 #ifdef _SVID3
13554 debug(F100,"ttgmdm _SVID3 defined","",0);
13555 #else
13556 debug(F100,"ttgmdm _SVID3 not defined","",0);
13557 #endif /* _SVID3 */
13558
13559 #ifdef NETCONN
13560 if (netconn) { /* Network connection */
13561 #ifdef TN_COMPORT
13562 if (istncomport()) {
13563 gotsigs = 1;
13564 return(tngmdm());
13565 } else
13566 #endif /* TN_COMPORT */
13567 return(-2); /* No modem signals */
13568 }
13569 #endif /* NETCONN */
13570
13571 #ifdef NETCMD
13572 if (ttpipe) return(-2);
13573 #endif /* NETCMD */
13574 #ifdef NETPTY
13575 if (ttpty) return(-2);
13576 #endif /* NETPTY */
13577
13578 return(-3); /* Sorry, I don't know how... */
13579
13580 #endif /* K_MDMCTL */
13581 #endif /* HPUX */
13582 #endif /* QNX */
13583 }
13584
13585 /* P S U S P E N D -- Put this process in the background. */
13586
13587 /*
13588 Call with flag nonzero if suspending is allowed, zero if not allowed.
13589 Returns 0 on apparent success, -1 on failure (flag was zero, or
13590 kill() returned an error code.
13591 */
13592 int
13593 psuspend(flag) int flag; {
13594
13595 #ifdef RTU
13596 extern int rtu_bug;
13597 #endif /* RTU */
13598
13599 if (flag == 0) return(-1);
13600
13601 #ifdef NOJC
13602 return(-1);
13603 #else
13604 #ifdef SIGTSTP
13605 /*
13606 The big question here is whether job control is *really* supported.
13607 There's no way Kermit can know for sure. The fact that SIGTSTP is
13608 defined does not guarantee the Unix kernel supports it, and the fact
13609 that the Unix kernel supports it doesn't guarantee that the user's
13610 shell (or other process that invoked Kermit) supports it.
13611 */
13612 #ifdef RTU
13613 rtu_bug = 1;
13614 #endif /* RTU */
13615 if (kill(0,SIGSTOP) < 0
13616 #ifdef MIPS
13617 /* Let's try this for MIPS too. */
13618 && kill(getpid(),SIGSTOP) < 0
13619 #endif /* MIPS */
13620 ) { /* If job control, suspend the job */
13621 perror("suspend");
13622 debug(F101,"psuspend error","",errno);
13623 return(-1);
13624 }
13625 debug(F100,"psuspend ok","",0);
13626 return(0);
13627 #else
13628 return(-1);
13629 #endif /* SIGTSTP */
13630 #endif /* NOJC */
13631 }
13632
13633 /*
13634 setuid package, by Kristoffer Eriksson, with contributions from Dean
13635 Long and fdc.
13636 */
13637
13638 /* The following is for SCO when CK_ANSILIBS is defined... */
13639 #ifdef M_UNIX
13640 #ifdef CK_ANSILIBS
13641 #ifndef NOGETID_PROTOS
13642 #define NOGETID_PROTOS
13643 #endif /* NOGETID_PROTOS */
13644 #endif /* CK_ANSILIBS */
13645 #endif /* M_UNIX */
13646
13647 #ifndef _POSIX_SOURCE
13648 #ifndef SUNOS4
13649 #ifndef NEXT
13650 #ifndef PS2AIX10
13651 #ifndef sequent
13652 #ifndef HPUX9
13653 #ifndef HPUX10
13654 #ifndef COHERENT
13655 #ifndef NOGETID_PROTOS
13656 _PROTOTYP( UID_T getuid, (void) );
13657 _PROTOTYP( UID_T geteuid, (void) );
13658 _PROTOTYP( UID_T getreuid, (void) );
13659 _PROTOTYP( UID_T getgid, (void) );
13660 _PROTOTYP( UID_T getegid, (void) );
13661 _PROTOTYP( UID_T getregid, (void) );
13662 #endif /* NOGETID_PROTOS */
13663 #else
13664 _PROTOTYP( UID_T getreuid, (void) );
13665 _PROTOTYP( UID_T getregid, (void) );
13666 #endif /* COHERENT */
13667 #endif /* HPUX10 */
13668 #endif /* HPUX9 */
13669 #endif /* sequent */
13670 #endif /* PS2AIX10 */
13671 #endif /* NEXT */
13672 #endif /* SUNOS4 */
13673 #endif /* _POSIX_SOURCE */
13674
13675 /*
13676 Subject: Set-user-id
13677 To: fdc@watsun.cc.columbia.edu (Frank da Cruz)
13678 Date: Sat, 21 Apr 90 4:48:25 MES
13679 From: Kristoffer Eriksson <ske@pkmab.se>
13680
13681 This is a set of functions to be used in programs that may be run set-user-id
13682 and/or set-group-id. They handle both the case where the program is not run
13683 with such privileges (nothing special happens then), and the case where one
13684 or both of these set-id modes are used. The program is made to run with the
13685 user's real user and group ids most of the time, except for when more
13686 privileges are needed. Don't set-user-id to "root".
13687
13688 This works on System V and POSIX. In BSD, it depends on the
13689 "saved-set-user-id" feature.
13690 */
13691
13692 #define UID_ROOT 0 /* Root user and group ids */
13693 #define GID_ROOT 0
13694
13695 /*
13696 The following code defines the symbol SETEUID for UNIX systems based
13697 on BSD4.4 (either -Encumbered or -Lite). This program will then use
13698 seteuid() and setegid() instead of setuid() and setgid(), which still
13699 don't allow arbitrary switching. It also avoids setreuid() and
13700 setregid(), which are included in BSD4.4 for compatibility only, are
13701 insecure, and print warnings to stderr under at least one system (NetBSD
13702 1.0). Note that POSIX systems should still use setuid() and setgid();
13703 the seteuid() and setegid() functions are BSD4.4 extensions to the
13704 POSIX model. Mike Long <mike.long@analog.com>, 8/94.
13705 */
13706 #ifdef BSD44
13707 #define SETEUID
13708 #endif /* BSD44 */
13709
13710 /*
13711 The following construction automatically defines the symbol SETREUID for
13712 UNIX versions based on Berkeley Unix 4.2 and 4.3. If this symbol is
13713 defined, then this program will use getreuid() and getregid() calls in
13714 preference to getuid() and getgid(), which in Berkeley-based Unixes do
13715 not allow arbitrary switching back and forth of real & effective uid.
13716 This construction also allows -DSETREUID to be put on the cc command line
13717 for any system that has and wants to use setre[ug]id(). It also prevents
13718 automatic definition of SETREUID if -DNOSETREU is included on the cc
13719 command line (or otherwise defined).
13720 */
13721 #ifdef FT18 /* None of this for Fortune. */
13722 #define NOSETREU
13723 #endif /* FT18 */
13724
13725 #ifdef ANYBSD
13726 #ifndef BSD29
13727 #ifndef BSD41
13728 #ifndef SETREUID
13729 #ifndef NOSETREU
13730 #ifndef SETEUID
13731 #define SETREUID
13732 #endif /* SETEUID */
13733 #endif /* NOSETREU */
13734 #endif /* SETREUID */
13735 #endif /* !BSD41 */
13736 #endif /* !BSD29 */
13737 #endif /* ANYBSD */
13738
13739 /* Variables for user and group IDs. */
13740
13741 static UID_T realuid = (UID_T) -1, privuid = (UID_T) -1;
13742 static GID_T realgid = (GID_T) -1, privgid = (GID_T) -1;
13743
13744
13745 /* P R I V _ I N I -- Initialize privileges package */
13746
13747 /* Called as early as possible in a set-uid or set-gid program to store the
13748 * set-to uid and/or gid and step down to the users real uid and gid. The
13749 * stored id's can be temporarily restored (allowed in System V) during
13750 * operations that require the privilege. Most of the time, the program
13751 * should execute in unpriviliged state, to not impose any security threat.
13752 *
13753 * Note: Don't forget that access() always uses the real id:s to determine
13754 * file access, even with privileges restored.
13755 *
13756 * Returns an error mask, with error values or:ed together:
13757 * 1 if setuid() fails,
13758 * 2 if setgid() fails, and
13759 * 4 if the program is set-user-id to "root", which can't be handled.
13760 *
13761 * Only the return value 0 indicates real success. In case of failure,
13762 * those privileges that could be reduced have been, at least, but the
13763 * program should be aborted none-the-less.
13764 *
13765 * Also note that these functions do not expect the uid or gid to change
13766 * without their knowing. It may work if it is only done temporarily, but
13767 * you're on your own.
13768 */
13769 int
13770 priv_ini() {
13771 int err = 0;
13772
13773 #ifndef HAVE_LOCKDEV
13774
13775 /* Save real ID:s. */
13776 realuid = getuid();
13777 realgid = getgid();
13778
13779 /* Save current effective ID:s, those set to at program exec. */
13780 privuid = geteuid();
13781 privgid = getegid();
13782
13783 /* If running set-uid, go down to real uid, otherwise remember that
13784 * no privileged uid is available.
13785 *
13786 * Exceptions:
13787 *
13788 * 1) If the real uid is already "root" and the set-uid uid (the
13789 * initial effective uid) is not "root", then we would have trouble
13790 * if we went "down" to "root" here, and then temporarily back to the
13791 * set-uid uid (not "root") and then again tried to become "root". I
13792 * think the "saved set-uid" is lost when changing uid from effective
13793 * uid "root", which changes all uid, not only the effective uid. But
13794 * in this situation, we can simply go to "root" and stay there all
13795 * the time. That should give sufficient privilege (understatement!),
13796 * and give the right uids for subprocesses.
13797 *
13798 * 2) If the set-uid (the initial effective uid) is "root", and we
13799 * change uid to the real uid, we can't change it back to "root" when
13800 * we need the privilege, for the same reason as in 1). Thus, we can't
13801 * handle programs that are set-user-id to "root" at all. The program
13802 * should be stopped. Use some other uid. "root" is probably too
13803 * privileged for such things, anyway. (The uid is reverted to the
13804 * real uid until termination.)
13805 *
13806 * These two exceptions have the effect that the "root" uid will never
13807 * be one of the two uids that are being switched between, which also
13808 * means we don't have to check for such cases in the switching
13809 * functions.
13810 *
13811 * Note that exception 1) is handled by these routines (by constantly
13812 * running with uid "root", while exception 2) is a serious error, and
13813 * is not provided for at all in the switching functions.
13814 */
13815 if (realuid == privuid)
13816 privuid = (UID_T) -1; /* Not running set-user-id. */
13817
13818 /* If running set-gid, go down to real gid, otherwise remember that
13819 * no privileged gid is available.
13820 *
13821 * There are no exception like there is for the user id, since there
13822 * is no group id that is privileged in the manner of uid "root".
13823 * There could be equivalent problems for group changing if the
13824 * program sometimes ran with uid "root" and sometimes not, but
13825 * that is already avoided as explained above.
13826 *
13827 * Thus we can expect always to be able to switch to the "saved set-
13828 * gid" when we want, and back to the real gid again. You may also
13829 * draw the conclusion that set-gid provides for fewer hassles than
13830 * set-uid.
13831 */
13832
13833 #ifdef SUIDDEBUG
13834 fprintf(stderr,"UID_ROOT=%d\n",UID_ROOT);
13835 fprintf(stderr,"realuid=%d\n",realuid);
13836 fprintf(stderr,"privuid=%d\n",privuid);
13837 #endif /* SUIDDEBUG */
13838
13839 if (realgid == privgid) /* If not running set-user-id, */
13840 privgid = (GID_T) -1; /* remember it this way. */
13841
13842 err = priv_off(); /* Turn off setuid privilege. */
13843
13844 if (privuid == UID_ROOT) /* If setuid to root, */
13845 err |= 4; /* return this error. */
13846
13847 if (realuid == UID_ROOT) { /* If real id is root, */
13848 privuid = (UID_T) -1; /* stay root at all times. */
13849 #ifdef ATT7300
13850 /* If Kermit installed SUID uucp and user is running as root */
13851 err &= ~1; /* System V R0 does not save UID */
13852 #endif /* ATT7300 */
13853 }
13854 #endif /* HAVE_LOCKDEV */
13855 return(err);
13856 }
13857
13858
13859 /* Macros for hiding the differences in UID/GID setting between various Unix
13860 * systems. These macros should always be called with both the privileged ID
13861 * and the non-privileged ID. The one in the second argument, will become the
13862 * effective ID. The one in the first argument will be retained for later
13863 * retrieval.
13864 */
13865 #ifdef SETREUID
13866 #ifdef SAVEDUID
13867 /* On BSD systems with the saved-UID feature, we just juggle the effective
13868 * UID back and forth, and leave the real UID at its true value. The kernel
13869 * allows switching to both the current real UID, the effective UID, and the
13870 * UID which the program is set-UID to. The saved set-UID always holds the
13871 * privileged UID for us, and the real UID will always be the non-privileged,
13872 * and we can freely choose one of them for the effective UID at any time.
13873 */
13874 #define switchuid(hidden,active) setreuid( (UID_T) -1, active)
13875 #define switchgid(hidden,active) setregid( (GID_T) -1, active)
13876
13877 #else /* SETREUID,!SAVEDUID */
13878
13879 /* On systems with setreXid() but without the saved-UID feature, notably
13880 * BSD 4.2, we swap the real and effective UIDs each time. It's
13881 * the effective UID that we are interested in, but we have to retain the
13882 * unused UID somewhere to enable us to restore it later, and we do this
13883 * in the real UID. The kernel only allows switching to either the current
13884 * real or the effective UID, unless you're "root".
13885 */
13886 #define switchuid(hidden,active) setreuid(hidden,active)
13887 #define switchgid(hidden,active) setregid(hidden,active)
13888 #endif
13889
13890 #else /* !SETREUID, !SAVEDUID */
13891
13892 #ifdef SETEUID
13893 /*
13894 BSD 4.4 works similarly to System V and POSIX (see below), but uses
13895 seteXid() instead of setXid() to change effective IDs. In addition, the
13896 seteXid() functions work the same for "root" as for other users.
13897 */
13898 #define switchuid(hidden,active) seteuid(active)
13899 #define switchgid(hidden,active) setegid(active)
13900
13901 #else /* !SETEUID */
13902
13903 /* On System V and POSIX, the only thing we can change is the effective UID
13904 * (unless the current effective UID is "root", but initsuid() avoids that for
13905 * us). The kernel allows switching to the current real UID or to the saved
13906 * set-UID. These are always set to the non-privileged UID and the privileged
13907 * UID, respectively, and we only change the effective UID. This breaks if
13908 * the current effective UID is "root", though, because for "root" setuid/gid
13909 * becomes more powerful, which is why initsuid() treats "root" specially.
13910 * Note: That special treatment maybe could be ignored for BSD? Note: For
13911 * systems that don't fit any of these four cases, we simply can't support
13912 * set-UID.
13913 */
13914
13915 #define switchuid(hidden,active) setuid(active)
13916 #define switchgid(hidden,active) setgid(active)
13917
13918 #endif /* SETEUID */
13919 #endif /* SETREUID */
13920
13921 /* P R I V _ O N -- Turn on the setuid and/or setgid */
13922
13923 /* Go to the privileged uid (gid) that the program is set-user-id
13924 * (set-group-id) to, unless the program is running unprivileged.
13925 * If setuid() fails, return value will be 1. If getuid() fails it
13926 * will be 2. Return immediately after first failure, and the function
13927 * tries to restore any partial work done. Returns 0 on success.
13928 * Group id is changed first, since it is less serious than user id.
13929 */
13930 int
13931 priv_on() {
13932 #ifndef HAVE_LOCKDEV
13933 if (privgid != (GID_T) -1)
13934 if (switchgid(realgid,privgid))
13935 return(2);
13936
13937 if (privuid != (UID_T) -1)
13938 if (switchuid(realuid,privuid)) {
13939 if (privgid != (GID_T) -1)
13940 if (switchgid(privgid,realgid))
13941 return(2);
13942 return(1);
13943 }
13944 #endif /* HAVE_LOCKDEV */
13945 return(0);
13946 }
13947
13948 /* P R I V _ O F F -- Turn on the real uid and gid */
13949
13950 /* Return to the unprivileged uid (gid) after an temporary visit to
13951 * privileged status, unless the program is running without set-user-id
13952 * (set-group-id). Returns 1 for failure in setuid() and 2 for failure
13953 * in setgid() or:ed together. The functions tries to return both uid
13954 * and gid to unprivileged state, regardless of errors. Returns 0 on
13955 * success.
13956 */
13957 int
13958 priv_off() {
13959 int err = 0;
13960 #ifndef HAVE_LOCKDEV
13961 if (privuid != (UID_T) -1)
13962 if (switchuid(privuid,realuid))
13963 err |= 1;
13964
13965 if (privgid != (GID_T) -1)
13966 if (switchgid(privgid,realgid))
13967 err |= 2;
13968 #endif /* HAVE_LOCKDEV */
13969 return(err);
13970 }
13971
13972 /* Turn off privilege permanently. No going back. This is necessary before
13973 * a fork() on BSD43 machines that don't save the setUID or setGID, because
13974 * we swap the real and effective ids, and we don't want to let the forked
13975 * process swap them again and get the privilege back. It will work on other
13976 * machines too, such that you can rely on its effect always being the same,
13977 * for instance, even when you're in priv_on() state when this is called.
13978 * (Well, that part about "permanent" is on System V only true if you follow
13979 * this with a call to exec(), but that's what we want it for anyway.)
13980 * Added by Dean Long -- dlong@midgard.ucsc.edu
13981 */
13982 int
13983 priv_can() {
13984 #ifndef HAVE_LOCKDEV
13985 #ifdef SETREUID
13986 int err = 0;
13987 if (privuid != (UID_T) -1)
13988 if (setreuid(realuid,realuid))
13989 err |= 1;
13990
13991 if (privgid != (GID_T) -1)
13992 if (setregid(realgid,realgid))
13993 err |= 2;
13994
13995 return(err);
13996
13997 #else
13998 #ifdef SETEUID
13999 int err = 0;
14000 if (privuid != (UID_T) -1)
14001 if (setuid(realuid)) {
14002 debug(F101,"setuid failed","",errno);
14003 err |= 1;
14004 debug(F101,"ruid","",getuid());
14005 debug(F101,"euid","",geteuid());
14006 }
14007 debug(F101,"setuid","",realuid);
14008 if (privgid != (GID_T) -1)
14009 if (setgid(realgid)) {
14010 debug(F101,"setgid failed","",errno);
14011 err |= 2;
14012 debug(F101,"rgid","",getgid());
14013 debug(F101,"egid","",getegid());
14014 }
14015 debug(F101,"setgid","",realgid);
14016 return(err);
14017 #else
14018 /* Easy way of using setuid()/setgid() instead of setreuid()/setregid().*/
14019 return(priv_off());
14020 #endif /* SETEUID */
14021 #endif /* SETREUID */
14022 #else
14023 return(0);
14024 #endif /* HAVE_LOCKDEV */
14025 }
14026
14027 /* P R I V _ O P N -- For opening protected files or devices. */
14028
14029 int
14030 priv_opn(name, modes) char *name; int modes; {
14031 int x;
14032 priv_on(); /* Turn privileges on */
14033 debug(F111,"priv_opn",name,modes);
14034 errno = 0;
14035 x = open(name, modes); /* Try to open the device */
14036 debug(F101,"priv_opn result","",x);
14037 debug(F101,"priv_opn errno","",errno);
14038 priv_off(); /* Turn privileges off */
14039 return(x); /* Return open's return code */
14040 }
14041
14042 /* P R I V _ C H K -- Check privileges. */
14043
14044 /* Try to turn them off. If turning them off did not succeed, cancel them */
14045
14046 int
14047 priv_chk() {
14048 int x, y = 0;
14049 x = priv_off(); /* Turn off privs. */
14050 if (x != 0 || getuid() == privuid || geteuid() == privuid)
14051 y = priv_can();
14052 if (x != 0 || getgid() == privgid || getegid() == privgid)
14053 y = y | priv_can();
14054 return(y);
14055 }
14056
14057 UID_T
14058 real_uid() {
14059 return(realuid);
14060 }
14061
14062 VOID
14063 ttimoff() { /* Turn off any timer interrupts */
14064 /* int xx; */
14065 /*
14066 As of 5A(183), we set SIGALRM to SIG_IGN (to ignore alarms) rather than to
14067 SIG_DFL (to catch alarms, or if there is no handler, to exit). This is to
14068 cure (mask, really) a deeper problem with stray alarms that occurs on some
14069 systems, possibly having to do with sleep(), that caused core dumps. It
14070 should be OK to do this, because no code in this module uses nested alarms.
14071 (But we still have to watch out for SCRIPT and DIAL...)
14072 */
14073 /* xx = */ alarm(0);
14074 /* debug(F101,"ttimoff alarm","",xx); */
14075 if (saval) { /* Restore any previous */
14076 signal(SIGALRM,saval); /* alarm handler. */
14077 /* debug(F101,"ttimoff alarm restoring saval","",saval); */
14078 saval = NULL;
14079 } else {
14080 signal(SIGALRM,SIG_IGN); /* Used to be SIG_DFL */
14081 /* debug(F100,"ttimoff alarm SIG_IGN","",0); */
14082 }
14083 }
14084
14085
14086 int
14087 tt_is_secure() { /* Tells whether the current connection is secure */
14088
14089 if (ttyfd == -1)
14090 return(0);
14091
14092 if (0
14093 #ifdef SSHBUILTIN
14094 || IS_SSH()
14095 #endif /* SSHBUILTIN */
14096 #ifdef CK_ENCRYPTION
14097 || ck_tn_encrypting() && ck_tn_decrypting()
14098 #endif /* CK_ENCRYPTION */
14099 #ifdef CK_SSL
14100 || tls_active_flag || ssl_active_flag
14101 #endif /* CK_SSL */
14102 #ifdef RLOGCODE
14103 #ifdef CK_KERBEROS
14104 #ifdef CK_ENCRYPTION
14105 || ttnproto == NP_EK4LOGIN || ttnproto == NP_EK5LOGIN
14106 #endif /* CK_ENCRYPTION */
14107 #endif /* CK_KERBEROS */
14108 #endif /* RLOGCODE */
14109 )
14110 return(1);
14111 return(0);
14112 }
14113
14114 #ifdef CK_REDIR
14115
14116 /* External protocol handler parameters from ckuus3.c */
14117 extern int exp_handler, exp_stderr, exp_timo;
14118
14119 #ifdef SELECT
14120 #ifdef NETPTY
14121
14122 /* The right size is 24576 */
14123
14124 #ifndef PTY_PBUF_SIZE /* Size of buffer to read from pty */
14125 #define PTY_PBUF_SIZE 24576 /* and write to net. */
14126 #endif /* PTY_PBUF_SIZE */
14127
14128 #ifndef PTY_TBUF_SIZE /* Size of buffer to read from net */
14129 #define PTY_TBUF_SIZE 24576 /* and write to pty. */
14130 #endif /* PTY_TBUF_SIZE */
14131
14132 #ifdef O_NDELAY /* Whether to use nonblocking */
14133 #ifndef PTY_NO_NDELAY /* reads on the pseudoterminal */
14134 #ifndef PTY_USE_NDELAY
14135 #define PTY_USE_NDELAY
14136 #endif /* PTY_USE_NDELAY */
14137 #endif /* PTY_NO_NDELAY */
14138 #endif /* O_NDELAY */
14139
14140 #ifndef HAVE_OPENPTY
14141 #ifndef USE_CKUPTY_C
14142 #define USE_CKUPTY_C
14143 #endif /* USE_CKUPTY_C */
14144 #endif /* HAVE_OPENPTY */
14145
14146 VOID
14147 pty_make_raw(fd) int fd; {
14148 int x = -23, i;
14149
14150 #ifdef BSD44ORPOSIX /* POSIX */
14151 struct termios tp;
14152 #else
14153 #ifdef ATTSV /* AT&T UNIX */
14154 #ifdef CK_ANSIC
14155 struct termio tp = {0};
14156 #else
14157 struct termio tp;
14158 #endif /* CK_ANSIC */
14159 #else
14160 struct sgttyb tp; /* Traditional */
14161 #endif /* ATTSV */
14162 #endif /* BSD44ORPOSIX */
14163
14164 debug(F101,"pty_make_raw fd","",fd);
14165 errno = 0;
14166
14167 #ifdef BSD44ORPOSIX /* POSIX */
14168 x = tcgetattr(fd,&tp);
14169 debug(F101,"pty_make_raw tcgetattr","",x);
14170 #else
14171 #ifdef ATTSV /* AT&T UNIX */
14172 x = ioctl(fd,TCGETA,&tp);
14173 debug(F101,"pty_make_raw TCGETA ioctl","",x);
14174 #else
14175 x = gtty(fd,&tp);
14176 debug(F101,"pty_make_raw ttty","",x);
14177 #endif /* ATTSV */
14178 #endif /* BSD44ORPOSIX */
14179 debug(F101,"pty_make_raw GET errno","",errno);
14180
14181 #ifdef USE_CFMAKERAW
14182 errno = 0;
14183 cfmakeraw(&tp);
14184 debug(F101,"pty_make_raw cfmakeraw errno","",errno);
14185 #else /* USE_CFMAKERAW */
14186
14187 #ifdef COMMENT
14188
14189 /* This very simple version recommended by Serg Iakolev doesn't work */
14190
14191 tp.c_lflag &= ~(ECHO|ICANON|IEXTEN|ISIG);
14192 tp.c_iflag &= ~(BRKINT|ICRNL|INPCK|ISTRIP|IXON);
14193 tp.c_cflag &= ~(CSIZE|PARENB);
14194 tp.c_cflag |= CS8;
14195 tp.c_oflag &= ~(OPOST);
14196 tp.c_cc[VMIN] = 1;
14197 tp.c_cc[VTIME] = 0;
14198
14199 debug(F101,"pty_make_raw 1 c_cc[] NCCS","",NCCS);
14200 debug(F101,"pty_make_raw 1 iflags","",tp.c_iflag);
14201 debug(F101,"pty_make_raw 1 oflags","",tp.c_oflag);
14202 debug(F101,"pty_make_raw 1 lflags","",tp.c_lflag);
14203 debug(F101,"pty_make_raw 1 cflags","",tp.c_cflag);
14204
14205 #else
14206 #ifdef COMMENT
14207 /*
14208 In this version we unset everything and then set only the
14209 bits we know we need.
14210 */
14211 /* iflags */
14212 tp.c_iflag = 0L;
14213 tp.c_iflag |= IGNBRK;
14214 #ifdef IMAXBEL
14215 tp.c_iflag |= IMAXBEL;
14216 #endif /* IMAXBEL */
14217
14218 /* oflags */
14219 tp.c_oflag = 0L;
14220
14221 /* lflags */
14222 tp.c_lflag = 0L;
14223 #ifdef NOKERNINFO
14224 tp.c_lflag |= NOKERNINFO;
14225 #endif /* NOKERNINFO */
14226
14227 /* cflags */
14228 tp.c_cflag = 0L;
14229 tp.c_cflag |= CS8|CREAD;
14230
14231 for (i = 0; i < NCCS; i++) { /* No special characters */
14232 tp.c_cc[i] = 0;
14233 }
14234 #ifdef VMIN
14235 tp.c_cc[VMIN] = 1; /* But always wait for input */
14236 #endif /* VMIN */
14237 debug(F101,"pty_make_raw 2 c_cc[] NCCS","",NCCS);
14238 debug(F101,"pty_make_raw 2 iflags","",tp.c_iflag);
14239 debug(F101,"pty_make_raw 2 oflags","",tp.c_oflag);
14240 debug(F101,"pty_make_raw 2 lflags","",tp.c_lflag);
14241 debug(F101,"pty_make_raw 2 cflags","",tp.c_cflag);
14242
14243 #else /* COMMENT */
14244 /*
14245 In this version we set or unset every single flag explicitly. It works a
14246 bit better than the simple version just above, but it's still far from
14247 adequate.
14248 */
14249 /* iflags */
14250 tp.c_iflag &= ~(PARMRK|ISTRIP|BRKINT|INLCR|IGNCR|ICRNL);
14251 tp.c_iflag &= ~(INPCK|IGNPAR|IXANY|IXON|IXOFF);
14252 tp.c_iflag |= IGNBRK;
14253 #ifdef IMAXBEL
14254 #ifdef COMMENT
14255 tp.c_iflag |= IMAXBEL;
14256 #else
14257 tp.c_iflag &= ~IMAXBEL;
14258 #endif /* COMMENT */
14259 #endif /* IMAXBEL */
14260 #ifdef IUCLC
14261 tp.c_iflag &= ~IUCLC;
14262 #endif /* IUCLC */
14263
14264 /* oflags */
14265 #ifdef BSDLY
14266 tp.c_oflag &= ~BSDLY;
14267 #endif /* BSDLY */
14268 #ifdef CRDLY
14269 tp.c_oflag &= ~CRDLY;
14270 #endif /* CRDLY */
14271 #ifdef FFDLY
14272 tp.c_oflag &= ~FFDLY;
14273 #endif /* FFDLY */
14274 #ifdef NLDLY
14275 tp.c_oflag &= ~NLDLY;
14276 #endif /* NLDLY */
14277 #ifdef TABDLY
14278 tp.c_oflag &= ~TABDLY;
14279 #endif /* TABDLY */
14280 #ifdef VTDLY
14281 tp.c_oflag &= ~VTDLY;
14282 #endif /* VTDLY */
14283 #ifdef OFDEL
14284 tp.c_oflag &= ~OFDEL;
14285 #endif /* OFDEL */
14286 #ifdef OFILL
14287 tp.c_oflag &= ~OFILL;
14288 #endif /* OFILL */
14289 #ifdef OLCUC
14290 tp.c_oflag &= ~OLCUC;
14291 #endif /* OLCUC */
14292 #ifdef CMSPAR
14293 tp.c_oflag &= ~CMSPAR;
14294 #endif /* CMSPAR */
14295 tp.c_oflag &= ~OPOST;
14296 #ifdef OXTABS
14297 tp.c_oflag &= ~OXTABS;
14298 #endif /* OXTABS */
14299 #ifdef COMMENT
14300 #ifdef ONOCR
14301 tp.c_oflag &= ~ONOCR; /* Maybe should be |=? */
14302 tp.c_oflag |= ONOCR; /* makes no difference either way */
14303 #endif /* ONOCR */
14304 #endif /* COMMENT */
14305 #ifdef ONOEOT
14306 tp.c_oflag &= ~ONOEOT;
14307 #endif /* ONOEOT */
14308 #ifdef ONLRET
14309 tp.c_oflag &= ~ONLRET;
14310 #endif /* ONLRET */
14311 #ifdef ONLCR
14312 tp.c_oflag &= ~ONLCR;
14313 #endif /* ONLCR */
14314 #ifdef OCRNL
14315 tp.c_oflag &= ~OCRNL;
14316 #endif /* OCRNL */
14317
14318 /* lflags */
14319 tp.c_lflag &= ~ECHO;
14320 #ifdef ECHOE
14321 tp.c_lflag &= ~ECHOE;
14322 #endif /* ECHOE */
14323 #ifdef ECHONL
14324 tp.c_lflag &= ~ECHONL;
14325 #endif /* ECHONL */
14326 #ifdef ECHOPRT
14327 tp.c_lflag &= ~ECHOPRT;
14328 #endif /* ECHOPRT */
14329 #ifdef ECHOKE
14330 tp.c_lflag &= ~ECHOKE;
14331 #endif /* ECHOKE */
14332 #ifdef ECHOCTL
14333 tp.c_lflag &= ~ECHOCTL;
14334 #endif /* ECHOCTL */
14335 #ifdef XCASE
14336 tp.c_lflag &= ~XCASE;
14337 #endif /* XCASE */
14338 #ifdef ALTWERASE
14339 tp.c_lflag &= ~ALTWERASE;
14340 #endif /* ALTWERASE */
14341 #ifdef EXTPROC
14342 tp.c_lflag &= ~(ICANON|ISIG|IEXTEN|TOSTOP|FLUSHO|PENDIN|EXTPROC);
14343 #else
14344 tp.c_lflag &= ~(ICANON|ISIG|IEXTEN|TOSTOP|FLUSHO|PENDIN);
14345 #endif /* EXTPROC */
14346 #ifdef NOKERNINFO
14347 tp.c_lflag |= NOKERNINFO;
14348 #endif /* NOKERNINFO */
14349 #ifndef COMMENT
14350 tp.c_lflag &= ~NOFLSH; /* TRY IT THE OTHER WAY? */
14351 #else
14352 tp.c_lflag |= NOFLSH; /* No, this way is worse */
14353 #endif /* COMMENT */
14354
14355 /* cflags */
14356 tp.c_cflag &= ~(CSIZE|PARENB|PARODD);
14357 tp.c_cflag |= CS8|CREAD;
14358
14359 #ifdef MDMBUF
14360 tp.c_cflag &= ~(MDMBUF);
14361 #else
14362 #ifdef CCAR_OFLOW
14363 tp.c_cflag &= ~(CCAR_OFLOW); /* two names for the same thing */
14364 #endif /* CCAR_OFLOW */
14365 #endif /* MDMBUF */
14366
14367 #ifdef CCTS_OFLOW
14368 tp.c_cflag &= ~(CCTS_OFLOW);
14369 #endif /* CCTS_OFLOW */
14370 #ifdef CDSR_OFLOW
14371 tp.c_cflag &= ~(CDSR_OFLOW);
14372 #endif /* CDSR_OFLOW */
14373 #ifdef CDTR_IFLOW
14374 tp.c_cflag &= ~(CDTR_IFLOW);
14375 #endif /* CDTR_IFLOW */
14376 #ifdef CRTS_IFLOW
14377 tp.c_cflag &= ~(CRTS_IFLOW);
14378 #endif /* CRTS_IFLOW */
14379 #ifdef CRTSXOFF
14380 tp.c_cflag &= ~(CRTSXOFF);
14381 #endif /* CRTSXOFF */
14382 #ifdef CRTSCTS
14383 tp.c_cflag &= ~(CRTSCTS);
14384 #endif /* CRTSCTS */
14385 #ifdef CLOCAL
14386 tp.c_cflag &= ~(CLOCAL);
14387 #endif /* CLOCAL */
14388 #ifdef CSTOPB
14389 tp.c_cflag &= ~(CSTOPB);
14390 #endif /* CSTOPB */
14391 #ifdef HUPCL
14392 tp.c_cflag &= ~(HUPCL);
14393 #endif /* HUPCL */
14394
14395 for (i = 0; i < NCCS; i++) { /* No special characters */
14396 tp.c_cc[i] = 0;
14397 }
14398 #ifdef VMIN
14399 tp.c_cc[VMIN] = 1; /* But always wait for input */
14400 #endif /* VMIN */
14401 debug(F101,"pty_make_raw 3 c_cc[] NCCS","",NCCS);
14402 debug(F101,"pty_make_raw 3 iflags","",tp.c_iflag);
14403 debug(F101,"pty_make_raw 3 oflags","",tp.c_oflag);
14404 debug(F101,"pty_make_raw 3 lflags","",tp.c_lflag);
14405 debug(F101,"pty_make_raw 3 cflags","",tp.c_cflag);
14406 #endif /* COMMENT */
14407 #endif /* COMMENT */
14408
14409 errno = 0;
14410 #ifdef BSD44ORPOSIX /* POSIX */
14411 x = tcsetattr(fd,TCSANOW,&tp);
14412 debug(F101,"pty_make_raw tcsetattr","",x);
14413 #else
14414 #ifdef ATTSV /* AT&T UNIX */
14415 x = ioctl(fd,TCSETA,&tp);
14416 debug(F101,"pty_make_raw ioctl","",x);
14417 #else
14418 x = stty(fd,&tp); /* Traditional */
14419 debug(F101,"pty_make_raw stty","",x);
14420 #endif /* ATTSV */
14421 #endif /* BSD44ORPOSIX */
14422 debug(F101,"pty_make_raw errno","",errno);
14423
14424 #endif /* __NetBSD__ */
14425 }
14426
14427 static int
14428 pty_chk(fd) int fd; {
14429 int x, n = 0;
14430 errno = 0;
14431 #ifdef FIONREAD
14432 x = ioctl(fd, FIONREAD, &n); /* BSD and most others */
14433 ckmakmsg(msgbuf,500,
14434 "pty_chk ioctl FIONREAD errno=",
14435 ckitoa(errno),
14436 " count=",
14437 ckitoa(n));
14438 debug(F100,msgbuf,"",0);
14439 #else
14440 #ifdef RDCHK
14441 n = rdchk(fd);
14442 debug(F101,"pty_chk rdchk","",n);
14443 #else
14444 n = 1;
14445 #endif /* RDCHK */
14446 #endif /* FIONREAD */
14447 return((n > -1) ? n : 0);
14448 }
14449
14450 static int
14451 pty_get_status(fd,pid) int fd; PID_T pid; {
14452 int x, status = -1;
14453 PID_T w;
14454
14455 debug(F101,"pty_get_status fd","",fd);
14456 debug(F101,"pty_get_status pid","",pid);
14457
14458 if (pexitstat > -1)
14459 return(pexitstat);
14460
14461 #ifdef COMMENT
14462 /* Not only unnecessary but harmful */
14463 errno = 0;
14464 x = kill(pty_fork_pid,0);
14465 debug(F101,"pty_get_status kill value","",x);
14466 debug(F101,"pty_get_status kill errno","",errno);
14467 if (x > -1 && errno != ESRCH)
14468 return(-1); /* Fork still there */
14469 /* Fork seems to be gone */
14470 #endif /* COMMENT */
14471
14472 errno = 0;
14473 x = waitpid(pty_fork_pid,&status,WNOHANG);
14474 debug(F111,"pty_get_status waitpid",ckitoa(errno),x);
14475 if (x <= 0 && errno == 0) {
14476 debug(F101,"pty_get_status waitpid return","",-1);
14477 return(-1);
14478 }
14479 if (x > 0) {
14480 if (x != pty_fork_pid)
14481 debug(F101,
14482 "pty_get_status waitpid pid doesn't match","",pty_fork_pid);
14483 debug(F101,"pty_get_status waitpid status","",status);
14484 debug(F101,"pty_get_status waitpid errno","",errno);
14485 if (WIFEXITED(status)) {
14486 debug(F100,"pty_get_status WIFEXITED","",0);
14487 status = WEXITSTATUS(status);
14488 debug(F101,"pty_get_status fork exit status","",status);
14489 #ifdef COMMENT
14490 end_pty();
14491 #endif /* COMMENT */
14492 close(fd);
14493 pexitstat = status;
14494 } else {
14495 debug(F100,"pty_get_status waitpid unexpected status","",0);
14496 }
14497 }
14498 debug(F101,"pty_get_status return status","",status);
14499 return(status);
14500 }
14501
14502 /* t t p t y c m d -- Run command on pty and forward to net */
14503
14504 /*
14505 Needed for running external protocols on secure connections.
14506 For example, if C-Kermit has made an SSL/TLS or Kerberos Telnet
14507 connection, and then needs to transfer a file with Zmodem, which is
14508 an external program, this routine reads Zmodem's output, encrypts it,
14509 and then forwards it out the connection, and reads the encrypted data
14510 stream coming in from the connection, decrypts it, and forwards it to
14511 Zmodem.
14512
14513 Works like a TCP/IP port forwarder except one end is a pty rather
14514 than a socket, which introduces some complications:
14515
14516 . On most platforms, select() always indicates the output side of
14517 the pty has characters waiting to be read, even when it doesn't,
14518 even when the pty process has already exited.
14519
14520 . Nonblocking reads must be used on the pty, because there is no
14521 way on certain platforms (e.g. NetBSD) to find out how many characters
14522 are available to be read (the FIONREAD ioctl always says 0). The code
14523 also allows for blocking reads (if O_NDELAY and O_NONBLOCK are not
14524 defined, or if PTY_NO_NDELAY is defined), but on some platforms this can
14525 result in single-byte reads and writes (NetBSD again).
14526
14527 . Testing for "EOF" on the pty is problematic. select() never gives
14528 any indication. After the pty process has exited and the fork has
14529 disappeared, read() can still return with 0 bytes read but without an
14530 error (NetBSD); no known test on the pty file descriptor will indicate
14531 that it is no longer valid. The process ID of the pty fork can be
14532 tested on some platforms (NetBSD, luckily) but not others (Solaris,
14533 Linux).
14534
14535 On the network side, we use ttinc() and ttoc(), which, for network
14536 connections, handle any active security methods.
14537
14538 Call with s = command.
14539 Returns 0 on failure, 1 on success.
14540 fdc - December 2006 - August 2007.
14541
14542 NOTE: This code defaults to nonblocking reads if O_NDELAY or O_NONBLOCK are
14543 defined in the header files, which should be true of every recent Unix
14544 platform. If this causes trouble somewhere, define PTY_NO_NDELAY, e.g. when
14545 building C-Kermit:
14546
14547 touch ckutio.c
14548 make platformname KFLAGS=-DPTY_NO_NODELAY
14549 */
14550 static int have_pty = 0; /* Do we have a pty? */
14551
14552 static SIGTYP (*save_sigchld)() = NULL; /* For catching SIGCHLD */
14553
14554 static VOID
14555 sigchld_handler(sig) int sig; {
14556 have_pty = 0; /* We don't have a pty */
14557 #ifdef DEBUG
14558 if (save_sigchld) {
14559 (VOID) signal(SIGCHLD,save_sigchld);
14560 save_sigchld = NULL;
14561 }
14562 if (deblog) {
14563 debug(F100,"**************","",0);
14564 debug(F100,"SIGCHLD caught","",0);
14565 debug(F100,"**************","",0);
14566 }
14567 #endif /* DEBUG */
14568 }
14569 #define HAVE_IAC 1
14570 #define HAVE_CR 2
14571
14572 int
14573 ttptycmd(s) char *s; {
14574 CHAR tbuf[PTY_TBUF_SIZE]; /* Read from net, write to pty */
14575 int tbuf_avail = 0; /* Pointers for tbuf */
14576 int tbuf_written = 0;
14577 static int in_state = 0; /* For TELNET IAC and NVT in */
14578 static int out_prev = 0; /* Simpler scheme for out */
14579
14580 CHAR pbuf[PTY_PBUF_SIZE]; /* Read from pty, write to net */
14581 CHAR dbuf[PTY_PBUF_SIZE + PTY_PBUF_SIZE + 1]; /* Double-size buffer */
14582 int pbuf_avail = 0; /* Pointers for pbuf */
14583 int pbuf_written = 0;
14584
14585 int ptyfd = -1; /* Pty file descriptor */
14586 int have_net = 0; /* We have a network connection */
14587 int pty_err = 0; /* Got error on pty */
14588 int net_err = 0; /* Got error on net */
14589 int status = -1; /* Pty process exit status */
14590 int rc = 0; /* Our return code */
14591
14592 int x1 = 0, x2 = 0; /* Workers... */
14593 int c, n, m, t, x; /* Workers */
14594
14595 long seconds_to_wait = 0L; /* select() timeout */
14596 struct timeval tv, *tv2; /* For select() */
14597 #ifdef INTSELECT
14598 int in, out, err; /* For select() */
14599 #else
14600 fd_set in, out, err;
14601 #endif /* INTSELECT */
14602 int nfds = 0; /* For select() */
14603
14604 int pset = 0, tset = 0, pnotset = 0, tnotset = 0; /* stats/debuggin only */
14605 int read_net_bytes = 0; /* Stats */
14606 int write_net_bytes = 0; /* Stats */
14607 int read_pty_bytes = 0; /* Stats */
14608 int write_pty_bytes = 0; /* Stats */
14609 int is_tn = 0; /* TELNET protocol is active */
14610
14611 int masterfd = -1;
14612 int slavefd = -1;
14613 #ifndef USE_CKUPTY_C
14614 struct termios term;
14615 struct winsize twin;
14616 struct stringarray * q;
14617 char ** args = NULL;
14618 #endif /* USE_CKUPTY_C */
14619
14620 in_state = 0; /* No previous character yet */
14621
14622 if (ttyfd == -1) {
14623 printf("?Sorry, communication channel is not open\n");
14624 return(0);
14625 } else {
14626 have_net = 1;
14627 }
14628 if (nopush) {
14629 debug(F100,"ttptycmd fail: nopush","",0);
14630 return(0);
14631 }
14632 if (!s) s = ""; /* Defense de bogus arguments */
14633 if (!*s) return(0);
14634 pexitstat = -1; /* Fork process exit status */
14635
14636 #ifdef TNCODE
14637 is_tn = (xlocal && netconn && IS_TELNET()) || /* Telnet protocol active */
14638 (!xlocal && sstelnet);
14639 #endif /* TNCODE */
14640
14641 debug(F110,"ttptycmd command",s,0);
14642 debug(F101,"ttptycmd ttyfd","",ttyfd);
14643 debug(F101,"ttptycmd is_tn","",is_tn);
14644 debug(F101,"ttptycmd ckermit pid","",getpid());
14645
14646 #ifdef USE_CKUPTY_C
14647 /* Call ckupty.c module to get and set up the pty fork */
14648 /* fc 1 == "run an external protocol" */
14649 debug(F100,"ttptycmd using ckupty.c","",0);
14650 if (do_pty(&ptyfd,s,1) < 0) { /* Start the command on a pty */
14651 debug(F100,"ttptycmd do_pty fails","",0);
14652 return(0);
14653 }
14654 masterfd = ptyfd;
14655 pty_master_fd = ptyfd;
14656 #ifdef COMMENT
14657 slavefd = pty_slave_fd; /* This is not visible to us */
14658 #endif /* COMMENT */
14659 debug(F111,"ttptycmd ptyfd","USE_CKUPTY_C",ptyfd);
14660 debug(F111,"ttptycmd masterfd","USE_CKUPTY_C",masterfd);
14661 debug(F111,"ttptycmd fork pid","USE_CKUPTY_C",pty_fork_pid);
14662 #ifndef SOLARIS
14663 /* "ioctl inappropriate on device" for pty master */
14664 pty_make_raw(masterfd);
14665 #endif /* SOLARIS */
14666
14667 #else /* USE_CKUPTY_C */
14668
14669 debug(F100,"ttptycmd OPENPTY","",0);
14670 if (tcgetattr(0, &term) == -1) { /* Get controlling terminal's modes */
14671 perror("tcgetattr");
14672 return(0);
14673 }
14674 if (ioctl(0, TIOCGWINSZ, (char *) &twin) == -1) { /* and window size */
14675 perror("ioctl TIOCGWINSZ");
14676 return(0);
14677 }
14678 if (openpty(&masterfd, &slavefd, NULL, NULL, NULL) == -1) {
14679 debug(F101,"ttptycmd openpty failed errno","",errno);
14680 perror("opentpy");
14681 return(0);
14682 }
14683 debug(F101,"ttptycmd openpty masterfd","",masterfd);
14684 debug(F101,"ttptycmd openpty slavefd","",slavefd);
14685 pty_master_fd = masterfd;
14686 pty_slave_fd = slavefd;
14687 debug(F101,"ttptycmd openpty pty_master_fd","",pty_master_fd);
14688
14689 /* Put pty master in raw mode but let forked app control the slave */
14690 pty_make_raw(masterfd);
14691
14692 #ifdef COMMENT
14693 #ifdef TIOCREMOTE
14694 /* TIOCREMOTE,0 = disable all termio processing */
14695 x = ioctl(masterfd, TIOCREMOTE, 1);
14696 debug(F111,"ttptycmd ioctl TIOCREMOTE",ckitoa(x),errno);
14697 #endif /* TIOCREMOTE */
14698 #ifdef TIOCTTY
14699 /* TIOCTTY,0 = disable all termio processing */
14700 x = ioctl(masterfd, TIOCTTY, 0);
14701 debug(F111,"ttptycmd ioctl TIOCTTY",ckitoa(x),errno);
14702 #endif /* TIOCTTY */
14703 #endif /* COMMENT */
14704
14705 have_pty = 1; /* We have an open pty */
14706 save_sigchld = signal(SIGCHLD, sigchld_handler); /* Catch fork quit */
14707
14708 pty_fork_pid = fork(); /* Make fork for external protocol */
14709 debug(F101,"ttptycmd pty_fork_pid","",pty_fork_pid);
14710 if (pty_fork_pid == -1) {
14711 perror("fork");
14712 return(0);
14713 } else if (pty_fork_pid == 0) { /* In new fork */
14714 int x;
14715 debug(F101,"ttptycmd new fork pid","",getpid());
14716 close(masterfd); /* Slave quarters no masters allowed */
14717 x = setsid();
14718 debug(F101,"ttptycmd new fork setsid","",x);
14719 if (x == -1) {
14720 perror("ttptycmd setsid");
14721 exit(1);
14722 }
14723 signal(SIGINT,SIG_IGN); /* Let upper fork catch this */
14724
14725 #ifdef COMMENT
14726 #ifdef TIOCSCTTY
14727 /* Make pty the controlling terminal for the process */
14728 /* THIS CAUSES AN INFINITE SIGWINCH INTERRUPT LOOP */
14729 x = ioctl(slavefd, TIOCSCTTY, NULL);
14730 debug(F101,"ttptycmd TIOCSCTTY","",x);
14731 #endif /* TIOCSCTTY */
14732 #endif /* COMMENT */
14733
14734 /* Initialize slave pty modes and size to those of our terminal */
14735 if (tcsetattr(slavefd, TCSANOW, &term) == -1) {
14736 perror("ttptycmd tcsetattr");
14737 exit(1);
14738 }
14739 if (ioctl(slavefd, TIOCSWINSZ, &twin) == -1) {
14740 perror("ttptycmd ioctl");
14741 exit(1);
14742 }
14743 #ifdef COMMENT
14744 #ifdef TIOCNOTTY
14745 /* Disassociate this process from its terminal */
14746 /* THIS HAS NO EFFECT */
14747 x = ioctl(slavefd, TIOCNOTTY, NULL);
14748 debug(F101,"ttptycmd TIOCNOTTY","",x);
14749 #endif /* TIOCNOTTY */
14750 #endif /* COMMENT */
14751
14752 #ifdef COMMENT
14753 #ifdef SIGTTOU
14754 /* Ignore terminal output interrupts */
14755 /* THIS HAS NO EFFECT */
14756 debug(F100,"ttptycmd ignoring SIGTTOU","",0);
14757 signal(SIGTTOU, SIG_IGN);
14758 #endif /* SIGTTOU */
14759 #ifdef SIGTSTP
14760 /* Ignore terminal output interrupts */
14761 /* THIS HAS NO EFFECT */
14762 debug(F100,"ttptycmd ignoring SIGTSTP","",0);
14763 signal(SIGTSTP, SIG_IGN);
14764 #endif /* SIGTSTP */
14765 #endif /* COMMENT */
14766
14767 pty_make_raw(slavefd); /* Put it in rawmode */
14768
14769 errno = 0;
14770 if (dup2(slavefd, STDIN_FILENO) != STDIN_FILENO ||
14771 dup2(slavefd, STDOUT_FILENO) != STDOUT_FILENO) {
14772 debug(F101,"ttptycmd new fork dup2 error","",errno);
14773 perror("ttptycmd dup2");
14774 exit(1);
14775 }
14776 debug(F100,"ttptycmd new fork dup2 ok","",0);
14777
14778 /* Parse external protocol command line */
14779 q = cksplit(1,0,s,NULL,"\\%[]&$+-/=*^_@!{}/<>|.#~'`:;?",7,0,0,0);
14780 if (!q) {
14781 debug(F100,"ttptycmd cksplit failed","",0);
14782 exit(1);
14783 } else {
14784 int i, n;
14785 debug(F100,"ttptycmd cksplit ok","",0);
14786 n = q->a_size;
14787 args = q->a_head + 1;
14788 for (i = 0; i <= n; i++) {
14789 if (!args[i]) {
14790 break;
14791 } else {
14792 /* sometimes cksplit() doesn't terminate the list */
14793 if ((i == n) && args[i]) {
14794 if ((int)strlen(args[i]) == 0)
14795 makestr(&(args[i]),NULL);
14796 }
14797 }
14798 }
14799 }
14800 #ifdef COMMENT
14801 /*
14802 Putting the slave pty in rawmode should not be necessary because the
14803 external protocol program is supposed to do that itself. Yet doing this
14804 here cuts down on Zmodem binary-file transmission errors by 30-50% but
14805 still doesn't eliminate them.
14806 */
14807 pty_make_raw(STDIN_FILENO);
14808 pty_make_raw(STDOUT_FILENO);
14809 #endif /* COMMENT */
14810
14811 debug(F100,"ttptycmd execvp'ing external protocol","",0);
14812 execvp(args[0],args);
14813 perror("execvp failed");
14814 debug(F101,"ttptycmd execvp failed","",errno);
14815 close(slavefd);
14816 exit(1);
14817 }
14818 /* (there are better ways to do this...) */
14819 msleep(1000); /* Make parent wait for child to be ready */
14820 ptyfd = masterfd; /* We talk to the master */
14821
14822 #endif /* USE_CKUPTY_C */
14823
14824 debug(F101,"ttptycmd ptyfd","",ptyfd);
14825 if (ptyfd < 0) {
14826 printf("?Failure to get pty\n");
14827 return(-9);
14828 }
14829 have_pty = 1; /* We have an open pty or we wouldn't he here */
14830
14831 debug(F101,"ttptycmd PTY_PBUF_SIZE","",PTY_PBUF_SIZE);
14832 debug(F101,"ttptycmd PTY_TBUF_SIZE","",PTY_TBUF_SIZE);
14833
14834 #ifdef PTY_USE_NDELAY
14835 /*
14836 NOTE: If select() and ioctl(ptyfd,FIONREAD,&n) return true indications
14837 on the pty, we don't need nonblocking reads. Performance of either
14838 method seems to be about the same, so use whatever works.
14839 */
14840 errno = 0;
14841 x = fcntl(ptyfd,F_SETFL,fcntl(ptyfd,F_GETFL, 0)|O_NDELAY);
14842 ckmakmsg(msgbuf,500,
14843 "ttptycmd set O_NDELAY errno=",
14844 ckitoa(errno),
14845 " fcntl=",
14846 ckitoa(x));
14847 debug(F100,msgbuf,"",0);
14848 #endif /* PTY_USE_NDELAY */
14849
14850 #ifdef COMMENT
14851 /* Not necessary, the protocol module already did this */
14852
14853 #ifdef USE_CFMAKERAW
14854 if (tcgetattr(ttyfd, &term) > -1) {
14855 cfmakeraw(&term);
14856 debug(F101,"ttptycmd net cfmakeraw errno","",errno);
14857 x tcsetattr(ttyfd, TCSANOW, &term);
14858 debug(F101,"ttptycmd net tcsetattr","",x);
14859 debug(F101,"ttptycmd net tcsetattr","",errno);
14860 }
14861 #else
14862 if (local) /* Put network connection in */
14863 ttpkt(ttspeed,ttflow,ttprty); /* "packet mode". */
14864 else
14865 conbin((char)escchr); /* OR... pty_make_raw(0) */
14866 #endif /* USE_CFMAKERAW */
14867 #endif /* COMMENT */
14868
14869 #ifdef TNCODE
14870 if (is_tn) {
14871 debug(F101,"<<< ttptycmd TELOPT_ME_BINARY","",TELOPT_ME(TELOPT_BINARY));
14872 debug(F101,"<<< ttptycmd TELOPT_U_BINARY","",TELOPT_U(TELOPT_BINARY));
14873 }
14874 #endif /* TNCODE */
14875
14876 debug(F101,"ttptycmd entering loop - seconds_to_wait","",seconds_to_wait);
14877
14878 while (have_pty || have_net) {
14879 FD_ZERO(&in); /* Initialize select() structs */
14880 FD_ZERO(&out);
14881 FD_ZERO(&err); /* (not used because useless) */
14882 nfds = -1;
14883
14884 debug(F101,"ttptycmd loop top have_pty","",have_pty);
14885 debug(F101,"ttptycmd loop top have_net","",have_net);
14886
14887 /* Pty is open and we have room to read from it? */
14888 if (have_pty && pbuf_avail < PTY_PBUF_SIZE) {
14889 debug(F100,"ttptycmd FD_SET ptyfd in","",0);
14890 FD_SET(ptyfd, &in);
14891 nfds = ptyfd;
14892 }
14893 /* Network is open and we have room to read from it? */
14894 if (have_net && have_pty && tbuf_avail < PTY_TBUF_SIZE) {
14895 debug(F100,"ttptycmd FD_SET ttyfd in","",0);
14896 FD_SET(ttyfd, &in);
14897 if (ttyfd > nfds) nfds = ttyfd;
14898 }
14899 /* Pty is open and we have stuff to write to it? */
14900 if (have_pty && tbuf_avail - tbuf_written > 0) {
14901 debug(F100,"ttptycmd FD_SET ptyfd out","",0);
14902 FD_SET (ptyfd, &out);
14903 if (ptyfd > nfds) nfds = ptyfd;
14904 }
14905 /* Net is open and we have stuff to write to it? */
14906 debug(F101,"ttptycmd pbuf_avail-pbuf_written","",
14907 pbuf_avail - pbuf_written);
14908 if (have_net && pbuf_avail - pbuf_written > 0) {
14909 debug(F100,"ttptycmd FD_SET ttyfd out","",0);
14910 FD_SET (ttyfd, &out);
14911 if (ttyfd > nfds) nfds = ttyfd;
14912 }
14913 /* We don't use err because it's not really for errors, */
14914 /* but for out of band data on the TCP socket, which, if it is */
14915 /* to be handled at all, is handled in the tt*() routines */
14916
14917 nfds++; /* 0-based to 1-based */
14918 debug(F101,"ttptycmd nfds","",nfds);
14919 if (!nfds) {
14920 debug(F100,"ttptycmd NO FDs set for select","",0);
14921 if (have_pty) {
14922 /* This is not right -- sleeping won't accomplish anything */
14923 debug(F101,"ttptycmd msleep","",100);
14924 msleep(100);
14925 } else {
14926 debug(F100,"ttptycmd no pty - quitting loop","",0);
14927 break;
14928 }
14929 }
14930 errno = 0;
14931
14932 if (seconds_to_wait > 0L) { /* Timeout in case nothing happens */
14933 tv.tv_sec = seconds_to_wait; /* for a long time */
14934 tv.tv_usec = 0L;
14935 tv2 = &tv;
14936 } else {
14937 tv2 = NULL;
14938 }
14939 x = select(nfds, &in, &out, NULL, tv2);
14940 debug(F101,"ttptycmd select","",x);
14941 if (x < 0) {
14942 if (errno == EINTR)
14943 continue;
14944 debug(F101,"ttptycmd select error","",errno);
14945 break;
14946 }
14947 if (x == 0) {
14948 debug(F101,"ttptycmd +++ select timeout","",seconds_to_wait);
14949 if (have_pty) {
14950 status = pty_get_status(ptyfd,pty_fork_pid);
14951 debug(F101,"ttptycmd pty_get_status A","",status);
14952 if (status > -1) pexitstat = status;
14953 have_pty = 0;
14954 }
14955 break;
14956 }
14957 /* We want to handle any pending writes first to make room */
14958 /* for new incoming. */
14959
14960 if (FD_ISSET(ttyfd, &out)) { /* Can write to net? */
14961 CHAR * s;
14962 s = pbuf + pbuf_written; /* Current spot for sending */
14963 #ifdef TNCODE
14964 if (is_tn) { /* ttol() doesn't double IACs */
14965 CHAR c; /* Rewrite string with IACs doubled */
14966 int i;
14967 s = pbuf + pbuf_written; /* Source */
14968 x = 0; /* Count */
14969 for (i = 0; i < pbuf_avail - pbuf_written; i++) {
14970 c = s[i]; /* Next character */
14971 if (c == IAC) { /* If it's IAC */
14972 dbuf[x++] = c; /* put another one */
14973 debug(F000,">>> QUOTED IAC","",c);
14974 } else if (c != 0x0a && out_prev == 0x0d) { /* Bare CR */
14975 if (!TELOPT_ME(TELOPT_BINARY)) { /* NVT rule */
14976 c = 0x00;
14977 dbuf[x++] = c;
14978 debug(F000,">>> CR-NUL","",c);
14979 }
14980 }
14981 dbuf[x++] = c; /* Copy and count it */
14982 debug(F000,">>> char",ckitoa(in_state),c);
14983 out_prev = c;
14984 }
14985 s = dbuf; /* New source */
14986 } else
14987 #endif /* TNCODE */
14988 x = pbuf_avail - pbuf_written; /* How much to send */
14989
14990 debug(F101,"ttptycmd bytes to send","",x);
14991 x = ttol(s, x);
14992 debug(F101,">>> ttol","",x);
14993 if (x < 0) {
14994 net_err++;
14995 debug(F111,"ttptycmd ttol error",ckitoa(x),errno);
14996 x = 0;
14997 }
14998 write_net_bytes += x;
14999 pbuf_written += x;
15000 }
15001 if (FD_ISSET(ptyfd, &out)) { /* Can write to pty? */
15002 debug(F100,"ttptycmd FD_ISSET ptyfd out","",0);
15003 errno = 0;
15004 #ifndef COMMENT
15005 x = write(ptyfd,tbuf + tbuf_written,tbuf_avail - tbuf_written);
15006 #else
15007 /* Byte loop to rule out data overruns in the pty */
15008 /* (it makes no difference) */
15009 {
15010 char *p = tbuf+tbuf_written;
15011 int n = tbuf_avail - tbuf_written;
15012 for (x = 0; x < n; x++) {
15013 msleep(10);
15014 if (write(ptyfd,&(p[x]),1) < 0)
15015 break;
15016 }
15017 }
15018 #endif /* COMMENT */
15019 debug(F111,"ttptycmd ptyfd write",ckitoa(errno),x);
15020 if (x > 0) {
15021 tbuf_written += x;
15022 write_pty_bytes += x;
15023 } else {
15024 x = 0;
15025 pty_err++;
15026 if (pexitstat < 0) {
15027 status = pty_get_status(ptyfd,pty_fork_pid);
15028 debug(F101,"ttptycmd pty_get_status B","",status);
15029 if (status > -1) pexitstat = status;
15030 have_pty = 0;
15031 }
15032 debug(F100,"ttptycmd +++ ptyfd write error","",0);
15033 }
15034 }
15035 if (FD_ISSET(ttyfd, &in)) { /* Can read from net? */
15036 tset++;
15037 debug(F100,"ttptycmd FD_ISSET ttyfd in","",0);
15038 n = in_chk(1,ttyfd);
15039 debug(F101,"ttptycmd in_chk(ttyfd)","",n);
15040 if (n < 0 || ttyfd == -1) {
15041 debug(F101,"ttptycmd +++ ttyfd errno","",errno);
15042 net_err++;
15043 } else if (n > 0) {
15044 if (n > PTY_TBUF_SIZE - tbuf_avail)
15045 n = PTY_TBUF_SIZE - tbuf_avail;
15046 debug(F101,"ttptycmd net read size adjusted","",n);
15047 if (xlocal && netconn) {
15048 /*
15049 We have to use a byte loop here because ttxin()
15050 does not decrypt or, for that matter, handle Telnet.
15051 */
15052 int c;
15053 CHAR * p;
15054 p = tbuf + tbuf_avail;
15055 for (x = 0; x < n; x++) {
15056 if ((c = ttinc(0)) < 0)
15057 break;
15058 if (!is_tn) { /* Not Telnet - keep all bytes */
15059 *p++ = (CHAR)c;
15060 debug(F000,"<<< char","",c);
15061 #ifdef TNCODE
15062 } else { /* Telnet - must handle IAC and NVT */
15063 debug(F000,"<<< char",ckitoa(in_state),c);
15064 switch (c) {
15065 case 0x00: /* NUL */
15066 if (in_state == HAVE_CR) {
15067 debug(F000,"<<< SKIP","",c);
15068 } else {
15069 *p++ = c;
15070 debug(F000,"<<< Keep","",c);
15071 }
15072 in_state = 0;
15073 break;
15074 case 0x0d: /* CR */
15075 if (!TELOPT_U(TELOPT_BINARY))
15076 in_state = HAVE_CR;
15077 *p++ = c;
15078 debug(F000,"<<< Keep","",c);
15079 break;
15080 #ifdef COMMENT
15081 case 0x0f: /* Ctrl-O */
15082 case 0x16: /* Ctrl-V */
15083 *p++ = 0x16;
15084 *p++ = c;
15085 debug(F000,"<<< QUOT","",c);
15086 break;
15087 #endif /* COMMENT */
15088 case 0xff: /* IAC */
15089 if (in_state == HAVE_IAC) {
15090 debug(F000,"<<< KEEP","",c);
15091 *p++ = c;
15092 in_state = 0;
15093 } else {
15094 debug(F000,"<<< SKIP","",c);
15095 in_state = HAVE_IAC;
15096 }
15097 break;
15098 default: /* All others */
15099 if (in_state == HAVE_IAC) {
15100 #ifdef COMMENT
15101 /*
15102 tn_doop() will consume an unknown number of bytes and we'll overshoot
15103 the for-loop. The only Telnet command I've ever seen arrive here is
15104 a Data Mark, which comes when the remote protocol exits and the remote
15105 job returns to its shell prompt. On the assumption it's a 1-byte command,
15106 we don't write out the IAC or the command, and we clear the state. If
15107 we called tn_doop() we'd have no way of knowing how many bytes it took
15108 from the input stream.
15109 */
15110 int xx;
15111 xx = tn_doop((CHAR)c,duplex,ttinc);
15112 debug(F111,"<<< DOOP",ckctoa(c),xx);
15113 #else
15114 debug(F101,"<<< DOOP","",c);
15115 #endif /* COMMENT */
15116 in_state = 0;
15117 } else {
15118 *p++ = c;
15119 debug(F000,"<<< keep","",c);
15120 in_state = 0;
15121 }
15122 }
15123 #endif /* TNCODE */
15124 }
15125 }
15126 ckmakmsg(msgbuf,500,
15127 "ttptycmd read net [ttinc loop] errno=",
15128 ckitoa(errno),
15129 " count=",
15130 ckitoa(x));
15131 debug(F100,msgbuf,"",0);
15132 } else {
15133 x = ttxin(n,tbuf+tbuf_avail);
15134 debug(F101,"ttptycmd ttxin x","",x);
15135 }
15136
15137 if (x < 0) {
15138 debug(F101,"ttptycmd read net error","",x);
15139 net_err++;
15140 }
15141 tbuf_avail += x;
15142 read_net_bytes += x;
15143 }
15144
15145 } else
15146 tnotset++;
15147
15148 if (FD_ISSET(ptyfd, &in)) { /* Read from pty? */
15149 pset++;
15150 debug(F100,"ttptycmd FD_ISSET ptyfd in","",0);
15151 #ifdef PTY_USE_NDELAY
15152 n = PTY_PBUF_SIZE;
15153 #else
15154 /*
15155 This does not work on nonblocking channels
15156 on certain platforms such as NetBSD.
15157 */
15158 n = pty_chk(ptyfd);
15159 #endif /* PTY_USE_NDELAY */
15160 debug(F101,"ttptycmd pty_chk() n","",n);
15161
15162 if (n < 0)
15163 n = 0;
15164 if (n > 0) {
15165 if (n > PTY_PBUF_SIZE - pbuf_avail)
15166 n = PTY_PBUF_SIZE - pbuf_avail;
15167 debug(F101,"ttptycmd pty read size adjusted","",n);
15168 errno = 0;
15169 x = read(ptyfd,pbuf+pbuf_avail,n);
15170 #ifdef DEBUG
15171 if (deblog) {
15172 ckmakmsg(msgbuf,500,
15173 "ttptycmd read pty errno=",
15174 ckitoa(errno),
15175 " count=",
15176 ckitoa(x));
15177 debug(F100,msgbuf,"",0);
15178 }
15179 #endif /* DEBUG */
15180
15181 if (x < 0 && errno == EAGAIN)
15182 x = 0;
15183
15184 if (x < 0) { /* This works on Solaris and Linux */
15185 pty_err++; /* but not NetBSD */
15186 debug(F100,"TERMINATION TEST A","",0);
15187 #ifdef COMMENT
15188 if (errno == EIO)
15189 rc = 1;
15190 #endif /* COMMENT */
15191 if (pexitstat < 0) {
15192 status = pty_get_status(ptyfd,pty_fork_pid);
15193 debug(F101,"ttptycmd pty_get_status C","",status);
15194 if (status > -1) pexitstat = status;
15195 }
15196 have_pty = 0;
15197 x = 0;
15198 }
15199 if (x == 0 && !pty_err) { /* This works on NetBSD but */
15200 debug(F100,"TERMINATION TEST B","",0);
15201 status = pexitstat > -1 ? pexitstat :
15202 pty_get_status(ptyfd,pty_fork_pid);
15203 debug(F101,"ttptycmd pty_get_status D","",status);
15204 if (status > -1) {
15205 pexitstat = status;
15206 pty_err++;
15207 have_pty = 0;
15208 } else { /* Select() lied */
15209 pty_err = 0; /* pty still there but has nothing */
15210 msleep(100); /* sleep a bit */
15211 }
15212 x = 0;
15213 }
15214 /* Hopefully the next two are no longer needed... */
15215 if (!pty_err && (
15216 #ifndef PTY_USE_NDELAY
15217 x < 1 || errno
15218 #else
15219 errno != 0 && errno != EAGAIN
15220 #endif /* PTY_USE_NDELAY */
15221 )) {
15222 debug(F100,"TERMINATION TEST C","",0);
15223 pty_err++;
15224 debug(F101,"ttptycmd SET pty_err","",pty_err);
15225 if (errno == EIO) /* errno == EIO is like EOF */
15226 rc = 1;
15227 if (x < 0)
15228 x = 0;
15229 }
15230 #ifdef COMMENT
15231 #ifdef DEBUG
15232 if (deblog) {
15233 pbuf[pbuf_avail + x] = '\0';
15234 debug(F111,"ttptycmd added to pty buffer",
15235 pbuf+pbuf_avail,x);
15236 }
15237 #endif /* DEBUG */
15238 #endif /* COMMENT */
15239 pbuf_avail += x;
15240 read_pty_bytes += x;
15241 } else { /* n == 0 with blocking reads */
15242 debug(F100,
15243 "PTY READ RETURNED ZERO BYTES - SHOULD NOT HAPPEN",
15244 "",0);
15245 }
15246 } else
15247 pnotset++;
15248
15249 /* If writes have caught up to reads, reset the buffers */
15250
15251 if (pbuf_written == pbuf_avail)
15252 pbuf_written = pbuf_avail = 0;
15253 if (tbuf_written == tbuf_avail)
15254 tbuf_written = tbuf_avail = 0;
15255
15256 /* See if we can exit */
15257
15258 x1 = pbuf_avail - pbuf_written;
15259 x2 = tbuf_avail - tbuf_written;
15260
15261 debug(F101,"ttptycmd pty_err LOOP EXIT TEST pty_err","",pty_err);
15262 debug(F101,"ttptycmd pty_err LOOP EXIT TEST x1 [write to net]","",x1);
15263 debug(F101,"ttptycmd pty_err LOOP EXIT TEST x2 [write to pty]","",x2);
15264 debug(F101,"ttptycmd pty_err LOOP EXIT TEST rc","",rc);
15265 debug(F101,"ttptycmd pty_err LOOP EXIT TEST status","",status);
15266 debug(F101,"ttptycmd pty_err LOOP EXIT TEST pexitstat","",pexitstat);
15267
15268 if (net_err) { /* Net error? */
15269 debug(F101,"ttptycmd net_err LOOP EXIT TEST net_err","",net_err);
15270 if (have_net) {
15271 if (local) {
15272 ttclos(0);
15273 printf("?Connection closed\n");
15274 }
15275 have_net = 0;
15276 }
15277 debug(F101,"ttptycmd net_err LOOP EXIT TEST x1","",x1);
15278 if (x1 == 0)
15279 break;
15280 }
15281 if (pty_err) { /* Pty error? */
15282 if (have_pty) {
15283 if (pexitstat < 0) {
15284 status = pty_get_status(ptyfd,pty_fork_pid);
15285 debug(F101,"ttptycmd pty_get_status E","",status);
15286 if (status > -1) pexitstat = status;
15287 }
15288 have_pty = 0;
15289 }
15290 if (x1 == 0 && x2 == 0) { /* If buffers are caught up */
15291 rc = 1; /* set preliminary return to success */
15292 debug(F101,"ttptycmd pty_err LOOP EXIT TEST rc 2","",rc);
15293 break; /* and exit the loop */
15294 }
15295 }
15296 }
15297 debug(F101,"ttptycmd +++ have_pty","",have_pty);
15298 if (have_pty) { /* In case select() failed */
15299 #ifdef USE_CKUPTY_C
15300 end_pty();
15301 close(ptyfd);
15302 #else
15303 close(slavefd);
15304 close(masterfd);
15305 #endif /* USE_CKUPTY_C */
15306 }
15307 pty_master_fd = -1;
15308 debug(F101,"ttptycmd +++ pexitstat","",pexitstat);
15309 if (pexitstat < 0) { /* Try one last time to get status */
15310 status = pty_get_status(ptyfd,pty_fork_pid);
15311 debug(F101,"ttptycmd pty_get_status F","",status);
15312 if (status > -1) pexitstat = status;
15313 }
15314 debug(F101,"ttptycmd +++ final pexitstat","",pexitstat);
15315 if (deblog) { /* Stats for debug log */
15316 debug(F101,"ttptycmd +++ pset ","",pset);
15317 debug(F101,"ttptycmd +++ pnotset","",pnotset);
15318 debug(F101,"ttptycmd +++ tset ","",tset);
15319 debug(F101,"ttptycmd +++ tnotset","",tnotset);
15320
15321 debug(F101,"ttptycmd +++ read_pty_bytes","",read_pty_bytes);
15322 debug(F101,"ttptycmd +++ write_net_bytes","",write_net_bytes);
15323 debug(F101,"ttptycmd +++ read_net_bytes","",read_net_bytes);
15324 debug(F101,"ttptycmd +++ write_pty_bytes","",write_pty_bytes);
15325 }
15326 /*
15327 If we got the external protocol's exit status from waitpid(), we use that
15328 to set our return code. If not, we fall back on whatever rc was previously
15329 set to, namely 1 (success) if the pty fork seemed to terminate, 0 otherwise.
15330 */
15331 if (save_sigchld) { /* Restore this if we changed it */
15332 (VOID) signal(SIGCHLD,save_sigchld);
15333 save_sigchld = NULL;
15334 }
15335 msleep(500);
15336 x = kill(pty_fork_pid,SIGHUP); /* In case it's still there */
15337 pty_fork_pid = -1;
15338 debug(F101,"ttptycmd fork kill SIGHUP","",x);
15339 if (pexitstat > -1)
15340 rc = (pexitstat == 0 ? 1 : 0);
15341 debug(F101,"ttptycmd +++ rc","",rc);
15342 if (!local) { /* If in remote mode */
15343 conres(); /* restore console to CBREAK mode */
15344 concb((char)escchr);
15345 }
15346 return(rc);
15347 }
15348 #endif /* NETPTY */
15349 #endif /* SELECT */
15350
15351 /* T T R U N C M D -- Redirect an external command over the connection. */
15352
15353 /*
15354 TTRUNCMD is the routine that was originally used for running external
15355 protocols. It is very simple and works fine provided (a) the connection
15356 is not encrypted, and (b) the external protocol uses standard i/o
15357 (file descriptors 0 and 1) for file transfer.
15358 */
15359
15360 int
15361 ttruncmd(s) char *s; {
15362 PID_T pid; /* pid of lower fork */
15363 int wstat; /* for wait() */
15364 int x;
15365 int statusp;
15366
15367 if (ttyfd == -1) {
15368 printf("?Sorry, device is not open\n");
15369 return(0);
15370 }
15371 if (nopush) {
15372 debug(F100,"ttruncmd fail: nopush","",0);
15373 return(0);
15374 }
15375
15376 #ifdef NETPTY
15377 /***************
15378 It might also be necessary to use the pty routine for other reasons,
15379 e.g. because the external program does not use stdio.
15380 */
15381 #ifdef NETCONN
15382 /*
15383 If we have a network connection we use a different routine because
15384 (a) if the connection is encrypted, the mechanism used here can't deal
15385 with it; and (b) it won't handle any network protocols either, e.g.
15386 Telnet, Rlogin, K5 U-to-U, etc. However, this routine works much
15387 better (faster, more transparent) on serial connections and when
15388 C-Kermit is in remote mode (i.e. is on the far end).
15389 */
15390 /* For testing always use this */
15391 if (netconn)
15392 return(ttptycmd(s));
15393 #endif /* NETCONN */
15394
15395 /***************/
15396 #else /* NETPTY */
15397 if (tt_is_secure()) {
15398 printf("?Sorry, \
15399 external protocols over secure connections not supported in this OS.\n"
15400 );
15401 return(0);
15402 }
15403 #endif /* NETPTY */
15404
15405 conres(); /* Make console normal */
15406 pexitstat = -4;
15407 if ((pid = fork()) == 0) { /* Make a child fork */
15408 if (priv_can()) /* Child: turn off privs. */
15409 exit(1);
15410 dup2(ttyfd, 0); /* Give stdin/out to the line */
15411 dup2(ttyfd, 1);
15412 x = system(s);
15413 debug(F101,"ttruncmd system",s,x);
15414 _exit(x ? BAD_EXIT : 0);
15415 } else {
15416 SIGTYP (*istat)(), (*qstat)();
15417 if (pid == (PID_T) -1) /* fork() failed? */
15418 return(0);
15419 istat = signal(SIGINT,SIG_IGN); /* Let the fork handle keyboard */
15420 qstat = signal(SIGQUIT,SIG_IGN); /* interrupts itself... */
15421
15422 #ifdef COMMENT
15423 while (((wstat = wait(&statusp)) != pid) && (wstat != -1)) ;
15424 #else /* Not COMMENT */
15425 while (1) {
15426 wstat = wait(&statusp);
15427 debug(F101,"ttruncmd wait","",wstat);
15428 if (wstat == pid || wstat == -1)
15429 break;
15430 }
15431 #endif /* COMMENT */
15432
15433 pexitstat = (statusp & 0xff) ? statusp : statusp >> 8;
15434 debug(F101,"ttruncmd wait statusp","",statusp);
15435 debug(F101,"ttruncmd wait pexitstat","",pexitstat);
15436 signal(SIGINT,istat); /* Restore interrupts */
15437 signal(SIGQUIT,qstat);
15438 }
15439 concb((char)escchr); /* Restore console to CBREAK mode */
15440 return(statusp == 0 ? 1 : 0);
15441 }
15442 #endif /* CK_REDIR */
15443
15444 struct tm *
15445 #ifdef CK_ANSIC
15446 cmdate2tm(char * date, int gmt) /* date as "yyyymmdd hh:mm:ss" */
15447 #else
15448 cmdate2tm(date,gmt) char * date; int gmt;
15449 #endif
15450 {
15451 /* date as "yyyymmdd hh:mm:ss" */
15452 static struct tm _tm;
15453 time_t now;
15454
15455 if (strlen(date) != 17 ||
15456 date[8] != ' ' ||
15457 date[11] != ':' ||
15458 date[14] != ':')
15459 return(NULL);
15460
15461 time(&now);
15462 if (gmt)
15463 _tm = *gmtime(&now);
15464 else
15465 _tm = *localtime(&now);
15466 _tm.tm_year = (date[0]-'0')*1000 + (date[1]-'0')*100 +
15467 (date[2]-'0')*10 + (date[3]-'0')-1900;
15468 _tm.tm_mon = (date[4]-'0')*10 + (date[5]-'0')-1;
15469 _tm.tm_mday = (date[6]-'0')*10 + (date[7]-'0');
15470 _tm.tm_hour = (date[9]-'0')*10 + (date[10]-'0');
15471 _tm.tm_min = (date[12]-'0')*10 + (date[13]-'0');
15472 _tm.tm_sec = (date[15]-'0')*10 + (date[16]-'0');
15473
15474 /* Should we set _tm.tm_isdst to -1 here? */
15475
15476 _tm.tm_wday = 0;
15477 _tm.tm_yday = 0;
15478
15479 return(&_tm);
15480 }
15481
15482 #ifdef HAVE_LOCALE
15483 #include <langinfo.h>
15484 #define DAYNAMERESULT 128
15485 static char daynameresult[DAYNAMERESULT];
15486 /*
15487 day = day-of-week number, 0-6 (0=Su, 1=Mo, 2=Tu, ..., 6=Sa).
15488 fc = 0 for full name, 1 for standard abbreviation, e.g. Mon, Tue.
15489 Returns: Day name according to current locale on success; NULL on failure.
15490 Note: nl_langinfo() items are indexed by numbers that vary from
15491 platform to platform (e.g. NetBSD and Solaris are totally different).
15492 */
15493 char *
15494 locale_dayname(day,fc) int day, fc; {
15495 /* date as "yyyymmdd hh:mm:ss" */
15496 int n = 0;
15497 int x = DAY_1;
15498 char * date;
15499 char buf[20];
15500
15501 if (day < 0 || day > 6) return(NULL);
15502 n = day + 1;
15503 if (n > 6) n = 0; /* 2013-10-15 */
15504 if (fc) x = ABDAY_1;
15505 ckstrncpy(daynameresult,nl_langinfo(((nl_item)(n+x))),DAYNAMERESULT);
15506 return((char *)daynameresult);
15507 }
15508 #define MONTHNAMERESULT 128
15509 static char monthnameresult[MONTHNAMERESULT];
15510 /*
15511 month = month-of-year number, 0-11 (0=Jan, 1=Feb, 2=Mar, ..., 11=Dec).
15512 fc = 0 for full name, 1 for standard abbreviation, e.g. Jan, Feb.
15513 Returns: Month name according to current locale on success; NULL on failure.
15514 */
15515 char *
15516 locale_monthname(month,fc) int month, fc; {
15517 int n = 0;
15518 int x = MON_1;
15519 char * date;
15520 char buf[20];
15521 char mbuf[4];
15522
15523 if (month < 0 || month > 11) return(NULL);
15524 n = month; /* 0-based calendar month number */
15525 if (fc) x = ABMON_1;
15526 ckstrncpy(monthnameresult,nl_langinfo(((nl_item)(n+x))),MONTHNAMERESULT);
15527 return((char *)monthnameresult);
15528 }
15529 #endif /* HAVE_LOCALE */
15530
15531 #ifdef OXOS
15532 #undef kill
15533 #endif /* OXOS */
15534
15535 #ifdef OXOS
15536 int
15537 priv_kill(pid, sig) int pid, sig; {
15538 int i;
15539
15540 if (priv_on())
15541 debug(F100,"priv_kill priv_on failed","",0);
15542 i = kill(pid, sig);
15543 if (priv_off())
15544 debug(F100,"priv_kill priv_off failed","",0);
15545 return(i);
15546 }
15547 #endif /* OXOS */
15548
15549 #ifdef BEOSORBEBOX
15550 /* #ifdef BE_DR_7 */
15551 /*
15552 alarm() function not supplied with Be OS DR7 - this one contributed by
15553 Neal P. Murphy.
15554 */
15555
15556 /*
15557 This should mimic the UNIX/POSIX alarm() function well enough, with the
15558 caveat that one's SIGALRM handler must call alarm_expired() to clean up vars
15559 and wait for the alarm thread to finish.
15560 */
15561 unsigned int
15562 alarm(unsigned int seconds) {
15563 long time_left = 0;
15564
15565 /* If an alarm is active, turn it off, saving the unused time */
15566 if (alarm_thread != -1) {
15567 /* We'll be generous and count partial seconds as whole seconds. */
15568 time_left = alarm_struct.time -
15569 ((system_time() - time_started) / 1000000.0);
15570
15571 /* Kill the alarm thread */
15572 kill_thread (alarm_thread);
15573
15574 /* We need to clean up as though the alarm occured. */
15575 time_started = 0;
15576 alarm_struct.thread = -1;
15577 alarm_struct.time = 0;
15578 alarm_expired();
15579 }
15580
15581 /* Set a new alarm clock, if requested. */
15582 if (seconds > 0) {
15583 alarm_struct.thread = find_thread(NULL);
15584 alarm_struct.time = seconds;
15585 time_started = system_time();
15586 alarm_thread = spawn_thread (do_alarm,
15587 "alarm_thread",
15588 B_NORMAL_PRIORITY,
15589 (void *) &alarm_struct
15590 );
15591 resume_thread (alarm_thread);
15592 }
15593
15594 /* Now return [unused time | 0] */
15595 return ((unsigned int) time_left);
15596 }
15597
15598 /*
15599 This function is the departure from UNIX/POSIX alarm handling. In the case
15600 of Be's missing alarm() function, this stuff needs to be done in the SIGALRM
15601 handler. When Be implements alarm(), this function call can be eliminated
15602 from user's SIGALRM signal handlers.
15603 */
15604
15605 void
15606 alarm_expired(void) {
15607 long ret_val;
15608
15609 if (alarm_thread != -1) {
15610 wait_for_thread (alarm_thread, &ret_val);
15611 alarm_thread = -1;
15612 }
15613 }
15614
15615 /*
15616 This is the function that snoozes the requisite number of seconds and then
15617 SIGALRMs the calling thread. Note that kill() wants a pid_t arg, whilst Be
15618 uses thread_id; currently they are both typdef'ed as long, but I'll do the
15619 cast anyway. This function is run in a separate thread.
15620 */
15621
15622 long
15623 do_alarm (void *alarm_struct) {
15624 snooze ((double) ((struct ALARM_STRUCT *) alarm_struct)->time * 1000000.0);
15625 kill ((pid_t)((struct ALARM_STRUCT *) alarm_struct)->thread, SIGALRM);
15626 time_started = 0;
15627 ((struct ALARM_STRUCT *) alarm_struct)->thread = -1;
15628 ((struct ALARM_STRUCT *) alarm_struct)->time = 0;
15629 }
15630 /* #endif */ /* BE_DR_7 */
15631 #endif /* BEOSORBEBOX */
15632
15633 #ifdef Plan9
15634
15635 int
15636 p9ttyctl(char letter, int num, int param) {
15637 char cmd[20];
15638 int len;
15639
15640 if (ttyctlfd < 0)
15641 return -1;
15642
15643 cmd[0] = letter;
15644 if (num)
15645 len = sprintf(cmd + 1, "%d", param) + 1;
15646 else {
15647 cmd[1] = param;
15648 len = 2;
15649 }
15650 if (write(ttyctlfd, cmd, len) == len) {
15651 cmd[len] = 0;
15652 /* fprintf(stdout, "wrote '%s'\n", cmd); */
15653 return 0;
15654 }
15655 return -1;
15656 }
15657
15658 int
15659 p9ttyparity(char l) {
15660 return p9ttyctl('p', 0, l);
15661 }
15662
15663 int
15664 p9tthflow(int flow, int status) {
15665 return p9ttyctl('m', 1, status);
15666 }
15667
15668 int
15669 p9ttsspd(int cps) {
15670 if (p9ttyctl('b', 1, cps * 10) < 0)
15671 return -1;
15672 ttylastspeed = cps * 10;
15673 return 0;
15674 }
15675
15676 int
15677 p9openttyctl(char *ttname) {
15678 char name[100];
15679
15680 if (ttyctlfd >= 0) {
15681 close(ttyctlfd);
15682 ttyctlfd = -1;
15683 ttylastspeed = -1;
15684 }
15685 sprintf(name, "%sctl", ttname);
15686 ttyctlfd = open(name, 1);
15687 return ttyctlfd;
15688 }
15689
15690 int
15691 p9concb() {
15692 if (consctlfd >= 0) {
15693 if (write(consctlfd, "rawon", 5) == 5)
15694 return 0;
15695 }
15696 return -1;
15697 }
15698
15699 int
15700 p9conbin() {
15701 return p9concb();
15702 }
15703
15704 int
15705 p9conres() {
15706 if (consctlfd >= 0) {
15707 if (write(consctlfd, "rawoff", 6) == 6)
15708 return 0;
15709 }
15710 return -1;
15711 }
15712
15713 int
15714 p9sndbrk(int msec) {
15715 if (ttyctlfd >= 0) {
15716 char cmd[20];
15717 int i = sprintf(cmd, "k%d", msec);
15718 if (write(ttyctlfd, cmd, i) == i)
15719 return 0;
15720 }
15721 return -1;
15722 }
15723
15724 int
15725 conwrite(char *buf, int n) {
15726 int x;
15727 static int length = 0;
15728 static int holdingcr = 0;
15729 int normal = 0;
15730 for (x = 0; x < n; x++) {
15731 char c = buf[x];
15732 if (c == 007) {
15733 if (normal) {
15734 write(1, buf + (x - normal), normal);
15735 length += normal;
15736 normal = 0;
15737 }
15738 /* write(noisefd, "1000 300", 8); */
15739 holdingcr = 0;
15740 } else if (c == '\r') {
15741 if (normal) {
15742 write(1, buf + (x - normal), normal);
15743 length += normal;
15744 normal = 0;
15745 }
15746 holdingcr = 1;
15747 } else if (c == '\n') {
15748 write(1, buf + (x - normal), normal + 1);
15749 normal = 0;
15750 length = 0;
15751 holdingcr = 0;
15752 } else if (c == '\b') {
15753 if (normal) {
15754 write(1, buf + (x - normal), normal);
15755 length += normal;
15756 normal = 0;
15757 }
15758 if (length) {
15759 write(1, &c, 1);
15760 length--;
15761 }
15762 holdingcr = 0;
15763 } else {
15764 if (holdingcr) {
15765 char b = '\b';
15766 while (length-- > 0)
15767 write(1, &b, 1);
15768 length = 0; /* compiler bug */
15769 }
15770 holdingcr = 0;
15771 normal++;
15772 }
15773 }
15774 if (normal) {
15775 write(1, buf + (x - normal), normal);
15776 length += normal;
15777 }
15778 return n;
15779 }
15780
15781 void
15782 conprint(char *fmt, ...) {
15783 static char buf[1000]; /* not safe if on the stack */
15784
15785 va_list ap;
15786 int i;
15787
15788 va_start(ap, fmt);
15789 i = vsprintf(buf, fmt, ap);
15790 conwrite(buf, i);
15791 }
15792 #endif /* Plan9 */
15793
15794 /* fprintf, printf, perror replacements... */
15795
15796 /* f p r i n t f */
15797
15798 #ifdef UNIX
15799 #ifdef CK_ANSIC
15800 #include <stdarg.h>
15801 #else /* CK_ANSIC */
15802 #ifdef __GNUC__
15803 #include <stdarg.h>
15804 #else
15805 #include <varargs.h>
15806 #endif /* __GNUC__ */
15807 #endif /* CK_ANSIC */
15808 #ifdef fprintf
15809 #undef fprintf
15810 static char str1[4096];
15811 static char str2[4096];
15812 int
15813 #ifdef CK_ANSIC
15814 ckxfprintf(FILE * file, const char * format, ...)
15815 #else /* CK_ANSIC */
15816 ckxfprintf(va_alist) va_dcl
15817 #endif /* CK_ANSIC */
15818 /* ckxfprintf */ {
15819 int i, j, len, got_cr;
15820 va_list args;
15821 int rc = 0;
15822
15823 #ifdef CK_ANSIC
15824 va_start(args, format);
15825 #else /* CK_ANSIC */
15826 char * format;
15827 FILE * file;
15828 va_start(args);
15829 file = va_arg(args,FILE *);
15830 format = va_arg(args,char *);
15831 #endif /* CK_ANSIC */
15832
15833 if (!inserver || (file != stdout && file != stderr && file != stdin)) {
15834 rc = vfprintf(file,format,args);
15835 } else {
15836 unsigned int c;
15837 rc = vsprintf(str1, format, args);
15838 len = strlen(str1);
15839 if (len >= sizeof(str1)) {
15840 debug(F101,"ckxfprintf() buffer overflow","",len);
15841 doexit(BAD_EXIT,1);
15842 }
15843 for (i = 0, j = 0, got_cr = 0;
15844 i < len && j < sizeof(str1)-2;
15845 i++, j++ ) {
15846 /* We can't use 255 as a case label because of signed chars */
15847 c = (unsigned)(str1[i] & 0xff);
15848 #ifdef TNCODE
15849 if (c == 255) {
15850 if (got_cr && !TELOPT_ME(TELOPT_BINARY))
15851 str2[j++] = '\0';
15852 str2[j++] = IAC;
15853 str2[j] = IAC;
15854 got_cr = 0;
15855 } else
15856 #endif /* TNCODE */
15857 switch (c) {
15858 case '\r':
15859 if (got_cr
15860 #ifdef TNCODE
15861 && !TELOPT_ME(TELOPT_BINARY)
15862 #endif /* TNCODE */
15863 )
15864 str2[j++] = '\0';
15865 str2[j] = str1[i];
15866 got_cr = 1;
15867 break;
15868 case '\n':
15869 if (!got_cr)
15870 str2[j++] = '\r';
15871 str2[j] = str1[i];
15872 got_cr = 0;
15873 break;
15874 default:
15875 if (got_cr
15876 #ifdef TNCODE
15877 && !TELOPT_ME(TELOPT_BINARY)
15878 #endif /* TNCODE */
15879 )
15880 str2[j++] = '\0';
15881 str2[j] = str1[i];
15882 got_cr = 0;
15883 }
15884 }
15885 if (got_cr
15886 #ifdef TNCODE
15887 && !TELOPT_ME(TELOPT_BINARY)
15888 #endif /* TNCODE */
15889 )
15890 str2[j++] = '\0';
15891 #ifdef CK_ENCRYPTION
15892 #ifdef TNCODE
15893 if (TELOPT_ME(TELOPT_ENCRYPTION))
15894 ck_tn_encrypt(str2,j);
15895 #endif /* TNCODE */
15896 #endif /* CK_ENCRYPTION */
15897 #ifdef CK_SSL
15898 if (inserver && (ssl_active_flag || tls_active_flag)) {
15899 /* Write using SSL */
15900 char * p = str2;
15901 ssl_retry:
15902 if (ssl_active_flag)
15903 rc = SSL_write(ssl_con, p, j);
15904 else
15905 rc = SSL_write(tls_con, p, j);
15906 debug(F111,"ckxfprintf","SSL_write",rc);
15907 switch (SSL_get_error(ssl_active_flag?ssl_con:tls_con,rc)) {
15908 case SSL_ERROR_NONE:
15909 if (rc == j)
15910 break;
15911 p += rc;
15912 j -= rc;
15913 goto ssl_retry;
15914 case SSL_ERROR_WANT_WRITE:
15915 case SSL_ERROR_WANT_READ:
15916 case SSL_ERROR_SYSCALL:
15917 if (rc != 0)
15918 return(-1);
15919 case SSL_ERROR_WANT_X509_LOOKUP:
15920 case SSL_ERROR_SSL:
15921 case SSL_ERROR_ZERO_RETURN:
15922 default:
15923 rc = 0;
15924 }
15925 } else
15926 #endif /* CK_SSL */
15927 fwrite(str2,sizeof(char),j,stdout);
15928 }
15929 va_end(args);
15930 return(rc);
15931 }
15932 #endif /* fprintf */
15933
15934 /* p r i n t f */
15935
15936 #ifdef printf
15937 #undef printf
15938 int
15939 #ifdef CK_ANSIC
15940 ckxprintf(const char * format, ...)
15941 #else /* CK_ANSIC */
15942 ckxprintf(va_alist) va_dcl
15943 #endif /* CK_ANSIC */
15944 /* ckxprintf */ {
15945 int i, j, len, got_cr;
15946 va_list args;
15947 int rc = 0;
15948
15949 #ifdef CK_ANSIC
15950 va_start(args, format);
15951 #else /* CK_ANSIC */
15952 char * format;
15953 va_start(args);
15954 format = va_arg(args,char *);
15955 #endif /* CK_ANSIC */
15956
15957 if (!inserver) {
15958 rc = vprintf(format, args);
15959 } else {
15960 unsigned int c;
15961 rc = vsprintf(str1, format, args);
15962 len = strlen(str1);
15963 if (len >= sizeof(str1)) {
15964 debug(F101,"ckxprintf() buffer overflow","",len);
15965 doexit(BAD_EXIT,1);
15966 }
15967 for (i = 0, j = 0, got_cr=0;
15968 i < len && j < sizeof(str1)-2;
15969 i++, j++ ) {
15970 c = (unsigned)(str1[i] & 0xff);
15971 #ifdef TNCODE
15972 if (c == 255) {
15973 if (got_cr && !TELOPT_ME(TELOPT_BINARY))
15974 str2[j++] = '\0';
15975 str2[j++] = IAC;
15976 str2[j] = IAC;
15977 got_cr = 0;
15978 } else
15979 #endif /* TNCODE */
15980 switch (c) {
15981 case '\r':
15982 if (got_cr
15983 #ifdef TNCODE
15984 && !TELOPT_ME(TELOPT_BINARY)
15985 #endif /* TNCODE */
15986 )
15987 str2[j++] = '\0';
15988 str2[j] = str1[i];
15989 got_cr = 1;
15990 break;
15991 case '\n':
15992 if (!got_cr)
15993 str2[j++] = '\r';
15994 str2[j] = str1[i];
15995 got_cr = 0;
15996 break;
15997 default:
15998 if (got_cr
15999 #ifdef TNCODE
16000 && !TELOPT_ME(TELOPT_BINARY)
16001 #endif /* TNCODE */
16002 )
16003 str2[j++] = '\0';
16004 str2[j] = str1[i];
16005 got_cr = 0;
16006 break;
16007 }
16008 }
16009 if (got_cr
16010 #ifdef TNCODE
16011 && !TELOPT_ME(TELOPT_BINARY)
16012 #endif /* TNCODE */
16013 )
16014 str2[j++] = '\0';
16015 #ifdef CK_ENCRYPTION
16016 #ifdef TNCODE
16017 if (TELOPT_ME(TELOPT_ENCRYPTION))
16018 ck_tn_encrypt(str2,j);
16019 #endif /* TNCODE */
16020 #endif /* CK_ENCRYPTION */
16021 #ifdef CK_SSL
16022 if (inserver && (ssl_active_flag || tls_active_flag)) {
16023 char * p = str2;
16024 /* Write using SSL */
16025 ssl_retry:
16026 if (ssl_active_flag)
16027 rc = SSL_write(ssl_con, p, j);
16028 else
16029 rc = SSL_write(tls_con, p, j);
16030 debug(F111,"ckxprintf","SSL_write",rc);
16031 switch (SSL_get_error(ssl_active_flag?ssl_con:tls_con,rc)) {
16032 case SSL_ERROR_NONE:
16033 if (rc == j)
16034 break;
16035 p += rc;
16036 j -= rc;
16037 goto ssl_retry;
16038 case SSL_ERROR_WANT_WRITE:
16039 case SSL_ERROR_WANT_READ:
16040 case SSL_ERROR_SYSCALL:
16041 if (rc != 0)
16042 return(-1);
16043 case SSL_ERROR_WANT_X509_LOOKUP:
16044 case SSL_ERROR_SSL:
16045 case SSL_ERROR_ZERO_RETURN:
16046 default:
16047 rc = 0;
16048 }
16049 } else
16050 #endif /* CK_SSL */
16051 rc = fwrite(str2,sizeof(char),j,stdout);
16052 }
16053 va_end(args);
16054 return(rc);
16055 }
16056 #endif /* printf */
16057
16058 /* p e r r o r */
16059
16060 #ifdef perror
16061 #undef perror
16062 _PROTOTYP(char * ck_errstr,(VOID));
16063 #ifdef NEXT
16064 void
16065 #else
16066 #ifdef CK_SCOV5
16067 void
16068 #else
16069 int
16070 #endif /* CK_SCOV5 */
16071 #endif /* NEXT */
16072 #ifdef CK_ANSIC
16073 ckxperror(const char * str)
16074 #else /* CK_ANSIC */
16075 ckxperror(str) char * str;
16076 #endif /* CK_ANSIC */
16077 /* ckxperror */ {
16078 char * errstr = ck_errstr();
16079 #ifndef NEXT
16080 #ifndef CK_SCOV5
16081 return
16082 #endif /* CK_SCOV5 */
16083 #endif /* NEXT */
16084 ckxprintf("%s%s %s\n",str,*errstr?":":"",errstr);
16085 }
16086 #endif /* perror */
16087 #endif /* UNIX */
16088
16089 #ifdef MINIX2
16090
16091 /* Minix doesn't have a gettimeofday call (but MINIX3 does).
16092 * We fake one here using time(2)
16093 */
16094
16095 #ifndef MINIX3
16096 int
16097 gettimeofday(struct timeval *tp, struct timezone *tzp) {
16098 tp->tv_usec = 0L; /* Close enough for horseshoes */
16099 if(time(&(tp->tv_sec))==-1)
16100 return(-1);
16101 return(0);
16102 }
16103 #endif /* MINIX3 */
16104
16105 #ifndef MINIX3
16106 int
16107 readlink(const char *path, void *buf, size_t bufsiz) {
16108 errno = ENOSYS;
16109 return(-1);
16110 }
16111 #endif /* MINIX3 */
16112
16113 #endif /* MINIX2 */
16114