ckutio.c
上传用户:dufan58
上传日期:2007-01-05
资源大小:3407k
文件大小:361k
源码类别:

通讯/手机编程

开发平台:

Windows_Unix

  1. debug(F101,"in_chk COHERENT select","",n);
  2. #else
  3. #ifdef SVR4
  4. n = select( FD_SETSIZE, &rfds, (fd_set *)0, (fd_set *)0, &tv );
  5. debug(F101,"in_chk SVR4 select","",n);
  6. #else
  7. #ifdef __linux__
  8. n = select( FD_SETSIZE, &rfds, (fd_set *)0, (fd_set *)0, &tv );
  9. debug(F101,"in_chk LINUX select","",n);
  10. #else
  11. n = select( FD_SETSIZE, &rfds, (int *)0, (int *)0, &tv );
  12. debug(F101,"in_chk catchall select","",n);
  13. #endif /* __linux__ */
  14. #endif /* SVR4 */
  15. #endif /* COHERENT */
  16. #endif /* QNX */
  17. #endif /* SOLARIS */
  18. #endif /* BSD43 */
  19. #endif /* BSD44 */
  20. #endif /* BELLV10 */
  21. #endif /* Plan9 */
  22.     }
  23. #else  /* Not SELECT */
  24. #ifdef CK_POLL
  25.     {
  26.       struct pollfd pfd;
  27.       pfd.fd = fd;
  28.       pfd.events = POLLIN;
  29.       pfd.revents = 0;
  30.       n = poll(&pfd, 1, 0);
  31.       debug(F101,"in_chk poll","",n);
  32.       if ((n > 0) && (pfd.revents & POLLIN))
  33. n = 1;
  34.     }
  35. #endif /* CK_POLL */
  36. #endif /* SELECT */
  37. #endif /* RDCHK */
  38. #endif /* PROVX1 */
  39. #endif /* V7 */
  40. #endif /* FIONREAD */
  41. /* From here down, treat console and communication device differently... */
  42.     if (channel == 0) { /* Console */
  43. #ifdef SVORPOSIX
  44. #ifndef FIONREAD
  45. #ifndef SELECT
  46. #ifndef CK_POLL
  47. #ifndef RDCHK
  48. /*
  49.   This is the hideous hack used in System V and POSIX systems that don't
  50.   support FIONREAD, rdchk(), select(), poll(), etc, in which the user's
  51.   CONNECT-mode escape character is attached to SIGQUIT.  Used, obviously,
  52.   only on the console.
  53. */
  54. if (conesc) { /* Escape character typed == SIGQUIT */
  55.     debug(F100,"in_chk conesc","",conesc);
  56.     conesc = 0;
  57.     signal(SIGQUIT,esctrp); /* Restore signal */
  58.     n += 1;
  59. }
  60. #endif /* RDCHK */
  61. #endif /* CK_POLL */
  62. #endif /* SELECT */
  63. #endif /* FIONREAD */
  64. #endif /* SVORPOSIX */
  65. return(n); /* Done with console */
  66.     }
  67.     if (channel != 0) { /* Communications connection */
  68. #ifdef MYREAD
  69. #ifndef FIONREAD
  70. /*
  71.   select() or rdchk(), etc, has told us that something is waiting, but we
  72.   don't know how much.  So we do a read to get it and then we know.  Note:
  73.   This read is NOT nonblocking if nothing is there (because of VMIN=1), but
  74.   it should be safe in this case since the OS tells us at least one byte is
  75.   waiting to be read, and MYREAD reads return as much as is there without
  76.   waiting for any more.  Controlled tests on Solaris and Unixware (with
  77.   FIONREAD deliberately undefined) show this to be true.
  78. */
  79. debug(F101,"in_chk read my_count","",my_count);
  80. debug(F101,"in_chk read n","",n);
  81. if (n > 0 && my_count == 0) {
  82.     /* This also catches disconnects etc */
  83.     /* Do what mygetbuf does except don't grab a character */
  84.     my_count = myfillbuf();
  85.     my_item = -1; /* ^^^ */
  86.     debug(F101,"in_chk myfillbuf my_count","",my_count);
  87.     if (my_count < 0)
  88.       return(-1);
  89.     else
  90.       n = 0; /* NB: n is replaced by my_count */
  91. }
  92. #endif /* FIONREAD */
  93. /*
  94.   Here we add whatever we think is unread to what is still in our
  95.   our internal buffer.  Thus the importance of setting n to 0 just above.
  96. */
  97. debug(F101,"in_chk my_count","",my_count);
  98. debug(F101,"in_chk n","",n);
  99. if (my_count > 0)
  100.   n += my_count;
  101. #endif /* MYREAD */
  102.     }
  103.     debug(F101,"in_chk result","",n);
  104.     /* Errors here don't prove the connection has dropped so just say 0 */
  105.     return(n < 0 ? 0 : n);
  106. }
  107. /*  T T C H K  --  Tell how many characters are waiting in tty input buffer  */
  108. int
  109. ttchk() {
  110.     int fd;
  111. #ifdef NETCMD
  112.     if (ttpipe)
  113.       fd = fdin;
  114.     else
  115. #endif /* NETCMD */
  116.       fd = ttyfd;
  117.     return(in_chk(1,fd));
  118. }
  119. /*  T T X I N  --  Get n characters from tty input buffer  */
  120. /*  Returns number of characters actually gotten, or -1 on failure  */
  121. /*  Intended for use only when it is known that n characters are actually */
  122. /*  Available in the input buffer.  */
  123. int
  124. ttxin(n,buf) int n; CHAR *buf; {
  125.     register int x = 0, i = 0, c = -2;
  126.     char cc;
  127.     int fd;
  128.     if (n < 1) /* Nothing to do */
  129.       return(0);
  130. #ifdef TTLEBUF
  131.     if (ttpush >= 0) {
  132.         buf[0] = ttpush; /* Put pushed char in buffer*/
  133.         ttpush = -1; /* Clear the push buffer */
  134.         if (ttchk() > 0)
  135.   return(ttxin(n-1, &buf[1]) + 1);
  136.         else
  137.   return(1);
  138.     }
  139.     if (le_data) {
  140.         while (le_inbuf() > 0) {
  141.     if (le_getchar(&buf[i])) {
  142.                 i++;
  143.                 n--;
  144.             }
  145.         }
  146.         if (ttchk() > 0)
  147.   return(ttxin(n,&buf[i])+i);
  148.         else
  149.   return(i);
  150.     }
  151. #endif /* TTLEBUF */
  152. #ifdef NETCMD
  153.     if (ttpipe)
  154.       fd = fdin;
  155.     else
  156. #endif /* NETCMD */
  157.       fd = ttyfd;
  158. #ifdef SUNX25
  159.     if (netconn && (ttnet == NET_SX25)) /* X.25 connection */
  160.       return(x25xin(n,buf));
  161. #endif /* SUNX25 */
  162. #ifdef IBMX25
  163.     /* riehm: possibly not needed. Test worked with normal reads and writes */
  164.     if (netconn && (ttnet == NET_IX25)) { /* X.25 connection */
  165. x = x25xin(n,buf);
  166. if (x > 0) buf[x] = '';
  167. return(x);
  168.     }
  169. #endif /* IBMX25 */
  170. #ifdef MYREAD
  171.     debug(F101,"ttxin MYREAD","",n);
  172.     while (x < n) {
  173. c = myread();
  174. if (c < 0) {
  175.     debug(F101,"ttxin myread returns","",c);
  176.     if (c == -3) x = -1;
  177.     break;
  178.         }
  179. buf[x++] = c & ttpmsk;
  180. #ifdef RLOGCODE
  181. #ifdef CK_KERBEROS
  182.         /* It is impossible to know how many characters are waiting */
  183.         /* to be read when you are using Encrypted Rlogin or SSL    */
  184.         /* as the transport since the number of real data bytes     */
  185.         /* can be greater or less than the number of bytes on the   */
  186.         /* wire which is what ttchk() returns.                      */
  187.         if (netconn && (ttnproto == NP_EK4LOGIN || ttnproto == NP_EK5LOGIN))
  188.   if (ttchk() <= 0)
  189.     break;
  190. #endif /* CK_KERBEROS */
  191. #endif /* RLOGCODE */
  192. #ifdef CK_SSL
  193.         if (ssl_active_flag || tls_active_flag)
  194.   if (ttchk() <= 0)
  195.     break;
  196. #endif /* CK_SSL */
  197.     }
  198. #else
  199.     debug(F101,"ttxin READ","",n);
  200.     x = read(fd,buf,n);
  201.     for (c = 0; c < n; c++) /* Strip any parity */
  202.       buf[c] &= ttpmsk;
  203. #endif /* MYREAD */
  204.     debug(F101,"ttxin x","",x); /* Done */
  205.     if (x > 0) buf[x] = '';
  206.     if (x < 0) x = -1;
  207.     return(x);
  208. }
  209. /*  T T O L  --  Write string s, length n, to communication device.  */
  210. /*
  211.   Returns:
  212.    >= 0 on success, number of characters actually written.
  213.    -1 on failure.
  214. */
  215. #ifdef CK_ENCRYPTION
  216. CHAR * xpacket = NULL;
  217. int nxpacket = 0;
  218. #endif /* CK_ENCRYPTION */
  219. #define TTOLMAXT 5
  220. int
  221. ttol(s,n) int n; CHAR *s; {
  222.     int x, len, tries, fd;
  223. #ifdef CKXXCHAR
  224.     extern int dblflag; /* For SET SEND DOUBLE-CHARACTER */
  225.     extern short dblt[];
  226.     CHAR *p = NULL, *p2, *s2, c;
  227.     int n2 = 0;
  228. #endif /* CKXXCHAR */
  229.     if (ttyfd < 0) /* Not open? */
  230.       return(-3);
  231. #ifdef DEBUG
  232.     if (deblog) hexdump("ttol s",s,n);
  233. #endif /* DEBUG */
  234. #ifdef NETCMD
  235.     if (ttpipe)
  236.       fd = fdout;
  237.     else
  238. #endif /* NETCMD */
  239.       fd = ttyfd;
  240. #ifdef CKXXCHAR
  241. /*  Double any characters that must be doubled.  */
  242.     debug(F101,"ttol dblflag","",dblflag);
  243.     if (dblflag) {
  244. p = (CHAR *) malloc(n + n + 1);
  245. if (p) {
  246.     s2 = s;
  247.     p2 = p;
  248.     n2 = 0;
  249.     while (*s2) {
  250. c = *s2++;
  251. *p2++ = c;
  252. n2++;
  253. if (dblt[(unsigned) c] & 2) {
  254.     *p2++ = c;
  255.     n2++;
  256. }
  257.     }
  258.     s = p;
  259.     n = n2;
  260.     s[n] = '';
  261. }
  262.     }
  263.     debug(F111,"ttol doubled",s,n);
  264. #endif /* CKXXCHAR */
  265.     tries = TTOLMAXT; /* Allow up to this many tries */
  266.     len = n; /* Remember original length */
  267. #ifdef CK_ENCRYPTION
  268. /*
  269.   This is to avoid encrypting a packet that is already encrypted, e.g.
  270.   when we resend a packet directly out of the packet buffer, and also to
  271.   avoid encrypting a constant (literal) string, which can cause a memory
  272.   fault.
  273. */
  274.     if (TELOPT_ME(TELOPT_ENCRYPTION)) {
  275. int x;
  276. if (nxpacket < n) {
  277.     if (xpacket) {
  278. free(xpacket);
  279. xpacket = NULL;
  280. nxpacket = 0;
  281.     }
  282.     x = n > 10240 ? n : 10240;
  283.     xpacket = (CHAR *)malloc(x);
  284.     if (!xpacket) {
  285. fprintf(stderr,"ttol malloc failuren");
  286. return(-1);
  287.     } else
  288.       nxpacket = x;
  289. }
  290. memcpy((char *)xpacket,(char *)s,n);
  291. s = xpacket;
  292. ck_tn_encrypt((char *)s,n);
  293.     }
  294. #endif /* CK_ENCRYPTION */
  295.     while (n > 0 &&
  296.    (tries-- > 0
  297. #ifdef CK_ENCRYPTION
  298.     /* keep trying if we are encrypting */
  299.     || TELOPT_ME(TELOPT_ENCRYPTION)
  300. #endif /* CK_ENCRYPTION */
  301.             )) { /* Be persistent */
  302. debug(F101,"ttol try","",TTOLMAXT - tries);
  303. #ifdef BEOSORBEBOX
  304.         if (netconn && !ttpipe && !ttpty)
  305.   x = nettol(s,n); /* Write string to device */
  306.         else
  307. #endif /* BEOSORBEBOX */
  308. #ifdef IBMX25
  309.   if (ttnet == NET_IX25)
  310.     /*
  311.      * this is a more controlled way of writing to X25
  312.      * STREAMS, however write should also work!
  313.      */
  314.     x = x25write(ttyfd, s, n);
  315.   else
  316. #endif /* IBMX25 */
  317. #ifdef CK_SSL
  318.     if (ssl_active_flag || tls_active_flag) {
  319. int error;
  320. /* Write using SSL */
  321. if (ssl_active_flag)
  322.                   x = SSL_write(ssl_con, s, n);
  323. else
  324.                   x = SSL_write(tls_con, s, n);
  325. switch (SSL_get_error(ssl_active_flag?ssl_con:tls_con,x)) {
  326.   case SSL_ERROR_NONE:
  327.     break;
  328.   case SSL_ERROR_WANT_WRITE:
  329.   case SSL_ERROR_WANT_READ:
  330.     x = 0;
  331.     break;
  332.   case SSL_ERROR_SYSCALL:
  333.   case SSL_ERROR_WANT_X509_LOOKUP:
  334.   case SSL_ERROR_SSL:
  335.   case SSL_ERROR_ZERO_RETURN:
  336.   default:
  337.     ttclos(0);
  338.     return(-3);
  339. }
  340.     } else
  341. #endif /* CK_SSL */
  342. #ifdef RLOGCODE
  343. #ifdef CK_KERBEROS
  344. #ifdef KRB4
  345.     if (ttnproto == NP_EK4LOGIN) {
  346. return(krb4_des_write(ttyfd,s,n));
  347.     } else
  348. #endif /* KRB4 */
  349. #ifdef KRB5
  350.             if (ttnproto == NP_EK5LOGIN) {
  351.                 return(krb5_des_write(ttyfd,s,n));
  352.             } else
  353. #endif /* KRB5 */
  354. #endif /* CK_KERBEROS */
  355. #endif /* RLOGCODE */
  356.       x = write(fd,s,n); /* Write string to device */
  357. if (x == n) { /* Worked? */
  358.     debug(F101,"ttol ok","",x); /* OK */
  359. #ifdef CKXXCHAR
  360.     if (p) free(p);
  361. #endif /* CKXXCHAR */
  362.     return(len); /* Done */
  363. } else if (x < 0) { /* No, got error? */
  364.     debug(F101,"ttol write error","",errno);
  365. #ifdef EWOULDBLOCK
  366.     if (errno == EWOULDBLOCK) {
  367. msleep(10);
  368. continue;
  369.     } else
  370. #endif /* EWOULDBLOCK */
  371. #ifdef TCPSOCKET
  372.     if (netconn && ttnet == NET_TCPB) {
  373. debug(F101,"ttol TCP error","",errno);
  374. ttclos(0); /* Close the connection. */
  375. x = -3;
  376.     }
  377. #endif /* TCPSOCKET */
  378. #ifdef CKXXCHAR
  379.     if (p) free(p);
  380. #endif /* CKXXCHAR */
  381.     return(x);
  382. } else { /* No error, so partial success */
  383.     debug(F101,"ttol partial","",x); /* This never happens */
  384.     s += x; /* Point to part not written yet */
  385.     n -= x; /* Adjust length */
  386.     if (x > 0) msleep(10); /* Wait 10 msec */
  387. } /* Go back and try again */
  388.     }
  389. #ifdef CKXXCHAR
  390.     if (p) free(p);
  391. #endif /* CKXXCHAR */
  392.     return(n < 1 ? len : -1); /* Return the results */
  393. }
  394. /*  T T O C  --  Output a character to the communication line  */
  395. /*
  396.  This function should only be used for interactive, character-mode operations,
  397.  like terminal connection, script execution, dialer i/o, where the overhead
  398.  of the signals and alarms does not create a bottleneck.
  399. */
  400. int
  401. #ifdef CK_ANSIC
  402. ttoc(char c)
  403. #else
  404. ttoc(c) char c;
  405. #endif /* CK_ANSIC */
  406. /* ttoc */ {
  407. #define TTOC_TMO 15 /* Timeout in case we get stuck */
  408.     int xx, fd;
  409.     if (ttyfd < 0) /* Check for not open. */
  410.       return(-1);
  411. #ifdef NETCMD
  412.     if (ttpipe)
  413.       fd = fdout;
  414.     else
  415. #endif /* NETCMD */
  416.       fd = ttyfd;
  417.     c &= 0xff;
  418.     /* debug(F101,"ttoc","",(CHAR) c); */
  419.     saval = signal(SIGALRM,timerh); /* Enable timer interrupt */
  420.     xx = alarm(TTOC_TMO); /* for this many seconds. */
  421.     if (xx < 0) xx = 0; /* Save old alarm value. */
  422.     /* debug(F101,"ttoc alarm","",xx); */
  423.     if (
  424. #ifdef CK_POSIX_SIG
  425. sigsetjmp(sjbuf,1)
  426. #else
  427. setjmp(sjbuf)
  428. #endif /* CK_POSIX_SIG */
  429. ) { /* Timer went off? */
  430. ttimoff(); /* Yes, cancel this alarm. */
  431. if (xx - TTOC_TMO > 0) alarm(xx - TTOC_TMO); /* Restore previous one */
  432.         /* debug(F100,"ttoc timeout","",0); */
  433. #ifdef NETCONN
  434. if (!netconn) {
  435. #endif /* NETCONN */
  436.     debug(F101,"ttoc timeout","",c);
  437.     if (ttflow == FLO_XONX) {
  438. debug(F101,"ttoc flow","",ttflow); /* Maybe we're xoff'd */
  439. #ifndef Plan9
  440. #ifdef POSIX
  441. /* POSIX way to unstick. */
  442. debug(F100,"ttoc tcflow","",tcflow(ttyfd,TCOON));
  443. #else
  444. #ifdef BSD4 /* Berkeley way to do it. */
  445. #ifdef TIOCSTART
  446. /* .... Used to be "ioctl(ttyfd, TIOCSTART, 0);".  Who knows? */
  447. {
  448.   int x = 0;
  449.   debug(F101,"ttoc TIOCSTART","",ioctl(ttyfd, TIOCSTART, &x));
  450. }
  451. #endif /* TIOCSTART */
  452. #endif /* BSD4 */
  453. /* Is there a Sys V way to do this? */
  454. #endif /* POSIX */
  455. #endif /* Plan9 */
  456.     }
  457. #ifdef NETCONN
  458.         }
  459. #endif /* NETCONN */
  460. return(-1); /* Return failure code. */
  461.     } else {
  462.         int rc;
  463. #ifdef BEOSORBEBOX
  464. #ifdef NETCONN
  465.         if (netconn && !ttpipe && !ttpty)
  466.   rc = nettoc(c);
  467.         else
  468. #endif /*  BEOSORBEBOX */
  469. #endif /* NETCONN */
  470. #ifdef CK_ENCRYPTION
  471.   if (TELOPT_ME(TELOPT_ENCRYPTION))
  472.     ck_tn_encrypt(&c,1);
  473. #endif /* CK_ENCRYPTION */
  474. #ifdef IBMX25
  475. /* riehm: maybe this isn't necessary after all. Test program
  476.  * worked fine with data being sent and retrieved with normal
  477.  * read's and writes!
  478.  */
  479. if (ttnet == NET_IX25)
  480.   rc = x25write(ttyfd,&c,1); /* as above for X25 streams */
  481. else
  482. #endif /* IBMX25 */
  483. #ifdef CK_SSL
  484.   if (ssl_active_flag || tls_active_flag) {
  485.       int error;
  486.       /* Write using SSL */
  487.       if (ssl_active_flag)
  488.                 rc = SSL_write(ssl_con, &c, 1);
  489.       else
  490.                 rc = SSL_write(tls_con, &c, 1);
  491.       switch (SSL_get_error(ssl_active_flag?ssl_con:tls_con,rc)){
  492. case SSL_ERROR_NONE:
  493.   break;
  494. case SSL_ERROR_WANT_WRITE:
  495. case SSL_ERROR_WANT_READ:
  496.   rc = 0;
  497.   break;
  498. case SSL_ERROR_SYSCALL:
  499. case SSL_ERROR_WANT_X509_LOOKUP:
  500. case SSL_ERROR_SSL:
  501. case SSL_ERROR_ZERO_RETURN:
  502. default:
  503.   ttclos(0);
  504.   return(-1);
  505.       }
  506.   } else
  507. #endif /* CK_SSL */
  508. #ifdef RLOGCODE
  509. #ifdef CK_KERBEROS
  510. #ifdef KRB4
  511.   if (ttnproto == NP_EK4LOGIN) {
  512.       rc = (krb4_des_write(ttyfd,&c,1) == 1);
  513.   } else
  514. #endif /* KRB4 */
  515. #ifdef KRB5
  516.           if (ttnproto == NP_EK5LOGIN) {
  517.               rc = (krb5_des_write(ttyfd,&c,1) == 1);
  518.           } else
  519. #endif /* KRB5 */
  520. #endif /* CK_KERBEROS */
  521. #endif /* RLOGCODE */
  522.     rc = write(fd,&c,1); /* Try to write the character. */
  523. if (rc < 1) { /* Failed */
  524.     ttimoff(); /* Turn off the alarm. */
  525.     alarm(xx); /* Restore previous alarm. */
  526.     debug(F101,"ttoc errno","",errno); /* Log the error, */
  527.     return(-1); /* and return the error code. */
  528. }
  529.     }
  530.     ttimoff(); /* Success, turn off the alarm. */
  531.     alarm(xx); /* Restore previous alarm. */
  532.     return(0); /* Return good code. */
  533. }
  534. /*  T T I N L  --  Read a record (up to break character) from comm line.  */
  535. /*
  536.   Reads up to "max" characters from the communication line, terminating on:
  537.     (a) the packet length field if the "turn" argument is zero, or
  538.     (b) on the packet-end character (eol) if the "turn" argument is nonzero
  539.     (c) a certain number of Ctrl-C's in a row
  540.   Returns:
  541.     >= 0, the number of characters read upon success;
  542.     -1 if "max" exceeded, timeout, or other correctable error;
  543.     -2 on user interruption (c);
  544.     -3 on fatal error like connection lost.
  545.   The characters that were input are copied into "dest" with their parity bits
  546.   stripped if parity was selected.  Returns the number of characters read.
  547.   Characters after the eol are available upon the next call to this function.
  548.   The idea is to minimize the number of system calls per packet, and also to
  549.   minimize timeouts.  This function is the inner loop of the protocol and must
  550.   be as efficient as possible.  The current strategy is to use myread().
  551.   WARNING: This function calls parchk(), which is defined in another module.
  552.   Normally, ckutio.c does not depend on code from any other module, but there
  553.   is an exception in this case because all the other ck?tio.c modules also
  554.   need to call parchk(), so it's better to have it defined in a common place.
  555. */
  556. #ifdef CTRLC
  557. #undef CTRLC
  558. #endif /* CTRLC */
  559. #define CTRLC '3'
  560. /*
  561.   We have four different declarations here because:
  562.   (a) to allow Kermit to be built without the automatic parity sensing feature
  563.   (b) one of each type for ANSI C, one for non-ANSI.
  564. */
  565. static int csave = -1;
  566. #ifndef NOXFER
  567. int
  568. #ifdef PARSENSE
  569. #ifdef CK_ANSIC
  570. ttinl(CHAR *dest, int max,int timo, CHAR eol, CHAR start, int turn)
  571. #else
  572. ttinl(dest,max,timo,eol,start,turn) int max,timo,turn; CHAR *dest, eol, start;
  573. #endif /* CK_ANSIC */
  574. #else /* not PARSENSE */
  575. #ifdef CK_ANSIC
  576. ttinl(CHAR *dest, int max,int timo, CHAR eol)
  577. #else
  578. ttinl(dest,max,timo,eol) int max,timo; CHAR *dest, eol;
  579. #endif /* __SDTC__ */
  580. #endif /* PARSENSE */
  581. /* ttinl */ {
  582. #ifndef MYREAD
  583.     CHAR ch, dum;
  584. #endif /* MYREAD */
  585. #ifdef PARSENSE
  586.     int pktlen = -1;
  587.     int lplen = 0;
  588.     int havelen = 0;
  589. #endif /* PARSENSE */
  590.     int cc = 0; /* Character count */
  591.     int fd;
  592.     int sopmask = 0xff; /* Start-Of-Packet mask */
  593. #ifdef CKXXCHAR
  594.     extern short dblt[]; /* Ignore-character table */
  595.     extern int ignflag;
  596. #endif /* CKXXCHAR */
  597. #ifdef TCPSOCKET
  598.     extern CHAR stchr;
  599. #endif /* TCPSOCKET */
  600.     int x;
  601.     if (ttyfd < 0) return(-3);          /* Not open. */
  602.     debug(F101,"ttinl max","",max);
  603.     debug(F101,"ttinl timo","",timo);
  604. #ifdef NETCMD
  605.     if (ttpipe)
  606.       fd = fdin;
  607.     else
  608. #endif /* NETCMD */
  609.       fd = ttyfd;
  610. #ifdef COMMENT
  611.     if (xlocal && conchk() > 0) /* Allow for console interruptions */
  612.       return(-1);
  613. #endif /* COMMENT */
  614.     *dest = '';                       /* Clear destination buffer */
  615.     if (timo < 0) timo = 0; /* Safety */
  616.     if (timo) { /* Don't time out if timo == 0 */
  617. int xx;
  618. saval = signal(SIGALRM,timerh); /* Enable timer interrupt */
  619. xx = alarm(timo); /* Set it. */
  620. debug(F101,"ttinl alarm","",xx);
  621.     }
  622.     if (
  623. #ifdef CK_POSIX_SIG
  624. sigsetjmp(sjbuf,1)
  625. #else
  626. setjmp(sjbuf)
  627. #endif /* CK_POSIX_SIG */
  628. ) { /* Timer went off? */
  629. debug(F100,"ttinl timout","",0); /* Get here on timeout. */
  630. /* debug(F110," with",(char *) dest,0); */
  631. ttimoff(); /* Turn off timer */
  632. return(-1); /* and return error code. */
  633.     } else {
  634. register int i, n; /* local variables */
  635. int ccn = 0;
  636. #ifdef PARSENSE
  637. register int flag = 0;
  638. debug(F000,"ttinl start","",start);
  639. #endif /* PARSENSE */
  640. ttpmsk = ttprty ? 0177 : 0377; /* Set parity stripping mask. */
  641. sopmask = needpchk ? 0177 : ttpmsk; /* And SOP matching mask. */
  642. /* Now read into destination, stripping parity and looking for the */
  643. /* the packet terminator, and also for several Ctrl-C's typed in a row. */
  644. i = 0; /* Destination index */
  645. debug(F101,"ttinl eol","",eol);
  646. while (i < max-1) {
  647. #ifdef MYREAD
  648.     /* debug(F101,"ttinl i","",i); */
  649.     errno = 0;
  650.     if (csave > -1) {
  651.         n = csave;
  652. debug(F101,"ttinl unsaving","",n);
  653.     } else
  654. #ifdef COMMENT
  655.       if (xlocal && conchk() > 0) {
  656.   /* Here we could catch keyboard interruptions. */
  657.   /* But this would be VERY expensive. */
  658.   /* We could also do it in myread() but it would be */
  659.   /* expensive there too -- even if done with select()... */
  660.       }
  661. #endif /* COMMENT */
  662.       if ((n = myread()) < 0) { /* Timeout or i/o error? */
  663. #ifdef DEBUG
  664. if (deblog) {
  665.     debug(F101,"ttinl myread failure, n","",n);
  666.     debug(F101,"ttinl myread errno","",errno);
  667. }
  668. #endif /* DEBUG */
  669. /* Don't let EINTR break packets. */
  670. if (n == -3) {
  671.     if (errno == EINTR && i > 0) {
  672. debug(F111,"ttinl EINTR myread i","continuing",i);
  673. continue;
  674.     } else {
  675. debug(F110,"ttinl non-EINTR -3","closing",0);
  676. wasclosed = 1;
  677. ttimoff(); /* Turn off timer */
  678. ttclos(0);
  679. return(n);
  680.     }
  681. } else if (n == -2 && netconn /* && timo == 0 */ ) {
  682.     /* Here we try to catch broken network connections */
  683.     /* even when ioctl() and read() do not catch them */
  684.     debug(F111,"ttinl network myread failure","closing",n);
  685.     wasclosed = 1;
  686.     ttimoff();
  687.     ttclos(0);
  688.     return(-3);
  689. }
  690. break; /* Break out of while loop */
  691.     }
  692. #else /* not MYREAD (is this code used anywhere any more?) */
  693.     if (csave > -1) /* Char saved from last time */
  694.       ch = csave;
  695.     else if ((n = read(fd, &ch, 1)) < 1)
  696.       break; /* Error - break out of while loop */
  697.     n = ch;
  698. #endif /* MYREAD */
  699.     /* Get here with char in n */
  700. #ifdef CK_ENCRYPTION
  701.     /* If csave > -1 we already decrypted this character */
  702.     /* So don't decrypt it again */
  703.     if (TELOPT_U(TELOPT_ENCRYPTION) && csave == -1) {
  704. CHAR ch = n;
  705. ck_tn_decrypt(&ch,1);
  706. n = ch;
  707.     }
  708. #endif /* CK_ENCRYPTION */
  709.     csave = -1; /* Unflag that we unsaved a char */
  710. #ifdef TCPSOCKET
  711.     if (n == IAC && /* Handle Telnet options */
  712. ((xlocal && netconn && (ttnproto == NP_TELNET)) ||
  713. (!xlocal && sstelnet))) {
  714. n = tt_tnopt(n);
  715. if (n < 0)
  716.   return(n);
  717. else if (n == 1)
  718.   start = stchr;
  719. if (n != 255) /* No data - go back for next char */
  720.   continue;
  721.     } /* Quoted IAC - keep going */
  722. #endif /* TCPSOCKET */
  723. #ifdef CKXXCHAR
  724.     if (ignflag)
  725.       if (dblt[(unsigned) n] & 1) /* Character to ignore? */
  726. continue;
  727. #endif /* CKXXCHAR */
  728. /*
  729.   Use parity mask, rather than always stripping parity, to check for
  730.   cancellation.  Otherwise, runs like x03x83x03 in a packet could cancel
  731.   the transfer when parity is NONE.  (Note that x03x03x03 is extremely
  732.   unlikely due to run-length encoding.)
  733. */
  734.     /* Check cancellation */
  735.     if (!xlocal && xfrcan && ((n & ttpmsk) == xfrchr)) {
  736. if (++ccn >= xfrnum) { /* If xfrnum in a row, bail out. */
  737.     if (timo) { /* Clear timer. */
  738. ttimoff();
  739.     }
  740.     if (xfrchr < 32)
  741.       printf("^%c...rn",(char)(xfrchr+64));
  742.     else
  743.       printf("Canceled...rn");
  744.     return(-2);
  745. }
  746.     } else ccn = 0; /* No cancellation, reset counter, */
  747. #ifdef PARSENSE
  748.     if (flag == 0) { /* Find the Start-Of-Packet. */
  749. if ((n & sopmask) == start) { /* Got it */
  750.     flag = 1;
  751. } else { /* Keep looking... */
  752.     debug(F000,"ttinl skipping","",n);
  753.     continue;
  754. }
  755.     }
  756.     dest[i++] = n & ttpmsk;
  757. /*
  758.   If we have not been instructed to wait for a turnaround character, we
  759.   can go by the packet length field.  If turn != 0, we must wait for the
  760.   end of line (eol) character before returning.  This is an egregious
  761.   violation of all principles of layering...
  762. */
  763.     if (!havelen) {
  764. if (i == 2) {
  765.     pktlen = xunchar(dest[1] & 0x7f);
  766.     if (pktlen > 1) {
  767. havelen = 1;
  768. debug(F101,"ttinl length","",pktlen);
  769.     }
  770. } else if (i == 5 && pktlen == 0) {
  771.     lplen = xunchar(dest[4] & 0x7f);
  772. } else if (i == 6 && pktlen == 0) {
  773.     pktlen = lplen * 95 + xunchar(dest[5] & 0x7f) + 5;
  774.     havelen = 1;
  775.     debug(F101,"ttinl extended length","",pktlen);
  776. }
  777.     }
  778. /*
  779.   Suppose we looked at the sequence number here and found it was out of
  780.   range?  This would mean either (a) incoming packets had SOP unprefixed
  781.   and we are out of sync, or (b) the packet is damaged.  Since (a) is bad
  782.   practice, let's ignore it.  So what should we do here if we know the
  783.   packet is damaged?
  784.    1. Nothing -- keep trying to read the packet till we find what we think
  785.       is the end, or we time out, and let the upper layer decide what to
  786.       do.  But since either the packet is corrupt or we are out of sync,
  787.       our criterion for finding the end does not apply and we are likely
  788.       to time out (or swallow a piece of the next packet) if our assumed
  789.       length is too long.  (This was the behavior prior to version 7.0.)
  790.    2. set flag = 0 and continue?  This would force us to wait for the
  791.       next packet to come in, and therefore (in the nonwindowing case),
  792.       would force a timeout in the other Kermit.
  793.    3. set flag = 0 and continue, but only if the window size is > 1 and
  794.       the window is not blocked?  Talk about cheating!
  795.    4. Return a failure code and let the upper layer decide what to do.
  796.       This should be equivalent to 3, but without the cheating.  So let's
  797.       do it that way...
  798. */
  799.     if (i == 3) { /* Peek at sequence number */
  800. x = xunchar(dest[i-1]); /* If it's not in range... */
  801. if (x < 0 || x > 63) {
  802.     debug(F111,"ttinl bad seq",dest,x);
  803.     if (timo) ttimoff();
  804.     return(-1); /* return a nonfatal error */
  805. }
  806.     }
  807. #else /* PARSENSE */
  808.     dest[i++] = n & ttpmsk;
  809. #endif /* PARSENSE */
  810.     /* Check for end of packet */
  811.     if (
  812. #ifdef PARSENSE
  813. /*
  814.   Purely length-driven if SET HANDSHAKE NONE (i.e. turn == 0).
  815.   This allows packet terminators and handshake characters to appear
  816.   literally inside a packet data field.
  817. */
  818. (havelen && (i > pktlen+1) &&
  819.  (!turn || (turn && (n & 0x7f) == turn))) /* (turn, not eol) */
  820. #else /* !PARSENSE */
  821. /*
  822.   Built without PARSENSE, so just look for packet terminator.
  823. */
  824. ((n & 0x7f) == eol)
  825. #endif /* PARSENSE */
  826. ) {
  827. #ifndef PARSENSE
  828. debug(F101,"ttinl got eol","",eol); /* (or turn) */
  829. dest[i] = ''; /* Yes, terminate the string, */
  830. /* debug(F101,"ttinl i","",i); */
  831. #else
  832. #ifdef DEBUG
  833. if (deblog) {
  834.     if ((n & 0x7f) != eol) {
  835. debug(F101,"ttinl EOP length","",pktlen);
  836. debug(F101,"ttinl i","",i);
  837. #ifdef MYREAD
  838. #ifdef PARSENSE
  839. /*
  840.   We read a packet based on its length.  This leaves the EOP character still
  841.   unread, and so ttchk() will always return at least 1 because of this.  But
  842.   if we know it is there, we can safely get rid of it.  So...
  843. */
  844. {
  845.     int x;
  846.     while (my_count > 0) {
  847. x = ttinc(0);
  848. /* Start of next packet */
  849. if (x == start) { /* Save for next time */
  850.     csave = (unsigned)((unsigned)x & 0xff);
  851.     debug(F000,"ttinl csaved","",x);
  852.     break;
  853. }
  854. debug(F000,"ttinl removed","",x);
  855.     }
  856. }
  857. #endif /* PARSENSE */
  858. #endif /* MYREAD */
  859.     } else debug(F101,"ttinl got eol","",eol); /* (or turn) */
  860. }
  861. #endif /* DEBUG */
  862. dest[i] = ''; /* Terminate the string, */
  863.         if (needpchk) { /* Parity checked yet? */
  864.     if (ttprty == 0) { /* No, check. */
  865. if ((ttprty = parchk(dest,start,i)) > 0) {
  866.     int j;
  867.     debug(F101,"ttinl senses parity","",ttprty);
  868.     debug(F110,"ttinl packet before",dest,0);
  869.     ttpmsk = 0x7f;
  870.     for (j = 0; j < i; j++)
  871.       dest[j] &= 0x7f; /* Strip parity from packet */
  872.     debug(F110,"ttinl packet after ",dest,0);
  873. } else ttprty = 0; /* Restore if parchk error */
  874.     }
  875.     sopmask = ttprty;
  876.     needpchk = 0;
  877. }
  878. #endif /* PARSENSE */
  879. if (timo) { /* Turn off timer. */
  880.     ttimoff();
  881. }
  882. debug(F011,"ttinl got", dest, (i < 60) ? i : -60);
  883. return(i);
  884.     }
  885. } /* End of while() */
  886. ttimoff();
  887. return(n);
  888.     }
  889. }
  890. #endif /* NOXFER */
  891. /*  T T I N C --  Read a character from the communication line  */
  892. /*
  893.  On success, returns the character that was read, >= 0.
  894.  On failure, returns -1 or other negative myread error code,
  895.    or -2 if connection is broken or ttyfd < 0.
  896.    or -3 if session limit has expired,
  897.    or -4 if something or other...
  898.  NOTE: The API does not provide for ttinc() returning a special code
  899.  upon timeout, but we need it.  So for this we have a global variable,
  900.  ttinctimo.
  901. */
  902. static int ttinctimo = 0; /* Yuk */
  903. int
  904. ttinc(timo) int timo; {
  905.     int n = 0, fd;
  906.     int is_tn = 0;
  907.     CHAR ch = 0;
  908.     ttinctimo = 0;
  909.     if (ttyfd < 0) return(-2);          /* Not open. */
  910.     is_tn = (xlocal && netconn && ttnproto == NP_TELNET) ||
  911.     (!xlocal && sstelnet);
  912. #ifdef TTLEBUF
  913.     if (ttpush >= 0) {
  914.         debug(F111,"ttinc","ttpush",ttpush);
  915.         ch = ttpush;
  916.         ttpush = -1;
  917.         return(ch);
  918.     }
  919.     if (le_data) {
  920.         if (le_getchar(&ch) > 0) {
  921.             debug(F111,"ttinc le_getchar","ch",ch);
  922.             return(ch);
  923.         }
  924.     }
  925. #endif /* TTLEBUF */
  926. #ifdef NETCMD
  927.     if (ttpipe)
  928.       fd = fdin;
  929.     else
  930. #endif /* NETCMD */
  931.       fd = ttyfd;
  932.     if ((timo <= 0) /* Untimed. */
  933. #ifdef MYREAD
  934. || (my_count > 0) /* Buffered char already waiting. */
  935. #endif /* MYREAD */
  936. ) {
  937. #ifdef MYREAD
  938.         /* Comm line failure returns -1 thru myread, so no &= 0377 */
  939. n = myread(); /* Wait for a character... */
  940. /* debug(F000,"ttinc MYREAD n","",n); */
  941. #ifdef CK_ENCRYPTION
  942. /* debug(F101,"ttinc u_encrypt","",TELOPT_U(TELOPT_ENCRYPTION)); */
  943. if (TELOPT_U(TELOPT_ENCRYPTION) && n >= 0) {
  944.     ch = n;
  945.     ck_tn_decrypt(&ch,1);
  946.     n = ch;
  947. }
  948. #endif /* CK_ENCRYPTION */
  949. #ifdef NETPTY
  950. if (ttpty && n < 0) {
  951.     debug(F101,"ttinc error on pty","",n);
  952.     ttclos(0);
  953.     return(n);
  954. }
  955. #endif /* NETPTY */
  956. #ifdef TNCODE
  957. if ((n > -1) && is_tn)
  958.   return((unsigned)(n & 0xff));
  959. else
  960. #endif /* TNCODE */
  961.   return(n < 0 ? n : (unsigned)(n & ttpmsk));
  962. #else  /* MYREAD */
  963.         while ((n = read(fd,&ch,1)) == 0) /* Wait for a character. */
  964.         /* Shouldn't have to loop in ver 5A. */
  965. #ifdef NETCONN
  966.   if (netconn) { /* Special handling for net */
  967.       netclos(); /* If read() returns 0 it means */
  968.       netconn = 0; /* the connection has dropped. */
  969.       errno = ENOTCONN;
  970.       return(-2);
  971.   }
  972. #endif /* NETCONN */
  973.   ;
  974. /* debug(F101,"ttinc","",ch); */
  975. #ifdef TNCODE
  976. if ((n > 0) && is_tn) {
  977. #ifdef CK_ENCRYPTION
  978.     if (TELOPT_U(TELOPT_ENCRYPTION)) {
  979. ck_tn_decrypt(&ch,1);
  980. n = ch;
  981.     }
  982. #endif /* CK_ENCRYPTION */
  983.     return((unsigned)(ch & 0xff));
  984. } else
  985. #endif /* TNCODE */
  986.         return((n < 0) ? -4 : ((n == 0) ? -1 : (unsigned)(ch & ttpmsk)));
  987. #endif /* MYREAD */
  988.     } else { /* Timed read */
  989. int oldalarm;
  990. saval = signal(SIGALRM,timerh); /* Set up handler, save old one. */
  991. oldalarm = alarm(timo); /* Set alarm, save old one. */
  992. if (
  993. #ifdef CK_POSIX_SIG
  994.     sigsetjmp(sjbuf,1)
  995. #else
  996.     setjmp(sjbuf)
  997. #endif /* CK_POSIX_SIG */
  998.     ) { /* Timer expired */
  999.     ttinctimo = 1;
  1000.     n = -1; /* set flag */
  1001. } else {
  1002. #ifdef MYREAD
  1003.     n = myread(); /* If managing own buffer... */
  1004.     debug(F101,"ttinc myread","",n);
  1005.     ch = n;
  1006. #else
  1007.     n = read(fd,&ch,1); /* Otherwise call the system. */
  1008.     if (n == 0) n = -1;
  1009.     debug(F101,"ttinc read","",n);
  1010. #endif /* MYREAD */
  1011. #ifdef CK_ENCRYPTION
  1012.     if (TELOPT_U(TELOPT_ENCRYPTION) && n >= 0) {
  1013. ck_tn_decrypt(&ch,1);
  1014.     }
  1015. #endif /* CK_ENCRYPTION */
  1016.     if (n >= 0)
  1017.       n = (unsigned) (ch & 0xff);
  1018.     else
  1019.       n = (n < 0) ? -4 : -2; /* Special return codes. */
  1020. }
  1021. ttimoff(); /* Turn off the timer */
  1022. if (oldalarm > 0) {
  1023.     if (n == -1) /* and restore any previous alarm */
  1024.       oldalarm -= timo;
  1025.     if (oldalarm < 0) /* adjusted by our timeout interval */
  1026.       oldalarm = 0;
  1027.     if (oldalarm) {
  1028.         debug(F101,"ttinc restoring oldalarm","",oldalarm);
  1029. alarm(oldalarm);
  1030.     }
  1031. }
  1032. #ifdef NETCONN
  1033. if (netconn) {
  1034.     if (n == -2) { /* read() returns 0 */
  1035. netclos(); /* on network read failure */
  1036. netconn = 0;
  1037. errno = ENOTCONN;
  1038.     }
  1039. }
  1040. #endif /* NETCONN */
  1041. #ifdef TNCODE
  1042. if ((n > -1) && is_tn)
  1043.   return((unsigned)(n & 0xff));
  1044. else
  1045. #endif /* TNCODE */
  1046.   /* Return masked char or neg. */
  1047.   return( (n < 0) ? n : (unsigned)(n & ttpmsk) );
  1048.     }
  1049. }
  1050. /*  S N D B R K  --  Send a BREAK signal of the given duration  */
  1051. static int
  1052. #ifdef CK_ANSIC
  1053. sndbrk(int msec) { /* Argument is milliseconds */
  1054. #else
  1055. sndbrk(msec) int msec; {
  1056. #endif /* CK_ANSIC */
  1057. #ifndef POSIX
  1058.     int x, n;
  1059. #endif /* POSIX */
  1060. #ifdef OXOS
  1061. #define BSDBREAK
  1062. #endif /* OXOS */
  1063. #ifdef ANYBSD
  1064. #define BSDBREAK
  1065. #endif /* ANYBSD */
  1066. #ifdef BSD44
  1067. #define BSDBREAK
  1068. #endif /* BSD44 */
  1069. #ifdef COHERENT
  1070. #ifdef BSDBREAK
  1071. #undef BSDBREAK
  1072. #endif /* BSDBREAK */
  1073. #endif /* COHERENT */
  1074. #ifdef BELLV10
  1075. #ifdef BSDBREAK
  1076. #undef BSDBREAK
  1077. #endif /* BSDBREAK */
  1078. #endif /* BELLV10 */
  1079. #ifdef PROVX1
  1080.     char spd;
  1081. #endif /* PROVX1 */
  1082.     debug(F101,"ttsndb ttyfd","",ttyfd);
  1083.     if (ttyfd < 0) return(-1);          /* Not open. */
  1084. #ifdef Plan9
  1085.     return p9sndbrk(msec);
  1086. #else
  1087. #ifdef NETCONN
  1088. #ifdef NETCMD
  1089.     if (ttpipe) /* Pipe */
  1090.       return(ttoc(''));
  1091. #endif /* NETCMD */
  1092. #ifdef NETPTY
  1093.     if (ttpty)
  1094.       return(ttoc(''));
  1095. #endif /* NETPTY */
  1096.     if (netconn)  /* Send network BREAK */
  1097.       return(netbreak());
  1098. #endif /* NETCONN */
  1099.     if (msec < 1 || msec > 5000) return(-1); /* Bad argument */
  1100. #ifdef POSIX /* Easy in POSIX */
  1101.     debug(F101,"sndbrk POSIX","",msec);
  1102.     return(tcsendbreak(ttyfd,msec / 375));
  1103. #else
  1104. #ifdef PROVX1
  1105.     gtty(ttyfd,&ttbuf);                 /* Get current tty flags */
  1106.     spd = ttbuf.sg_ospeed;              /* Save speed */
  1107.     ttbuf.sg_ospeed = B50;              /* Change to 50 baud */
  1108.     stty(ttyfd,&ttbuf);                 /*  ... */
  1109.     n = (int)strlen(brnuls); /* Send the right number of nulls */
  1110.     x = msec / 91;
  1111.     if (x > n) x = n;
  1112.     write(ttyfd,brnuls,n);
  1113.     ttbuf.sg_ospeed = spd;              /* Restore speed */
  1114.     stty(ttyfd,&ttbuf);                 /*  ... */
  1115.     return(0);
  1116. #else
  1117. #ifdef aegis
  1118.     sio_$control((short)ttyfd, sio_$send_break, msec, st);
  1119.     return(0);
  1120. #else
  1121. #ifdef BSDBREAK
  1122.     n = FWRITE;                         /* Flush output queue. */
  1123. /* Watch out for int vs long problems in &n arg! */
  1124.     debug(F101,"sndbrk BSDBREAK","",msec);
  1125.     ioctl(ttyfd,TIOCFLUSH,&n);          /* Ignore any errors.. */
  1126.     if (ioctl(ttyfd,TIOCSBRK,(char *)0) < 0) {  /* Turn on BREAK */
  1127.         perror("Can't send BREAK");
  1128.         return(-1);
  1129.     }
  1130.     x = msleep(msec);                    /* Sleep for so many milliseconds */
  1131.     if (ioctl(ttyfd,TIOCCBRK,(char *)0) < 0) {  /* Turn off BREAK */
  1132.         perror("BREAK stuck!!!");
  1133.         doexit(BAD_EXIT,-1); /* Get out, closing the line. */
  1134.                                         /*   with bad exit status */
  1135.     }
  1136.     return(x);
  1137. #else
  1138. #ifdef ATTSV
  1139. /*
  1140.   No way to send a long BREAK in Sys V, so send a bunch of regular ones.
  1141.   (Actually, Sys V R4 is *supposed* to have the POSIX tcsendbreak() function,
  1142.   but there's no way for this code to know for sure.)
  1143. */
  1144.     debug(F101,"sndbrk ATTSV","",msec);
  1145.     x = msec / 275;
  1146.     for (n = 0; n < x; n++) {
  1147. /* Reportedly the cast breaks this function on some systems */
  1148. /* But then why was it here in the first place? */
  1149. if (ioctl(ttyfd,TCSBRK, /* (char *) */ 0) < 0) {
  1150.     perror("Can't send BREAK");
  1151.     return(-1);
  1152. }
  1153.     }
  1154.     return(0);
  1155. #else
  1156. #ifdef  V7
  1157.     debug(F101,"sndbrk V7","",msec);
  1158.     return(genbrk(ttyfd,250)); /* Simulate a BREAK */
  1159. #else
  1160.     debug(F101,"sndbrk catchall","",msec);
  1161.     ttoc(0);ttoc(0);ttoc(0);ttoc(0);
  1162.     return(0);
  1163. #endif /* V7 */
  1164. #endif /* BSDBREAK */
  1165. #endif /* ATTSV */
  1166. #endif /* aegis */
  1167. #endif /* PROVX1 */
  1168. #endif /* POSIX */
  1169. #endif /* Plan9 */
  1170. }
  1171. /*  T T S N D B  --  Send a BREAK signal  */
  1172. int
  1173. ttsndb() {
  1174.     return(sndbrk(275));
  1175. }
  1176. /*  T T S N D L B  --  Send a Long BREAK signal  */
  1177. int
  1178. ttsndlb() {
  1179.     return(sndbrk(1500));
  1180. }
  1181. /*  M S L E E P  --  Millisecond version of sleep().  */
  1182. /*
  1183.   Call with number of milliseconds (thousandths of seconds) to sleep.
  1184.   Intended only for small intervals.  For big ones, just use sleep().
  1185.   Highly system-dependent.
  1186.   Returns 0 always, even if it didn't work.
  1187. */
  1188. /* Define MSLFTIME for systems that must use an ftime() loop. */
  1189. #ifdef ANYBSD /* For pre-4.2 BSD versions */
  1190. #ifndef BSD4
  1191. #define MSLFTIME
  1192. #endif /* BSD4 */
  1193. #endif /* ANYBSD */
  1194. #ifdef TOWER1 /* NCR Tower OS 1.0 */
  1195. #define MSLFTIME
  1196. #endif /* TOWER1 */
  1197. #ifdef COHERENT         /* Coherent... */
  1198. #ifndef _I386           /* Maybe Coherent/386 should get this, too */
  1199. #define MSLFTIME        /* Opinions are divided */
  1200. #endif /* _I386 */
  1201. #endif /* COHERENT */
  1202. #ifdef COMMENT
  1203. #ifdef GETMSEC
  1204. /* Millisecond timer */
  1205. static long msecbase = 0L; /* Unsigned long not portable */
  1206. long
  1207. getmsec() { /* Milliseconds since base time */
  1208.     struct timeval xv;
  1209.     struct timezone xz;
  1210.     long secs, msecs;
  1211.     if (
  1212. #ifdef GTODONEARG
  1213. gettimeofday(&tv)
  1214. #else
  1215. #ifdef PTX
  1216. gettimeofday(&tv, NULL)
  1217. #else
  1218. gettimeofday(&tv, &tz)
  1219. #endif /* PTX */
  1220. #endif /* GTODONEARG */
  1221. < 0)
  1222.       return(-1);
  1223.     if (msecbase == 0L) { /* First call, set base time. */
  1224. msecbase = tv.tv_sec;
  1225. debug(F101,"getmsec base","",msecbase);
  1226.     }
  1227.     return(((tv.tv_sec - msecbase) * 1000L) + (tv.tv_usec / 1000L));
  1228. }
  1229. #endif /* GETMSEC */
  1230. #endif /* COMMENT */
  1231. #ifdef SELECT
  1232. int
  1233. ttwait(fd, secs) int fd, secs; {
  1234.     int x;
  1235.     fd_set rfds;
  1236.     FD_ZERO(&rfds);
  1237.     FD_SET(fd,&rfds);
  1238.     tv.tv_sec = secs;
  1239.     tv.tv_usec = 0L;
  1240.     errno = 0;
  1241.     if ((x = select(FD_SETSIZE,
  1242. #ifdef HPUX9
  1243.     (int *)
  1244. #else
  1245. #ifdef HPUX1000
  1246.     (int *)
  1247. #endif /* HPUX1000 */
  1248. #endif /* HPUX9 */
  1249.     &rfds,
  1250.     0, 0, &tv)) < 0) {
  1251. debug(F101,"ttwait select errno","",errno);
  1252. return(0);
  1253.     } else {
  1254. debug(F101,"ttwait OK","",errno);
  1255. x = FD_ISSET(fd, &rfds);
  1256. debug(F101,"ttwait select x","",x);
  1257. return(x ? 1 : 0);
  1258.     }
  1259. }
  1260. #endif /* SELECT */
  1261. int
  1262. msleep(m) int m; {
  1263. /*
  1264.   Other possibilities here are:
  1265.    nanosleep(), reportedly defined in POSIX.4.
  1266.    sginap(), IRIX only (back to what IRIX version I don't know).
  1267. */
  1268. #ifdef Plan9
  1269.     return _SLEEP(m);
  1270. #else
  1271. #ifdef BEOSORBEBOX
  1272.     snooze(m*1000);
  1273. #else /* BEOSORBEBOX */
  1274. #ifdef SELECT
  1275.     int t1, x;
  1276.     debug(F101,"msleep SELECT 1","",m);
  1277.     if (m <= 0) return(0);
  1278.     if (m >= 1000) { /* Catch big arguments. */
  1279. sleep(m/1000);
  1280. m = m % 1000;
  1281. if (m < 10) return(0);
  1282.     }
  1283.     debug(F101,"msleep SELECT 2","",m);
  1284. #ifdef BELLV10
  1285.     x = select( 0, (fd_set *)0, (fd_set *)0, (fd_set *)0, m );
  1286.     debug(F101,"msleep BELLV10 select","",x);
  1287. #else /* BELLV10 */
  1288. #ifdef HPUX9
  1289.     gettimeofday(&tv, &tz);
  1290. #else
  1291. #ifndef COHERENT
  1292. #ifdef GTODONEARG
  1293.     if (gettimeofday(&tv) < 0)
  1294. #else
  1295. #ifdef PTX
  1296.     if (gettimeofday(&tv,NULL) < 0)
  1297. #else
  1298.     if (gettimeofday(&tv, &tz) < 0)
  1299. #endif /* PTX */
  1300. #endif /* GTODONEARG */
  1301.       return(-1);
  1302.     t1 = tv.tv_sec;                     /* Seconds */
  1303. #endif /* COHERENT */
  1304. #endif /* HPUX9 */
  1305.     tv.tv_sec = 0;                      /* Use select() */
  1306.     tv.tv_usec = m * 1000L;
  1307. #ifdef BSD44
  1308.     x = select( 0, (fd_set *)0, (fd_set *)0, (fd_set *)0, &tv );
  1309.     debug(F101,"msleep BSD44 select","",x);
  1310. #else /* BSD44 */
  1311. #ifdef __linux__
  1312.     x = select( 0, (fd_set *)0, (fd_set *)0, (fd_set *)0, &tv );
  1313.     debug(F101,"msleep __linux__ select","",x);
  1314. #else /* __linux__ */
  1315. #ifdef BSD43
  1316.     x = select( 0, (fd_set *)0, (fd_set *)0, (fd_set *)0, &tv );
  1317.     debug(F101,"msleep BSD43 select","",x);
  1318. #else /* BSD43 */
  1319. #ifdef QNX
  1320.     x = select( 0, (fd_set *)0, (fd_set *)0, (fd_set *)0, &tv );
  1321.     debug(F101,"msleep QNX select","",x);
  1322. #else /* QNX */
  1323. #ifdef COHERENT
  1324.     x = select( 0, (fd_set *)0, (fd_set *)0, (fd_set *)0, &tv );
  1325.     debug(F101,"msleep COHERENT select","",x);
  1326. #else /* COHERENT */
  1327. #ifdef HPUX1000 /* 10.00 only, not 10.10 or later */
  1328.     x = select( 0, (int *)0, (int *)0, (int *)0, &tv );
  1329.     debug(F101,"msleep HP-UX 10.00 select","",x);
  1330. #else /* HPUX1000 */
  1331. #ifdef SVR4
  1332.     x = select( 0, (fd_set *)0, (fd_set *)0, (fd_set *)0, &tv );
  1333.     debug(F101,"msleep SVR4 select","",x);
  1334. #else /* SVR4 */
  1335. #ifdef OSF40
  1336.     x = select( 0, (fd_set *)0, (fd_set *)0, (fd_set *)0, &tv );
  1337.     debug(F101,"msleep OSF40 select","",x);
  1338. #else /* OSF40 */
  1339. #ifdef PTX
  1340.     x = select( 0, (fd_set *)0, (fd_set *)0, (fd_set *)0, &tv );
  1341.     debug(F101,"msleep OSF40 select","",x);
  1342. #else
  1343.     x = select( 0, (int *)0, (int *)0, (int *)0, &tv );
  1344.     debug(F101,"msleep catch-all select","",x);
  1345. #endif /* PTX */
  1346. #endif /* OSF40 */
  1347. #endif /* HP1000 */
  1348. #endif /* SVR4 */
  1349. #endif /* COHERENT */
  1350. #endif /* QNX */
  1351. #endif /* BSD43 */
  1352. #endif /* __linux__ */
  1353. #endif /* BSD44 */
  1354. #endif /* BELLV10 */
  1355.     return(0);
  1356. #else /* Not SELECT */
  1357. #ifdef CK_POLL /* We have poll() */
  1358.     struct pollfd pfd; /* Supply a valid address for poll() */
  1359. #ifdef ODT30 /* But in SCO ODT 3.0 */
  1360. #ifdef NAP /* we should use nap() instead */
  1361.     debug(F101,"msleep ODT 3.0 NAP","",m); /* because using poll() here */
  1362.     nap((long)m);    /* seems to break dialing. */
  1363.     return(0);
  1364. #else
  1365.     debug(F101,"msleep ODT 3.0 POLL","",m);
  1366.     poll(&pfd, 0, m);
  1367.     return(0);
  1368. #endif /* NAP */
  1369. #else
  1370.     debug(F101,"msleep POLL","",m);
  1371.     poll(&pfd, 0, m);
  1372.     return(0);
  1373. #endif /* ODT30 */
  1374. /*
  1375.   We could handle the above more cleanly by just letting nap() take
  1376.   always take precedence over poll() in this routine, but there is no way
  1377.   to know whether that would break something else.
  1378. */
  1379. #else /* Not POLL */
  1380. #ifdef USLEEP
  1381. /*
  1382.   "This routine is implemented using setitimer(2); it requires eight
  1383.   system calls...".  In other words, it might take 5 minutes to sleep
  1384.   10 milliseconds...
  1385. */
  1386.     debug(F101,"msleep USLEEP","",m);
  1387.     if (m >= 1000) { /* Catch big arguments. */
  1388. sleep(m/1000);
  1389. m = m % 1000;
  1390. if (m < 10) return(0);
  1391.     }
  1392.     usleep((unsigned int)(m * 1000));
  1393.     return(0);
  1394. #else
  1395. #ifdef aegis
  1396.     time_$clock_t dur;
  1397.     debug(F101,"msleep aegis","",m);
  1398.     dur.c2.high16 = 0;
  1399.     dur.c2.low32  = 250 * m; /* one millisecond = 250 four microsecond ticks */
  1400.     time_$wait(time_$relative, dur, st);
  1401.     return(0);
  1402. #else
  1403. #ifdef PROVX1
  1404.     debug(F101,"msleep Venix","",m);
  1405.     if (m <= 0) return(0);
  1406.     sleep(-((m * 60 + 500) / 1000));
  1407.     return(0);
  1408. #else
  1409. #ifdef NAP
  1410.     debug(F101,"msleep NAP","",m);
  1411.     nap((long)m);
  1412.     return(0);
  1413. #else
  1414. #ifdef ATTSV
  1415. #ifndef BSD44
  1416.     extern long times(); /* Or #include <times.h> ? */
  1417. #endif /* BSD44 */
  1418.     long t1, t2, tarray[4];
  1419.     int t3;
  1420.     char *cp = getenv("HZ");
  1421.     int CLOCK_TICK;
  1422.     int hertz;
  1423.     if (cp && (hertz = atoi(cp))) {
  1424.         CLOCK_TICK  = 1000 / hertz;
  1425.     } else { /* probably single user mode */
  1426. #ifdef HZ
  1427.         CLOCK_TICK  = 1000 / HZ;
  1428. #else
  1429. static warned = 0;
  1430. /* HZ always exists in, for instance, SCO Xenix, so you don't have to
  1431.  * make special #ifdefs for XENIX here, like in ver 4F. Also, if you
  1432.  * have Xenix, you have should have nap(), so the best is to use -DNAP
  1433.  * in the makefile. Most systems have HZ.
  1434.  */
  1435. CLOCK_TICK = 17; /* 1/60 sec */
  1436. if (!warned) {
  1437.           printf("warning: environment variable HZ bad... using HZ=%drn",
  1438.  1000 / CLOCK_TICK);
  1439.           warned = 1;
  1440. }
  1441. #endif /* !HZ */
  1442.     }
  1443.     debug(F101,"msleep ATTSV","",m);
  1444.     if (m <= 0) return(0);
  1445.     if (m >= 1000) { /* Catch big arguments. */
  1446. sleep(m/1000);
  1447. m = m % 1000;
  1448. if (m < 10) return(0);
  1449.     }
  1450.     if ((t1 = times(tarray)) < 0) return(-1);
  1451.     while (1) {
  1452.         if ((t2 = times(tarray)) < 0) return(-1);
  1453.         t3 = ((int)(t2 - t1)) * CLOCK_TICK;
  1454.         if (t3 > m) return(t3);
  1455.     }
  1456. #else /* Not ATTSV */
  1457. #ifdef MSLFTIME /* Use ftime() loop... */
  1458.     int t1, t3 = 0;
  1459.     debug(F101,"msleep MSLFTIME","",m);
  1460.     if (m <= 0) return(0);
  1461.     if (m >= 1000) { /* Catch big arguments. */
  1462. sleep(m/1000);
  1463. m = m % 1000;
  1464. if (m < 10) return(0);
  1465.     }
  1466. #ifdef QNX
  1467.     ftime(&ftp); /* void ftime() in QNX */
  1468. #else
  1469.     if (ftime(&ftp) < 0) return(-1); /* Get base time. */
  1470. #endif /* QNX */
  1471.     t1 = ((ftp.time & 0xff) * 1000) + ftp.millitm;
  1472.     while (1) {
  1473.         ftime(&ftp); /* Get current time and compare. */
  1474.         t3 = (((ftp.time & 0xff) * 1000) + ftp.millitm) - t1;
  1475.         if (t3 > m) return(0);
  1476.     }
  1477. #else
  1478. /* This includes true POSIX, which has no way to do this. */
  1479.     debug(F101,"msleep busy loop","",m);
  1480.     if (m >= 1000) { /* Catch big arguments. */
  1481. sleep(m/1000);
  1482. m = m % 1000;
  1483. if (m < 10) return(0);
  1484.     }
  1485.     if (m > 0) while (m > 0) m--; /* Just a dumb busy loop */
  1486.     return(0);
  1487. #endif /* MSLFTIME */
  1488. #endif /* ATTSV */
  1489. #endif /* NAP */
  1490. #endif /* PROVX1 */
  1491. #endif /* aegis */
  1492. #endif /* CK_POLL */
  1493. #endif /* SELECT */
  1494. #endif /* BEOSORBEBOX */
  1495. #endif /* USLEEP */
  1496. #endif /* Plan9 */
  1497. }
  1498. /*  R T I M E R --  Reset elapsed time counter  */
  1499. VOID
  1500. rtimer() {
  1501.     tcount = time( (time_t *) 0 );
  1502. }
  1503. /*  G T I M E R --  Get current value of elapsed time counter in seconds  */
  1504. int
  1505. gtimer() {
  1506.     int x;
  1507.     x = (int) (time( (time_t *) 0 ) - tcount);
  1508.     debug(F101,"gtimer","",x);
  1509.     return( (x < 0) ? 0 : x );
  1510. }
  1511. #ifdef GFTIMER
  1512. /*
  1513.   Floating-point timers.  Require not only floating point support, but
  1514.   also gettimeofday().
  1515. */
  1516. static struct timeval tzero;
  1517. VOID
  1518. rftimer() {
  1519. #ifdef GTODONEARG /* Account for Mot's definition */
  1520.     (VOID) gettimeofday(&tzero);
  1521. #else
  1522.     (VOID) gettimeofday(&tzero, (struct timezone *)0);
  1523. #endif /* GTODONEARG */
  1524. }
  1525. CKFLOAT
  1526. gftimer() {
  1527.     struct timeval tnow, tdelta;
  1528.     CKFLOAT s, sb;
  1529. #ifdef DEBUG
  1530.     char fpbuf[64];
  1531. #endif /* DEBUG */
  1532. #ifdef GTODONEARG /* Acount for Mot's definition */
  1533.     (VOID) gettimeofday(&tnow);
  1534. #else
  1535.     (VOID) gettimeofday(&tnow, (struct timezone *)0);
  1536. #endif /* GTODONEARG */
  1537.     tdelta.tv_sec = tnow.tv_sec - tzero.tv_sec;
  1538.     tdelta.tv_usec = tnow.tv_usec - tzero.tv_usec;
  1539.     if (tdelta.tv_usec < 0) {
  1540. tdelta.tv_sec--;
  1541. tdelta.tv_usec += 1000000;
  1542.     }
  1543.     s = (CKFLOAT) tdelta.tv_sec + ((CKFLOAT) tdelta.tv_usec / 1000000.0);
  1544.     if (s < GFMINTIME)
  1545.       s = GFMINTIME;
  1546. #ifdef DEBUG
  1547.     if (deblog) {
  1548. sprintf(fpbuf,"%f",s);
  1549. debug(F110,"gftimer",fpbuf,0);
  1550.     }
  1551. #endif /* DEBUG */
  1552.     return(s);
  1553. }
  1554. #endif /* GFTIMER */
  1555. /*  Z T I M E  --  Return asctime()-format date/time string  */
  1556. /*
  1557.   NOTE: as a side effect of calling this routine, we can also set the
  1558.   following two variables, giving the micro- and milliseconds (fractions of
  1559.   seconds) of the clock time.  Currently this is done only in BSD-based builds
  1560.   that use gettimeofday().  When these variables are not filled in, they are
  1561.   left with a value of -1L.
  1562. */
  1563. VOID
  1564. ztime(s) char **s; {
  1565. #ifdef GFTIMER
  1566. /*
  1567.   The gettimeofday() method, which also sets ztmsec and ztusec, works for
  1568.   all GFTIMER builds.  NOTE: ztmsec and ztusec are defined in ckcmai.c,
  1569.   and extern declarations for them are in ckcdeb.h; thus they are
  1570.   declared in this file by inclusion of ckcdeb.h.
  1571. */
  1572.     char *asctime();
  1573.     struct tm *localtime();
  1574.     struct tm *tp;
  1575.     ztmsec = -1L;
  1576.     ztusec = -1L;
  1577. #ifdef GTODONEARG
  1578.     /* No 2nd arg in Motorola SV88 and some others */
  1579.     if (gettimeofday(&tv) > -1)
  1580. #else
  1581. #ifndef COHERENT
  1582. #ifdef PTX
  1583.     if (gettimeofday(&tv,NULL) > -1)
  1584. #else
  1585.     if (gettimeofday(&tv,&tz) > -1)
  1586. #endif /* PTX */
  1587. #endif /* COHERENT */
  1588. #endif /* GTODONEARG */
  1589.       { /* Fill in tm struct */
  1590. ztusec = tv.tv_usec; /* Microseconds */
  1591. ztmsec = ztusec / 1000L; /* Milliseconds */
  1592. #ifdef HPUX9
  1593. {
  1594.     time_t zz;
  1595.     zz = tv.tv_sec;
  1596.     tp = localtime(&zz); /* Convert to local time */
  1597. }
  1598. #else
  1599. #ifdef HPUX1000
  1600. {
  1601.     time_t zz;
  1602.     zz = tv.tv_sec;
  1603.     tp = localtime(&zz);
  1604. }
  1605. #else
  1606. #ifdef LINUX
  1607. {   /* avoid unaligned access trap on 64-bit platforms */
  1608.     time_t zz;
  1609.     zz = tv.tv_sec;
  1610.     tp = localtime(&zz);
  1611. }
  1612. #else
  1613. #ifdef MACOSX
  1614. tp = localtime((time_t *)&tv.tv_sec); /* Convert to local time */
  1615. #else
  1616. tp = localtime(&tv.tv_sec);
  1617. #endif /* MACOSX */
  1618. #endif /* LINUX */
  1619. #endif /* HPUX1000 */
  1620. #endif /* HPUX9 */
  1621. *s = asctime(tp); /* Convert result to ASCII string */
  1622. debug(F111,"ztime GFTIMER gettimeofday",*s,ztusec);
  1623.     }
  1624. #else  /* Not GFTIMER */
  1625. #undef ZTIMEV7 /* Which systems need to use */
  1626. #ifdef COHERENT /* old UNIX Version 7 way... */
  1627. #define ZTIMEV7
  1628. #endif /* COHERENT */
  1629. #ifdef TOWER1
  1630. #define ZTIMEV7
  1631. #endif /* TOWER1 */
  1632. #ifdef ANYBSD
  1633. #ifndef BSD42
  1634. #define ZTIMEV7
  1635. #endif /* BSD42 */
  1636. #endif /* ANYBSD */
  1637. #ifdef V7
  1638. #ifndef MINIX
  1639. #define ZTIMEV7
  1640. #endif /* MINIX */
  1641. #endif /* V7 */
  1642. #ifdef POSIX
  1643. #define ZTIMEV7
  1644. #endif /* POSIX */
  1645. #ifdef HPUX1020
  1646. /*
  1647.   Prototypes are in <time.h>, included above.
  1648. */
  1649.     time_t clock_storage;
  1650.     clock_storage = time((void *) 0);
  1651.     *s = ctime(&clock_storage);
  1652.     debug(F110,"ztime: HPUX 10.20",*s,0);
  1653. #else
  1654. #ifdef ATTSV /* AT&T way */
  1655. /*  extern long time(); */ /* Theoretically these should */
  1656.     char *ctime(); /* already been dcl'd in <time.h> */
  1657.     time_t clock_storage;
  1658.     clock_storage = time(
  1659. #ifdef IRIX60
  1660.  (time_t *)
  1661. #else
  1662. #ifdef BSD44
  1663.  (time_t *)
  1664. #else
  1665.  (long *)
  1666. #endif /* BSD44 */
  1667. #endif /* IRIX60 */
  1668.  0 );
  1669.     *s = ctime( &clock_storage );
  1670.     debug(F110,"ztime: ATTSV",*s,0);
  1671. #else
  1672. #ifdef PROVX1 /* Venix 1.0 way */
  1673.     int utime[2];
  1674.     time(utime);
  1675.     *s = ctime(utime);
  1676.     debug(F110,"ztime: PROVX1",*s,0);
  1677. #else
  1678. #ifdef BSD42 /* 4.2BSD way */
  1679.     char *asctime();
  1680.     struct tm *localtime();
  1681.     struct tm *tp;
  1682.     gettimeofday(&tv, &tz);
  1683.     ztusec = tv.tv_usec;
  1684.     ztmsec = tv.tv_usec / 1000L;
  1685.     tp = localtime(&tv.tv_sec);
  1686.     *s = asctime(tp);
  1687.     debug(F111,"ztime: BSD42",*s,ztusec);
  1688. #else
  1689. #ifdef MINIX /* MINIX way */
  1690. #ifdef COMMENT
  1691.     extern long time(); /* Already got these from <time.h> */
  1692.     extern char *ctime();
  1693. #endif /* COMMENT */
  1694.     time_t utime[2];
  1695.     time(utime);
  1696.     *s = ctime(utime);
  1697.     debug(F110,"ztime: MINIX",*s,0);
  1698. #else
  1699. #ifdef ZTIMEV7 /* The regular way */
  1700.     char *asctime();
  1701.     struct tm *localtime();
  1702.     struct tm *tp;
  1703.     long xclock; /* or unsigned long for BeBox? */
  1704.     time(&xclock);
  1705.     tp = localtime(&xclock);
  1706.     *s = asctime(tp);
  1707.     debug(F110,"ztime: ZTIMEV7",*s,0);
  1708. #else /* Catch-all for others... */
  1709.     *s = "Day Mon 00 00:00:00 0000n"; /* Return dummy in asctime() format */
  1710.     debug(F110,"ztime: catch-all",*s,0);
  1711. #endif /* ZTIMEV7 */
  1712. #endif /* MINIX */
  1713. #endif /* BSD42 */
  1714. #endif /* PROVX1 */
  1715. #endif /* ATTSV */
  1716. #endif /* HPUX1020 */
  1717. #endif /* GFTIMER */
  1718. }
  1719. /*  C O N G M  --  Get console terminal modes.  */
  1720. /*
  1721.   Saves initial console mode, and establishes variables for switching
  1722.   between current (presumably normal) mode and other modes.
  1723.   Should be called when program starts, but only after establishing
  1724.   whether program is in the foreground or background.
  1725.   Returns 1 if it got the modes OK, 0 if it did nothing, -1 on error.
  1726. */
  1727. int
  1728. congm() {
  1729.     int fd;
  1730.     if (backgrd || !isatty(0)) { /* If in background. */
  1731. cgmf = -1; /* Don't bother, modes are garbage. */
  1732. return(-1);
  1733.     }
  1734.     if (cgmf > 0) return(0); /* Already did this. */
  1735.     debug(F100,"congm getting modes","",0); /* Need to do it. */
  1736. #ifdef aegis
  1737.     ios_$inq_type_uid(ios_$stdin, conuid, st);
  1738.     if (st.all != status_$ok) {
  1739. fprintf(stderr, "problem getting stdin objtype: ");
  1740. error_$print(st);
  1741.     }
  1742.     concrp = (conuid == mbx_$uid);
  1743.     conbufn = 0;
  1744. #endif /* aegis */
  1745. #ifndef BEBOX
  1746.     if ((fd = open(CTTNAM,2)) < 0) { /* Open controlling terminal */
  1747. #ifdef COMMENT
  1748. fprintf(stderr,"Error opening %sn", CTTNAM);
  1749. perror("congm");
  1750. return(-1);
  1751. #else
  1752. fd = 0;
  1753. #endif /* COMMENT */
  1754.     }
  1755. #else
  1756.     fd = 0;
  1757. #endif /* !BEBOX */
  1758. #ifdef BSD44ORPOSIX
  1759.     if (tcgetattr(fd,&ccold) < 0) return(-1);
  1760.     if (tcgetattr(fd,&cccbrk) < 0) return(-1);
  1761.     if (tcgetattr(fd,&ccraw) < 0) return(-1);
  1762. #else
  1763. #ifdef ATTSV
  1764.     if (ioctl(fd,TCGETA,&ccold)  < 0) return(-1);
  1765.     if (ioctl(fd,TCGETA,&cccbrk) < 0) return(-1);
  1766.     if (ioctl(fd,TCGETA,&ccraw)  < 0) return(-1);
  1767. #ifdef VXVE
  1768.     cccbrk.c_line = 0; /* STTY line 0 for CDC VX/VE */
  1769.     if (ioctl(fd,TCSETA,&cccbrk) < 0) return(-1);
  1770.     ccraw.c_line = 0; /* STTY line 0 for CDC VX/VE */
  1771.     if (ioctl(fd,TCSETA,&ccraw) < 0) return(-1);
  1772. #endif /* VXVE */
  1773. #else
  1774. #ifdef BELLV10
  1775.     if (ioctl(fd,TIOCGETP,&ccold) < 0) return(-1);
  1776.     if (ioctl(fd,TIOCGETP,&cccbrk) < 0) return(-1);
  1777.     if (ioctl(fd,TIOCGETP,&ccraw) < 0) return(-1);
  1778.     debug(F101,"cccbrk.sg_flags orig","", cccbrk.sg_flags);
  1779. #else
  1780.     if (gtty(fd,&ccold) < 0) return(-1);
  1781.     if (gtty(fd,&cccbrk) < 0) return(-1);
  1782.     if (gtty(fd,&ccraw) < 0) return(-1);
  1783. #endif /* BELLV10 */
  1784. #endif /* ATTSV */
  1785. #endif /* BSD44ORPOSIX */
  1786. #ifdef sony_news /* Sony NEWS */
  1787.     if (ioctl(fd,TIOCKGET,&km_con) < 0) { /* Get console Kanji mode */
  1788. perror("congm error getting Kanji mode");
  1789. debug(F101,"congm error getting Kanji mode","",0);
  1790. km_con = -1; /* Make sure this stays undefined. */
  1791. return(-1);
  1792.     }
  1793. #endif /* sony_news */
  1794.     if (fd > 0)
  1795.       close(fd);
  1796.     cgmf = 1; /* Flag that we got them. */
  1797.     return(1);
  1798. }
  1799. /*  C O N C B --  Put console in cbreak mode.  */
  1800. /*  Returns 0 if ok, -1 if not  */
  1801. int
  1802. #ifdef CK_ANSIC
  1803. concb(char esc)
  1804. #else
  1805. concb(esc) char esc;
  1806. #endif /* CK_ANSIC */
  1807. /* concb */ {
  1808.     int x;
  1809.     debug(F101,"concb cgmf","",cgmf);
  1810.     debug(F101,"concb backgrd","",backgrd);
  1811.     if (cgmf < 1) /* Did we get console modes yet? */
  1812.       if (!backgrd) /* No, in background? */
  1813. congm(); /* No, try to get them now. */
  1814.     if (cgmf < 1) /* Still don't have them? */
  1815.       return(0); /* Give up. */
  1816.     debug(F101,"concb ttyfd","",ttyfd);
  1817.     debug(F101,"concb ttfdflg","",ttfdflg);
  1818. #ifdef COMMENT
  1819.     /* This breaks returning to prompt after protocol with "-l 0" */
  1820.     /* Commented out July 1998 */
  1821.     if (ttfdflg && ttyfd >= 0 && ttyfd < 3)
  1822.       return(0);
  1823. #endif /* COMMENT */
  1824.     x = isatty(0);
  1825.     debug(F101,"concb isatty","",x);
  1826.     if (!x) return(0); /* Only when running on real ttys */
  1827.     debug(F101,"concb suspend","",suspend);
  1828.     if (backgrd) return(0); /* Do nothing if in background. */
  1829.     escchr = esc;                       /* Make this available to other fns */
  1830.     ckxech = 1;                         /* Program can echo characters */
  1831. #ifdef aegis
  1832.     conbufn = 0;
  1833.     if (concrp) return(write(1, "3502", 2));
  1834.     if (conuid == input_pad_$uid) {pad_$raw(ios_$stdin, st); return(0);}
  1835. #endif /* aegis */
  1836. #ifdef COHERENT
  1837. #define SVORPOSIX
  1838. #endif /* COHERENT */
  1839. #ifdef Plan9
  1840.     x = p9concb();
  1841. #else
  1842. #ifndef SVORPOSIX /* BSD, V7, etc */
  1843.     debug(F101,"cccbrk.sg_flags concb 1","", cccbrk.sg_flags);
  1844.     debug(F101,"concb stty CBREAK","",0);
  1845.     cccbrk.sg_flags |= (CBREAK|CRMOD); /* Set to character wakeup, */
  1846.     cccbrk.sg_flags &= ~ECHO;           /* no echo. */
  1847.     debug(F101,"cccbrk.sg_flags concb 2","", cccbrk.sg_flags);
  1848. #ifdef BELLV10
  1849.     x = ioctl(0,TIOCSETP,&cccbrk);
  1850. #else
  1851.     x = stty(0,&cccbrk);
  1852.     debug(F101,"cccbrk.sg_flags concb x","", x);
  1853. #endif /* BELLV10 */
  1854. #else /* Sys V and POSIX */
  1855. #ifndef OXOS
  1856.     debug(F101,"concb cccbrk.c_flag","",cccbrk.c_lflag);
  1857. #ifdef QNX
  1858.     /* Don't mess with IEXTEN */
  1859.     cccbrk.c_lflag &= ~(ICANON|ECHO);
  1860. #else
  1861. #ifdef COHERENT
  1862.     cccbrk.c_lflag &= ~(ICANON|ECHO);
  1863. #else
  1864.     cccbrk.c_lflag &= ~(ICANON|ECHO|IEXTEN);
  1865. #endif /* COHERENT */
  1866. #endif /* QNX */
  1867.     cccbrk.c_lflag |= ISIG; /* Allow signals in command mode. */
  1868.     cccbrk.c_iflag |= IGNBRK; /* But ignore BREAK signal */
  1869.     cccbrk.c_iflag &= ~BRKINT;
  1870. #else /* OXOS */
  1871.     debug(F100,"concb OXOS is defined","",0);
  1872.     cccbrk.c_lflag &= ~(ICANON|ECHO);
  1873.     cccbrk.c_cc[VDISCARD] = cccbrk.c_cc[VLNEXT] = CDISABLE;
  1874. #endif /* OXOS */
  1875. #ifdef COMMENT
  1876. /*
  1877.   Believe it or not, in SCO UNIX, VSUSP is greater than NCC, and so this
  1878.   array reference is out of bounds.  It's only a debug() call so who needs it.
  1879. */
  1880. #ifdef VSUSP
  1881.     debug(F101,"concb c_cc[VSUSP]","",cccbrk.c_cc[VSUSP]);
  1882. #endif /* VSUSP */
  1883. #endif /* COMMENT */
  1884. #ifndef VINTR
  1885.     debug(F101,"concb c_cc[0]","",cccbrk.c_cc[0]);
  1886.     cccbrk.c_cc[0] = 003;               /* Interrupt char is Control-C */
  1887. #else
  1888.     debug(F101,"concb c_cc[VINTR]","",cccbrk.c_cc[0]);
  1889.     cccbrk.c_cc[VINTR] = 003;
  1890. #endif /* VINTR */
  1891. #ifndef VQUIT
  1892.     cccbrk.c_cc[1] = escchr;            /* escape during packet modes */
  1893. #else
  1894.     cccbrk.c_cc[VQUIT] = escchr;
  1895. #endif /* VQUIT */
  1896. #ifndef VEOF
  1897.     cccbrk.c_cc[4] = 1;
  1898. #else
  1899. #ifndef OXOS
  1900. #ifdef VMIN
  1901.     cccbrk.c_cc[VMIN] = 1;
  1902. #endif /* VMIN */
  1903. #else /* OXOS */
  1904.     cccbrk.c_min = 1;
  1905. #endif /* OXOS */
  1906. #endif /* VEOF */
  1907. #ifdef ZILOG
  1908.     cccbrk.c_cc[5] = 0;
  1909. #else
  1910. #ifndef VEOL
  1911.     cccbrk.c_cc[5] = 1;
  1912. #else
  1913. #ifndef OXOS
  1914. #ifdef VTIME
  1915.     cccbrk.c_cc[VTIME] = 1;
  1916. #endif /* VTIME */
  1917. #else /* OXOS */
  1918.     cccbrk.c_time = 1;
  1919. #endif /* OXOS */
  1920. #endif /* VEOL */
  1921. #endif /* ZILOG */
  1922. #ifdef BSD44ORPOSIX /* Set new modes */
  1923.     x = tcsetattr(0,TCSADRAIN,&cccbrk);
  1924. #else /* ATTSV */       /* or the POSIX way */
  1925.     x = ioctl(0,TCSETAW,&cccbrk); /* the Sys V way */
  1926. #endif /* BSD44ORPOSIX */
  1927. #endif /* SVORPOSIX */
  1928. #ifdef COHERENT
  1929. #undef SVORPOSIX
  1930. #endif /* COHERENT */
  1931. #ifndef aegis
  1932. #ifndef NOSETBUF
  1933.     if (x > -1) setbuf(stdout,NULL);    /* Make console unbuffered. */
  1934. #endif /* NOSETBUF */
  1935. #endif /* aegis */
  1936. #ifdef  V7
  1937. #ifndef MINIX
  1938.     if (kmem[CON] < 0) {
  1939.         qaddr[CON] = initrawq(0);
  1940.         if((kmem[CON] = open("/dev/kmem", 0)) < 0) {
  1941.             fprintf(stderr, "Can't read /dev/kmem in concb.n");
  1942.             perror("/dev/kmem");
  1943.             exit(1);
  1944.         }
  1945.     }
  1946. #endif /* MINIX */
  1947. #endif /* V7 */
  1948. #endif /* Plan9 */
  1949.     debug(F101,"concb returns","",x);
  1950.     return(x);
  1951. }
  1952. /*  C O N B I N  --  Put console in binary mode  */
  1953. /*  Returns 0 if ok, -1 if not  */
  1954. int
  1955. #ifdef CK_ANSIC
  1956. conbin(char esc)
  1957. #else
  1958. conbin(esc) char esc;
  1959. #endif /* CK_ANSIC */
  1960. /* conbin */  {
  1961.     if (!isatty(0)) return(0);          /* only for real ttys */
  1962.     congm(); /* Get modes if necessary. */
  1963.     debug(F100,"conbin","",0);
  1964.     escchr = esc;                       /* Make this available to other fns */
  1965.     ckxech = 1;                         /* Program can echo characters */
  1966. #ifdef aegis
  1967.     conbufn = 0;
  1968.     if (concrp) return(write(1, "3502", 2));
  1969.     if (conuid == input_pad_$uid) {
  1970. pad_$raw(ios_$stdin, st);
  1971. return(0);
  1972.       }
  1973. #endif /* aegis */
  1974. #ifdef COHERENT
  1975. #define SVORPOSIX
  1976. #endif /* COHERENT */
  1977. #ifdef Plan9
  1978.     return p9conbin();
  1979. #else
  1980. #ifdef SVORPOSIX
  1981. #ifndef OXOS
  1982. #ifdef QNX
  1983.     ccraw.c_lflag &= ~(ISIG|ICANON|ECHO);
  1984. #else
  1985. #ifdef COHERENT
  1986.     ccraw.c_lflag &= ~(ISIG|ICANON|ECHO);
  1987. #else
  1988.     ccraw.c_lflag &= ~(ISIG|ICANON|ECHO|IEXTEN);
  1989. #endif /* COHERENT */
  1990. #endif /* QNX */
  1991. #else /* OXOS */
  1992.     ccraw.c_lflag &= ~(ISIG|ICANON|ECHO);
  1993.     ccraw.c_cc[VDISCARD] = ccraw.c_cc[VLNEXT] = CDISABLE;
  1994. #endif /* OXOS */
  1995.     ccraw.c_iflag |= IGNPAR;
  1996. /*
  1997.   Note that for terminal sessions we disable Xon/Xoff flow control to allow
  1998.   the passage ^Q and ^S as data characters for EMACS, and to allow XMODEM
  1999.   transfers to work when C-Kermit is in the middle, etc.  Hardware flow
  2000.   control, if in use, is not affected.
  2001. */
  2002. #ifdef ATTSV
  2003. #ifdef BSD44
  2004.     ccraw.c_iflag &= ~(IGNBRK|INLCR|IGNCR|ICRNL|IXON|IXANY|IXOFF
  2005.                         |INPCK|ISTRIP);
  2006. #else
  2007.     ccraw.c_iflag &= ~(IGNBRK|INLCR|IGNCR|ICRNL|IUCLC|IXON|IXANY|IXOFF
  2008.                         |INPCK|ISTRIP);
  2009. #endif /* BSD44 */
  2010. #else /* POSIX */
  2011.     ccraw.c_iflag &= ~(IGNBRK|INLCR|IGNCR|ICRNL|IXON|IXOFF|INPCK|ISTRIP);
  2012. #endif /* ATTSV */
  2013.     ccraw.c_oflag &= ~OPOST;
  2014. #ifdef COMMENT
  2015. /*
  2016.   WHAT THE HECK WAS THIS FOR?
  2017.   The B9600 setting (obviously) prevents CONNECT from working at any
  2018.   speed other than 9600 when you are logged in to the 7300 on a serial
  2019.   line.  Maybe some of the other flags are necessary -- if so, put back
  2020.   the ones that are needed.  This code is supposed to work the same, no
  2021.   matter whether you are logged in to the 7300 on the real console device,
  2022.   or through a serial port.
  2023. */
  2024. #ifdef ATT7300
  2025.     ccraw.c_cflag = CLOCAL | B9600 | CS8 | CREAD | HUPCL;
  2026. #endif /* ATT7300 */
  2027. #endif /* COMMENT */
  2028. /*** Kermit used to put the console in 8-bit raw mode, but some users have
  2029.  *** pointed out that this should not be done, since some sites actually
  2030.  *** use terminals with parity settings on their Unix systems, and if we
  2031.  *** override the current settings and stop doing parity, then their terminals
  2032.  *** will display blotches for characters whose parity is wrong.  Therefore,
  2033.  *** the following two lines are commented out (Larry Afrin, Clemson U):
  2034.  ***
  2035.  ***   ccraw.c_cflag &= ~(PARENB|CSIZE);
  2036.  ***   ccraw.c_cflag |= (CS8|CREAD);
  2037.  ***
  2038.  *** Sys III/V sites that have trouble with this can restore these lines.
  2039.  ***/
  2040. #ifndef VINTR
  2041.     ccraw.c_cc[0] = 003; /* Interrupt char is Ctrl-C */
  2042. #else
  2043.     ccraw.c_cc[VINTR] = 003;
  2044. #endif /* VINTR */
  2045. #ifndef VQUIT
  2046.     ccraw.c_cc[1] = escchr; /* Escape during packet mode */
  2047. #else
  2048.     ccraw.c_cc[VQUIT] = escchr;
  2049. #endif /* VQUIT */
  2050. #ifndef VEOF
  2051.     ccraw.c_cc[4] = 1;
  2052. #else
  2053. #ifndef OXOS
  2054. #ifdef VMIN
  2055.     ccraw.c_cc[VMIN] = 1;
  2056. #endif /* VMIN */
  2057. #else /* OXOS */
  2058.     ccraw.c_min = 1;
  2059. #endif /* OXOS */
  2060. #endif /* VEOF */
  2061. #ifdef ZILOG
  2062.     ccraw.c_cc[5] = 0;
  2063. #else
  2064. #ifndef VEOL
  2065.     ccraw.c_cc[5] = 1;
  2066. #else
  2067. #ifndef OXOS
  2068. #ifdef VTIME
  2069.     ccraw.c_cc[VTIME] = 1;
  2070. #endif /* VTIME */
  2071. #else /* OXOS */
  2072.     ccraw.c_time = 1;
  2073. #endif /* OXOS */
  2074. #endif /* VEOL */
  2075. #endif /* ZILOG */
  2076. #ifdef BSD44ORPOSIX
  2077.     return(tcsetattr(0,TCSADRAIN,&ccraw));
  2078. #else
  2079.     return(ioctl(0,TCSETAW,&ccraw)); /* Set new modes. */
  2080. #endif /* BSD44ORPOSIX */
  2081. #else /* Berkeley, etc. */
  2082.     ccraw.sg_flags |= (RAW|TANDEM);     /* Set rawmode, XON/XOFF (ha) */
  2083.     ccraw.sg_flags &= ~(ECHO|CRMOD);    /* Set char wakeup, no echo */
  2084. #ifdef BELLV10
  2085.     return(ioctl(0,TIOCSETP,&ccraw));
  2086. #else
  2087.     return(stty(0,&ccraw));
  2088. #endif /* BELLV10 */
  2089. #endif /* SVORPOSIX */
  2090. #endif /* Plan9 */
  2091. #ifdef COHERENT
  2092. #undef SVORPOSIX
  2093. #endif /* COHERENT */
  2094. }
  2095. /*  C O N R E S  --  Restore the console terminal  */
  2096. int
  2097. conres() {
  2098.     debug(F101,"conres cgmf","",cgmf);
  2099.     if (cgmf < 1) return(0); /* Do nothing if modes unchanged */
  2100.     if (!isatty(0)) return(0);          /* only for real ttys */
  2101.     debug(F100,"conres isatty ok","",0);
  2102.     ckxech = 0;                         /* System should echo chars */
  2103. #ifdef aegis
  2104.     conbufn = 0;
  2105.     if (concrp) return(write(1, "3501", 2));
  2106.     if (conuid == input_pad_$uid) {
  2107. pad_$cooked(ios_$stdin, st);
  2108. return(0);
  2109.     }
  2110. #endif /* aegis */
  2111. #ifdef Plan9
  2112.     p9conres();
  2113. #else
  2114. #ifdef BSD44ORPOSIX
  2115.     debug(F100,"conres restoring tcsetattr","",0);
  2116.     return(tcsetattr(0,TCSADRAIN,&ccold));
  2117. #else
  2118. #ifdef ATTSV
  2119.     debug(F100,"conres restoring ioctl","",0);
  2120.     return(ioctl(0,TCSETAW,&ccold));
  2121. #else /* BSD, V7, and friends */
  2122. #ifdef sony_news /* Sony NEWS */
  2123.     if (km_con != -1)
  2124.       ioctl(0,TIOCKSET,&km_con); /* Restore console Kanji mode */
  2125. #endif /* sony_news */
  2126.     msleep(100);
  2127.     debug(F100,"conres restoring stty","",0);
  2128. #ifdef BELLV10
  2129.     return(ioctl(0,TIOCSETP,&ccold));
  2130. #else
  2131.     return(stty(0,&ccold));
  2132. #endif /* BELLV10 */
  2133. #endif /* ATTSV */
  2134. #endif /* BSD44ORPOSIX */
  2135. #endif /* Plan9 */
  2136. }
  2137. /*  C O N O C  --  Output a character to the console terminal  */
  2138. int
  2139. #ifdef CK_ANSIC
  2140. conoc(char c)
  2141. #else
  2142. conoc(c) char c;
  2143. #endif /* CK_ANSIC */
  2144. /* conoc */ {
  2145. #ifdef IKSD
  2146.     if (inserver && !local)
  2147.       return(ttoc(c));
  2148. #ifdef CK_ENCRYPTION
  2149.     if (inserver && TELOPT_ME(TELOPT_ENCRYPTION))
  2150.         ck_tn_encrypt(&c,1);
  2151. #endif /* CK_ENCRYPTION */
  2152. #endif /* IKSD */
  2153. #ifdef Plan9
  2154.     return conwrite(&c,1);
  2155. #else
  2156.     return(write(1,&c,1));
  2157. #endif /* Plan9 */
  2158. }
  2159. /*  C O N X O  --  Write x characters to the console terminal  */
  2160. int
  2161. conxo(x,s) int x; char *s; {
  2162. #ifdef IKSD
  2163.     if (inserver && !local)
  2164.       return(ttol((CHAR *)s,x));
  2165. #ifdef CK_ENCRYPTION
  2166.     if (inserver && TELOPT_ME(TELOPT_ENCRYPTION))
  2167.         ck_tn_encrypt(s,x);
  2168. #endif /* CK_ENCRYPTION */
  2169. #endif /* IKSD */
  2170. #ifdef Plan9
  2171.     return(conwrite(s,x));
  2172. #else
  2173.     return(write(1,s,x));
  2174. #endif /* Plan9 */
  2175. }
  2176. /*  C O N O L  --  Write a line to the console terminal  */
  2177. int
  2178. conol(s) char *s; {
  2179.     int len;
  2180.     if (!s) s = ""; /* Always do this! */
  2181.     len = strlen(s);
  2182. #ifdef IKSD
  2183.     if (inserver && !local)
  2184.       return(ttol((CHAR *)s,len));
  2185. #ifdef CK_ENCRYPTION
  2186.     if (inserver && TELOPT_ME(TELOPT_ENCRYPTION)) {
  2187. if (nxpacket < len) {
  2188.     if (xpacket) {
  2189. free(xpacket);
  2190. xpacket = NULL;
  2191. nxpacket = 0;
  2192.     }
  2193.     len = len > 10240 ? len : 10240;
  2194.     xpacket = (char *)malloc(len);
  2195.     if (!xpacket) {
  2196. fprintf(stderr,"ttol malloc failuren");
  2197. return(-1);
  2198.     } else
  2199.       nxpacket = len;
  2200. }
  2201. memcpy(xpacket,s,len);
  2202. s = xpacket;
  2203. ck_tn_encrypt(s,len);
  2204.     }
  2205. #endif /* CK_ENCRYPTION */
  2206. #endif /* IKSD */
  2207. #ifdef Plan9
  2208.     return(conwrite(s,len));
  2209. #else
  2210.     return(write(1,s,len));
  2211. #endif /* Plan9 */
  2212. }
  2213. /*  C O N O L A  --  Write an array of lines to the console terminal */
  2214. int
  2215. conola(s) char *s[]; {
  2216.     char * p;
  2217.     int i, x;
  2218.     if (!s) return(0);
  2219.     for (i = 0; ; i++) {
  2220. p = s[i];
  2221. if (!p) p = ""; /* Let's not dump core shall we? */
  2222. if (!*p)
  2223.   break;
  2224. #ifdef IKSD
  2225. if (inserver && !local)
  2226.   x = ttol((CHAR *)p,(int)strlen(p));
  2227. else
  2228. #endif /* IKSD */
  2229.   x = conol(p);
  2230. if (x < 0)
  2231.   return(-1);
  2232.     }
  2233.     return(0);
  2234. }
  2235. /*  C O N O L L  --  Output a string followed by CRLF  */
  2236. int
  2237. conoll(s) char *s; {
  2238.     CHAR buf[3];
  2239.     buf[0] = 'r';
  2240.     buf[1] = 'n';
  2241.     buf[2] = '';
  2242.     if (!s) s = "";
  2243. #ifdef IKSD
  2244.     if (inserver && !local) {
  2245. ttol((CHAR *)s,(int)strlen(s));
  2246. return(ttol(buf,2));
  2247.     }
  2248. #endif /* IKSD */
  2249.     conol(s);
  2250. #ifdef IKSD
  2251. #ifdef CK_ENCRYPTION
  2252.     if (inserver && TELOPT_ME(TELOPT_ENCRYPTION))
  2253.       ck_tn_encrypt(buf,2);
  2254. #endif /* CK_ENCRYPTION */
  2255. #endif /* IKSD */
  2256. #ifdef Plan9
  2257.     return(conwrite(buf, 2));
  2258. #else
  2259.     return(write(1,buf,2));
  2260. #endif /* Plan9 */
  2261. }
  2262. /*  C O N C H K  --  Return how many characters available at console  */
  2263. /*
  2264.   We could also use select() here to cover a few more systems that are not
  2265.   covered by any of the following, e.g. HP-UX 9.0x on the model 800.
  2266. */
  2267. int
  2268. conchk() {
  2269.     static int contyp = 0; /* +1 for isatty, -1 otherwise */
  2270.     if (contyp == 0) /* This prevents unnecessary */
  2271.       contyp = (isatty(0) ? 1 : -1); /* duplicated calls to isatty() */
  2272.     debug(F101,"conchk contyp","",contyp);
  2273.     if (backgrd || (contyp < 0))
  2274.       return(0);
  2275. #ifdef aegis
  2276.     if (conbufn > 0) return(conbufn);   /* use old count if nonzero */
  2277.     /* read in more characters */
  2278.     conbufn = ios_$get(ios_$stdin,
  2279.               ios_$cond_opt, conbuf, (long)sizeof(conbuf), st);
  2280.     if (st.all != status_$ok) conbufn = 0;
  2281.     conbufp = conbuf;
  2282.     return(conbufn);
  2283. #else
  2284. #ifdef IKSD
  2285.     if (inserver && !local)
  2286.       return(in_chk(1,ttyfd));
  2287.     else
  2288. #endif /* IKSD */
  2289.       return(in_chk(0,0));
  2290. #endif /* aegis */
  2291. }
  2292. /*  C O N I N C  --  Get a character from the console  */
  2293. /*
  2294.   Call with timo > 0 to do a timed read, timo == 0 to do an untimed blocking
  2295.   read.  Upon success, returns the character.  Upon failure, returns -1.
  2296.   A timed read that does not complete within the timeout period returns -2.
  2297. */
  2298. int
  2299. coninc(timo) int timo; {
  2300.     int n = 0; CHAR ch;
  2301.     int xx;
  2302.     errno = 0; /* Clear this */
  2303. #ifdef IKSD
  2304.     if (inserver && !local) {
  2305. xx = ttinc(timo);
  2306. if (xx < 0)
  2307.   return(ttinctimo ? -2 : -1);
  2308. else
  2309.   return(xx);
  2310.     }
  2311. #endif /* IKSD */
  2312. #ifdef aegis /* Apollo Aegis only... */
  2313.     debug(F101,"coninc timo","",timo);
  2314.     fflush(stdout);
  2315.     if (conchk() > 0) {
  2316. --conbufn;
  2317. return((unsigned)(*conbufp++ & 0xff));
  2318.     }
  2319. #endif /* aegis */
  2320. #ifdef TTLEBUF
  2321.     if (
  2322. #ifdef IKSD
  2323. inserver &&
  2324. #endif /* IKSD */
  2325. !xlocal
  2326. ) {
  2327. if (ttpush >= 0) {
  2328.     debug(F111,"ttinc","ttpush",ttpush);
  2329.     ch = ttpush;
  2330.     ttpush = -1;
  2331.     return(ch);
  2332. }
  2333. if (le_data) {
  2334.     if (le_getchar(&ch) > 0) {
  2335. debug(F111,"ttinc LocalEchoInBuf","ch",ch);
  2336. return(ch);
  2337.     }
  2338. }
  2339.     }
  2340. #endif /* TTLEBUF */
  2341.     if (timo <= 0) { /* Untimed, blocking read. */
  2342. while (1) { /* Keep trying till we get one. */
  2343.     n = read(0, &ch, 1); /* Read a character. */
  2344.     if (n == 0) continue; /* Shouldn't happen. */
  2345.     if (n > 0) { /* If read was successful, */
  2346. #ifdef IKSD
  2347. #ifdef CK_ENCRYPTION
  2348.                 debug(F100,"coninc decrypt 1","",0);
  2349.                 if (inserver && !local && TELOPT_U(TELOPT_ENCRYPTION))
  2350.   ck_tn_decrypt(&ch,1);
  2351. #endif /* CK_ENCRYPTION */
  2352. #endif /* IKSD */
  2353. return((unsigned)(ch & 0xff)); /* return the character. */
  2354.             }
  2355. /* Come here if read() returned an error. */
  2356.     debug(F101, "coninc(0) errno","",errno); /* Log the error. */
  2357. #ifndef OXOS
  2358. #ifdef SVORPOSIX
  2359. #ifdef CIE                             /* CIE Regulus has no EINTR symbol? */
  2360. #ifndef EINTR
  2361. #define EINTR 4
  2362. #endif /* EINTR */
  2363. #endif /* CIE */
  2364. /*
  2365.   This routine is used for several different purposes.  In CONNECT mode, it is
  2366.   used to do an untimed, blocking read from the keyboard in the lower CONNECT
  2367.   fork.  During local-mode file transfer, it reads a character from the
  2368.   console to interrupt the file transfer (like A for a status report, X to
  2369.   cancel a file, etc).  Obviously, we don't want the reads in the latter case
  2370.   to be blocking, or the file transfer would stop until the user typed
  2371.   something.  Unfortunately, System V does not allow the console device input
  2372.   buffer to be sampled nondestructively (e.g. by conchk()), so a kludge is
  2373.   used instead.  During local-mode file transfer, the SIGQUIT signal is armed
  2374.   and trapped by esctrp(), and this routine pretends to have read the quit
  2375.   character from the keyboard normally.  But, kludge or no kludge, the read()
  2376.   issued by this command, under System V only, can fail if a signal -- ANY
  2377.   signal -- is caught while the read is pending.  This can occur not only when
  2378.   the user types the quit character, but also during telnet negotiations, when
  2379.   the lower CONNECT fork signals the upper one about an echoing mode change.
  2380.   When this happens, we have to post the read() again.  This is apparently not
  2381.   a problem in BSD-based UNIX versions.
  2382. */
  2383.     if (errno == EINTR) /* Read interrupted. */
  2384.       if (conesc)  { /* If by SIGQUIT, */
  2385.    conesc = 0; /* the conesc variable is set, */
  2386.    return(escchr); /* so return the escape character. */
  2387.      } else continue; /* By other signal, try again. */
  2388. #else
  2389. /*
  2390.   This might be dangerous, but let's do this on non-System V versions too,
  2391.   since at least one SunOS 4.1.2 user complains of immediate disconnections
  2392.   upon first making a TELNET connection.
  2393. */
  2394.     if (errno == EINTR) /* Read interrupted. */
  2395.       continue;
  2396. #endif /* SVORPOSIX */
  2397. #else /* OXOS */
  2398.     if (errno == EINTR) /* Read interrupted. */
  2399.       continue;
  2400. #endif /* OXOS */
  2401.     return(-1); /* Error */
  2402. }
  2403.     }
  2404. #ifdef DEBUG
  2405.     if (deblog && timo <= 0) {
  2406. debug(F100,"coninc timeout logic error","",0);
  2407. timo = 1;
  2408.     }
  2409. #endif /* DEBUG */
  2410. /* Timed read... */
  2411.     saval = signal(SIGALRM,timerh); /* Set up timeout handler. */
  2412.     xx = alarm(timo); /* Set the alarm. */
  2413.     debug(F101,"coninc alarm set","",timo);
  2414.     if (
  2415. #ifdef CK_POSIX_SIG
  2416. sigsetjmp(sjbuf,1)
  2417. #else
  2418. setjmp(sjbuf)
  2419. #endif /* CK_POSIX_SIG */
  2420. ) /* The read() timed out. */
  2421.       n = -2; /* Code for timeout. */
  2422.     else
  2423.       n = read(0, &ch, 1);
  2424.     ttimoff(); /* Turn off timer */
  2425.     if (n > 0) { /* Got character OK. */
  2426. #ifdef IKSD
  2427. #ifdef CK_ENCRYPTION
  2428.         debug(F100,"coninc decrypt 2","",0);
  2429.         if (inserver && !local && TELOPT_U(TELOPT_ENCRYPTION))
  2430.   ck_tn_decrypt(&ch,1);
  2431. #endif /* CK_ENCRYPTION */
  2432. #endif /* IKSD */
  2433. return((unsigned)(ch & 0xff)); /* Return it. */
  2434.     }
  2435. /*
  2436.   read() returned an error.  Same deal as above, but without the loop.
  2437. */
  2438.     debug(F101, "coninc(timo) n","",n);
  2439.     debug(F101, "coninc(timo) errno","",errno);
  2440. #ifndef OXOS
  2441. #ifdef SVORPOSIX
  2442.     if (n == -1 && errno == EINTR && conesc != 0) {
  2443. conesc = 0;
  2444. return(escchr); /* User entered escape character. */
  2445.     }
  2446. #endif /* SVORPOSIX */
  2447.     if (n == 0 && errno > 0) { /* It's an error */
  2448. return(-1);
  2449.     }
  2450. #endif /* ! OXOS */
  2451.     return(n);
  2452. }
  2453. /*  C O N G K S  --  Console Get Keyboard Scancode  */
  2454. #ifndef congks
  2455. /*
  2456.   This function needs to be filled in with the various system-dependent
  2457.   system calls used by SUNOS, NeXT OS, Xenix, Aviion, etc, to read a full
  2458.   keyboard scan code.  For now, it's a dummy.
  2459. */
  2460. int
  2461. congks(timo) int timo; {
  2462. #ifdef IKSD
  2463.     if (inserver && !local)
  2464.       return(ttinc(timo));
  2465. #endif /* IKSD */
  2466.     return(coninc(timo));
  2467. }
  2468. #endif /* congks */
  2469. #ifdef ATT7300
  2470. /*  A T T D I A L  --  Dial up the remote system using internal modem
  2471.  * Purpose: to open and dial a number on the internal modem available on the
  2472.  * ATT7300 UNIX PC.  Written by Joe Doupnik. Superceeds version written by
  2473.  * Richard E. Hill, Dickinson, TX. which employed dial(3c).
  2474.  * Uses information in <sys/phone.h> and our status int attmodem.
  2475.  */
  2476. attdial(ttname,speed,telnbr) char *ttname,*telnbr; long speed; {
  2477.     char *telnum;
  2478.     attmodem &= ~ISMODEM;                       /* modem not in use yet */
  2479.                     /* Ensure O_NDELAY is set, else i/o traffic hangs */
  2480.                     /* We turn this flag off once the dial is complete */
  2481.     fcntl(ttyfd, F_SETFL, fcntl(ttyfd, F_GETFL, 0) | O_NDELAY);
  2482.     /* Condition line, check availability & DATA mode, turn on speaker */
  2483.     if (ioctl(ttyfd,PIOCOFFHOOK, &dialer) == -1) {
  2484.         printf("cannot access phonen");
  2485.         ttclos(0);
  2486.         return (-2);
  2487.     }
  2488.     ioctl(ttyfd,PIOCGETP,&dialer);      /* get phone dialer parameters */
  2489.     if (dialer.c_lineparam & VOICE) { /* phone must be in DATA mode */
  2490.         printf(" Should not dial with modem in VOICE mode.n");
  2491.         printf(" Exit Kermit, switch to DATA and retry call.n");
  2492.         ttclos(0);
  2493.         return (-2);
  2494.     }
  2495. #ifdef ATTTONED /* Old way, tone dialing only. */
  2496.     dialer.c_lineparam = DATA | DTMF; /* Dial with tones, */
  2497.     dialer.c_lineparam &= ~PULSE; /* not with pulses. */
  2498. #else
  2499.     /* Leave current pulse/tone state alone. */
  2500.     /* But what about DATA?  Add it back if you have trouble. */
  2501.     /* sys/phone says you get DATA automatically by opening device RDWR */
  2502. #endif
  2503.     dialer.c_waitdialtone = 5;                  /* wait 5 sec for dialtone */
  2504. #ifdef COMMENT
  2505.     dialer.c_feedback = SPEAKERON|NORMSPK|RINGON;  /* control speaker */
  2506. #else
  2507.     /* sys/phone says RINGON used only for incoming voice calls */
  2508.     dialer.c_feedback &= ~(SOFTSPK|LOUDSPK);
  2509.     dialer.c_feedback |= SPEAKERON|NORMSPK;
  2510. #endif
  2511.     dialer.c_waitflash = 500;                   /* 0.5 sec flash hook */
  2512.     if(ioctl(ttyfd,PIOCSETP,&dialer) == -1) {   /* set phone parameters */
  2513.         printf("Cannot set modem characteristicsn");
  2514.         ttclos(0);
  2515.         return (-2);
  2516.     }
  2517.     ioctl(ttyfd,PIOCRECONN,0); /* Turns on speaker for pulse */
  2518. #ifdef COMMENT
  2519.     fprintf(stderr,"Phone line status. line_par:%o dialtone_wait:%o 
  2520. line_status:%o feedback:%on",
  2521.     dialer.c_lineparam, dialer.c_waitdialtone,
  2522.     dialer.c_linestatus, dialer.c_feedback);
  2523. #endif
  2524.     attmodem |= ISMODEM;                        /* modem is now in-use */
  2525.     sleep(1);
  2526.     for (telnum = telnbr; *telnum != ''; telnum++)    /* dial number */
  2527. #ifdef ATTTONED
  2528.       /* Tone dialing only */
  2529.       if (ioctl(ttyfd,PIOCDIAL,telnum) != 0) {
  2530.   perror("Error in dialing");
  2531.   ttclos(0);
  2532.   return(-2);
  2533.       }
  2534. #else /* Allow Pulse or Tone dialing */
  2535.     switch (*telnum) {
  2536.       case 't': case 'T': case '%': /* Tone dialing requested */
  2537. dialer.c_lineparam |= DTMF;
  2538. dialer.c_lineparam &= ~PULSE;
  2539. if (ioctl(ttyfd,PIOCSETP,&dialer) == -1) {
  2540.     printf("Cannot set modem to tone dialingn");
  2541.     ttclos(0);
  2542.     return(-2);
  2543. }
  2544. break;
  2545.       case 'd': case 'D': case 'p': case 'P': case '^':
  2546. dialer.c_lineparam |= PULSE;
  2547. dialer.c_lineparam &= ~DTMF;
  2548. if (ioctl(ttyfd,PIOCSETP,&dialer) == -1) {
  2549.     printf("Cannot set modem to pulse dialingn");
  2550.     ttclos(0);
  2551.     return(-2);
  2552. }
  2553. break;
  2554.       default:
  2555.         if (ioctl(ttyfd,PIOCDIAL,telnum) != 0) {
  2556.     perror("Dialing error");
  2557.     ttclos(0);
  2558.     return(-2);
  2559. }
  2560. break;
  2561.     }
  2562. #endif
  2563.     ioctl(ttyfd,PIOCDIAL,"@"); /* terminator for data call */
  2564.     do { /* wait for modems to Connect */
  2565.         if (ioctl(ttyfd,PIOCGETP,&dialer) != 0) { /* get params */
  2566.     perror("Cannot get modems to connect");
  2567.     ttclos(0);
  2568.     return(-2);
  2569. }
  2570.     } while ((dialer.c_linestatus & MODEMCONNECTED) == 0);
  2571.     /* Turn off O_NDELAY flag now. */
  2572.     fcntl(ttyfd, F_SETFL, fcntl(ttyfd, F_GETFL, 0) & ~O_NDELAY);
  2573.     signal(SIGHUP, sighup);             /* hangup on loss of carrier */
  2574.     return(0);                          /* return success */
  2575. }
  2576. /*
  2577.   Offgetty, ongetty functions. These function get the 'getty(1m)' off
  2578.   and restore it to the indicated line.  Shell's return codes are:
  2579.     0: Can't do it.  Probably a user logged on.
  2580.     1: No need.  No getty on that line.
  2581.     2: Done, you should restore the getty when you're done.
  2582.   DOGETY System(3), however, returns them as 0, 256, 512, respectively.
  2583.   Thanks to Kevin O'Gorman, Anarm Software Systems.
  2584.    getoff.sh looks like:   geton.sh looks like:
  2585.      setgetty $1 0           setgetty $1 1
  2586.      err=$?                  exit $?
  2587.      sleep 2
  2588.      exit $err
  2589. */
  2590. /*  O F F G E T T Y  --  Turn off getty(1m) for the communications tty line
  2591.  * and get status so it can be restarted after the line is hung up.
  2592.  */
  2593. int
  2594. offgetty(ttname) char *ttname; {
  2595.     char temp[30];
  2596.     while (*ttname != '') ttname++;       /* seek terminator of path */
  2597.     ttname -= 3;                            /* get last 3 chars of name */
  2598.     sprintf(temp,"/usr/bin/getoff.sh %s",ttname);
  2599.     return(zsyscmd(temp));
  2600. }
  2601. /*  O N G E T T Y  --  Turn on getty(1m) for the communications tty line */
  2602. int
  2603. ongetty(ttname) char *ttname; {
  2604.     char temp[30];
  2605.     while (*ttname != '') ttname++;       /* comms tty path name */
  2606.     ttname -= 3;
  2607.     sprintf(temp,"/usr/bin/geton.sh %s",ttname);
  2608.     return(zsyscmd(temp));
  2609. }
  2610. #endif /* ATT7300 */
  2611. /*  T T S C A R R  --  Set ttcarr variable, controlling carrier handling.
  2612.  *
  2613.  *  0 = Off: Always ignore carrier. E.g. you can connect without carrier.
  2614.  *  1 = On: Heed carrier, except during dialing. Carrier loss gives disconnect.
  2615.  *  2 = Auto: For "modem direct": The same as "Off".
  2616.  *            For real modem types: Heed carrier during connect, but ignore
  2617.  *                it anytime else.  Compatible with pre-5A C-Kermit versions.
  2618.  *
  2619.  * As you can see, this setting does not affect dialing, which always ignores
  2620.  * carrier (unless there is some special exception for some modem type).  It
  2621.  * does affect ttopen() if it is set before ttopen() is used.  This setting
  2622.  * takes effect on the next call to ttopen()/ttpkt()/ttvt().  And they are
  2623.  * (or should be) always called before any communications is tried, which
  2624.  * means that, practically speaking, the effect is immediate.
  2625.  *
  2626.  * Of course, nothing of this applies to remote mode (xlocal = 0).
  2627.  *
  2628.  * Someone has yet to uncover how to manipulate the carrier in the BSD
  2629.  * environment (or any non-termio using environment).  Until that time, this
  2630.  * will simply be a no-op for BSD.
  2631.  *
  2632.  * Note that in previous versions, the carrier was most often left unchanged
  2633.  * in ttpkt()/ttvt() unless they were called with FLO_DIAL or FLO_DIAX.  This
  2634.  * has changed.  Now it is controlled by ttcarr in conjunction with these
  2635.  * modes.
  2636.  */
  2637. int
  2638. ttscarr(carrier) int carrier; {
  2639.     ttcarr = carrier;
  2640.     debug(F101, "ttscarr","",ttcarr);
  2641.     return(ttcarr);
  2642. }
  2643. /* C A R R C T L  --  Set tty modes for carrier treatment.
  2644.  *
  2645.  * Sets the appropriate bits in a termio or sgttyb struct for carrier control
  2646.  * (actually, there are no bits in sgttyb for that), or performs any other
  2647.  * operations needed to control this on the current system.  The function does
  2648.  * not do the actual TCSETA or stty, since often we want to set other bits too
  2649.  * first.  Don't call this function when xlocal is 0, or the tty is not opened.
  2650.  *
  2651.  * We don't know how to do anything like carrier control on non-ATTSV systems,
  2652.  * except, apparently, ultrix.  See above.  It is also known that this doesn't
  2653.  * have much effect on a Xenix system.  For Xenix, one should switch back and
  2654.  * forth between the upper and lower case device files.  Maybe later.
  2655.  * Presently, Xenix will stick to the mode it was opened with.
  2656.  *
  2657.  * carrier: 0 = ignore carrier, 1 = require carrier.
  2658.  * The current state is saved in curcarr, and checked to save labour.
  2659.  */
  2660. #ifdef SVORPOSIX
  2661. int
  2662. #ifdef BSD44ORPOSIX
  2663. carrctl(ttpar, carrier) struct termios *ttpar; int carrier;
  2664. #else /* ATTSV */
  2665. carrctl(ttpar, carrier) struct termio *ttpar; int carrier;
  2666. #endif /* BSD44ORPOSIX */
  2667. /* carrctl */ {
  2668.     debug(F101, "carrctl","",carrier);
  2669.     if (carrier)
  2670.       ttpar->c_cflag &= ~CLOCAL;
  2671.     else
  2672.       ttpar->c_cflag |= CLOCAL;
  2673.     return(0);
  2674. }
  2675. #else /* Berkeley, V7, et al... */
  2676. int
  2677. carrctl(ttpar, carrier) struct sgttyb *ttpar; int carrier; {
  2678.     debug(F101, "carrctl","",carrier);
  2679.     if (carrier == curcarr)
  2680.       return(0);
  2681.     curcarr = carrier;
  2682. #ifdef ultrix
  2683. #ifdef COMMENT
  2684. /*
  2685.   Old code from somebody at DEC that tends to get stuck, time out, etc.
  2686. */
  2687.     if (carrier) {
  2688. ioctl(ttyfd, TIOCMODEM, &temp);
  2689. ioctl(ttyfd, TIOCHPCL, 0);
  2690.     } else {
  2691. /* (According to the manuals, TIOCNCAR should be preferred */
  2692. /* over TIOCNMODEM...) */
  2693. ioctl(ttyfd, TIOCNMODEM, &temp);
  2694.     }
  2695. #else
  2696. /*
  2697.   New code from Jamie Watson that, he says, eliminates the problems.
  2698. */
  2699.     if (carrier) {
  2700. ioctl(ttyfd, TIOCCAR);
  2701. ioctl(ttyfd, TIOCHPCL);
  2702.     } else {
  2703. ioctl(ttyfd, TIOCNCAR);
  2704.     }
  2705. #endif /* COMMENT */
  2706. #endif /* ultrix */
  2707.     return(0);
  2708. }
  2709. #endif /* SVORPOSIX */
  2710. /*  T T G M D M  --  Get modem signals  */
  2711. /*
  2712.  Looks for RS-232 modem signals, and returns those that are on in as its
  2713.  return value, in a bit mask composed of the BM_xxx values defined in ckcdeb.h.
  2714.  Returns:
  2715.  -3 Not implemented
  2716.  -2 if the communication device does not have modem control (e.g. telnet)
  2717.  -1 on error.
  2718.  >= 0 on success, with a bit mask containing the modem signals that are on.
  2719. */
  2720. /*
  2721.   Define the symbol K_MDMCTL if we have Sys V R3 / 4.3 BSD style
  2722.   modem control, namely the TIOCMGET ioctl.
  2723. */
  2724. #ifdef BSD43
  2725. #define K_MDMCTL
  2726. #endif /* BSD43 */
  2727. #ifdef SUNOS4
  2728. #define K_MDMCTL
  2729. #endif /* SUNOS4 */
  2730. /*
  2731.   SCO OpenServer R5.0.4.  The TIOCMGET definition is hardwired in because it
  2732.   is skipped in termio.h when _POSIX_SOURCE is defined.  But _POSIX_SOURCE
  2733.   must be defined in order to get the high serial speeds that are new to
  2734.   5.0.4.  However, the regular SCO drivers do not implement TIOCMGET, so the
  2735.   ioctl() returns -1 with errno 22 (invalid function).  But third-party
  2736.   drivers, e.g. for Digiboard, do implement it, and so it should work on ports
  2737.   driven by those drivers.
  2738. */
  2739. #ifdef SCO_OSR504
  2740. #ifndef TIOCMGET
  2741. #define TIOCMGET (('t'<<8)|29)
  2742. #endif /* TIOCMGET */
  2743. #endif /* SCO_OSR504 */
  2744. #ifdef QNX
  2745. #define K_MDMCTL
  2746. #else
  2747. #ifdef TIOCMGET
  2748. #define K_MDMCTL
  2749. #endif /* TIOCMGET */
  2750. #endif /* QNX */
  2751. /*
  2752.   "A serial communication program that can't read modem signals
  2753.    is like a car without windows."
  2754. */
  2755. int
  2756. ttgmdm() {
  2757. #ifdef QNX
  2758. #include <sys/qioctl.h>
  2759.     unsigned long y, mdmbits[2] = { 0L, 0L };
  2760.     int z = 0;
  2761.     if (xlocal && ttyfd < 0)
  2762.       return(-1);
  2763. #ifdef NETCMD
  2764.     if (ttpipe) return(-2);
  2765. #endif /* NETCMD */
  2766. #ifdef NETPTY
  2767.     if (ttpty) return(-2);
  2768. #endif /* NETPTY */
  2769.     if (!qnx_ioctl(ttyfd, QCTL_DEV_CTL, &mdmbits[0], 8, &mdmbits[0], 4)) {
  2770. y = mdmbits[0];
  2771. if (y & 0x100000L) z |= BM_CTS; /* Values from comment */
  2772. if (y & 0x200000L) z |= BM_DSR; /* in sys/qioctl.h */
  2773. if (y & 0x800000L) z |= BM_DCD;
  2774. if (y & 0x400000L) z |= BM_RNG;
  2775. if (y & 0x000001L) z |= BM_DTR;
  2776. if (y & 0x000002L) z |= BM_RTS;
  2777. return(z);
  2778.     } else return(-1);
  2779. #else
  2780. #ifdef HPUX /* HPUX has its own way */
  2781.     int x, z;
  2782. #ifdef HPUX10 /* Modem flag word */
  2783.     mflag y; /* mflag typedef'd in <sys/modem.h> */
  2784. #else
  2785. #ifdef HPUX9
  2786.     mflag y;
  2787. #else
  2788. #ifdef HPUX8
  2789.     mflag y;
  2790. #else
  2791.     unsigned long y; /* Not sure about pre-8.0... */
  2792. #endif /* HPUX8 */
  2793. #endif /* HPUX9 */
  2794. #endif /* HPUX10 */
  2795.     if (xlocal && ttyfd < 0)
  2796.       return(-1);
  2797.     if (netconn) /* Network connection */
  2798.       return(-2); /* No modem signals */
  2799. #ifdef NETCMD
  2800.     if (ttpipe) return(-2);
  2801. #endif /* NETCMD */
  2802. #ifdef NETPTY
  2803.     if (ttpty) return(-2);
  2804. #endif /* NETPTY */
  2805.     if (xlocal) /* Get modem signals */
  2806.       x = ioctl(ttyfd,MCGETA,&y);
  2807.     else
  2808.       x = ioctl(0,MCGETA,&y);
  2809.     if (x < 0) return(-1);
  2810.     debug(F101,"ttgmdm","",y);
  2811.     z = 0; /* Initialize return value */
  2812. /* Now set bits for each modem signal that is reported to be on. */
  2813. #ifdef MCTS
  2814.     /* Clear To Send */
  2815.     if (y & MCTS) z |= BM_CTS;
  2816. #endif
  2817. #ifdef MDSR
  2818.     /* Data Set Ready */
  2819.     if (y & MDSR) z |= BM_DSR;
  2820. #endif
  2821. #ifdef MDCD
  2822.     /* Carrier */
  2823.     if (y & MDCD) z |= BM_DCD;
  2824. #endif
  2825. #ifdef MRI
  2826.     /* Ring Indicate */
  2827.     if (y & MRI) z |= BM_RNG;
  2828. #endif
  2829. #ifdef MDTR
  2830.     /* Data Terminal Ready */
  2831.     if (y & MDTR) z |= BM_DTR;
  2832. #endif
  2833. #ifdef MRTS
  2834.     /* Request To Send */
  2835.     if (y & MRTS) z |= BM_RTS;
  2836. #endif
  2837.     return(z);
  2838. #else /* ! HPUX */
  2839. #ifdef K_MDMCTL
  2840. /*
  2841.   Note, TIOCMGET might already have been defined in <sys/ioctl.h> or elsewhere.
  2842.   If not, we try including <sys/ttycom.h> -- if this blows up then more ifdefs
  2843.   are needed.
  2844. */
  2845. #ifndef TIOCMGET
  2846. #include <sys/ttycom.h>
  2847. #endif /* TIOCMGET */
  2848.     int x, y, z;
  2849.     debug(F100,"ttgmdm K_MDMCTL defined","",0);
  2850.     if (netconn) /* Network connection */
  2851.       return(-2); /* No modem signals */
  2852. #ifdef NETCMD
  2853.     if (ttpipe) return(-2);
  2854. #endif /* NETCMD */
  2855. #ifdef NETPTY
  2856.     if (ttpty) return(-2);
  2857. #endif /* NETPTY */
  2858.     if (xlocal && ttyfd < 0)
  2859.       return(-1);
  2860.     if (xlocal)
  2861.       x = ioctl(ttyfd,TIOCMGET,&y); /* Get modem signals. */
  2862.     else
  2863.       x = ioctl(0,TIOCMGET,&y);
  2864.     debug(F101,"ttgmdm TIOCMGET ioctl","",x);
  2865.     if (x < 0) {
  2866. debug(F101,"ttgmdm errno","",errno);
  2867. return(-1);
  2868.     }
  2869.     debug(F101,"ttgmdm bits","",y);
  2870.     z = 0; /* Initialize return value. */
  2871. #ifdef TIOCM_CTS
  2872.     /* Clear To Send */
  2873.     if (y & TIOCM_CTS) z |= BM_CTS;
  2874. #endif
  2875. #ifdef TIOCM_DSR
  2876.     /* Data Set Ready */
  2877.     if (y & TIOCM_DSR) z |= BM_DSR;
  2878. #endif
  2879. #ifdef TIOCM_CAR
  2880.     /* Carrier */
  2881.     if (y & TIOCM_CAR) z |= BM_DCD;
  2882. #endif
  2883. #ifdef TIOCM_RNG
  2884.     /* Ring Indicate */
  2885.     if (y & TIOCM_RNG) z |= BM_RNG;
  2886. #endif
  2887. #ifdef TIOCM_DTR
  2888.     /* Data Terminal Ready */
  2889.     if (y & TIOCM_DTR) z |= BM_DTR;
  2890. #endif
  2891. #ifdef TIOCM_RTS
  2892.     /* Request To Send */
  2893.     if (y & TIOCM_RTS) z |= BM_RTS;
  2894. #endif
  2895.     return(z);
  2896. #else /* !K_MDMCTL catch-All */
  2897.     debug(F100,"ttgmdm K_MDMCTL not defined","",0);
  2898. #ifdef TIOCMGET
  2899.     debug(F100,"ttgmdm TIOCMGET defined","",0);
  2900. #else
  2901.     debug(F100,"ttgmdm TIOCMGET not defined","",0);
  2902. #endif /* TIOCMGET */
  2903. #ifdef _SVID3
  2904.     debug(F100,"ttgmdm _SVID3 defined","",0);
  2905. #else
  2906.     debug(F100,"ttgmdm _SVID3 not defined","",0);
  2907. #endif /* _SVID3 */
  2908.     if (netconn) /* Network connection */
  2909.       return(-2); /* No modem signals */
  2910. #ifdef NETCMD
  2911.     if (ttpipe) return(-2);
  2912. #endif /* NETCMD */
  2913. #ifdef NETPTY
  2914.     if (ttpty) return(-2);
  2915. #endif /* NETPTY */
  2916.     return(-3); /* Sorry, I don't know how... */
  2917. #endif /* K_MDMCTL */
  2918. #endif /* HPUX */
  2919. #endif /* QNX */
  2920. }
  2921. /*  P S U S P E N D  --  Put this process in the background.  */
  2922. /*
  2923.   Call with flag nonzero if suspending is allowed, zero if not allowed.
  2924.   Returns 0 on apparent success, -1 on failure (flag was zero, or
  2925.   kill() returned an error code.
  2926. */
  2927. int
  2928. psuspend(flag) int flag; {
  2929. #ifdef RTU
  2930.     extern int rtu_bug;
  2931. #endif /* RTU */
  2932.     if (flag == 0) return(-1);
  2933. #ifdef NOJC
  2934.     return(-1);
  2935. #else
  2936. #ifdef SIGTSTP
  2937. /*
  2938.   The big question here is whether job control is *really* supported.
  2939.   There's no way Kermit can know for sure.  The fact that SIGTSTP is
  2940.   defined does not guarantee the Unix kernel supports it, and the fact
  2941.   that the Unix kernel supports it doesn't guarantee that the user's
  2942.   shell (or other process that invoked Kermit) supports it.
  2943. */
  2944. #ifdef RTU
  2945.     rtu_bug = 1;
  2946. #endif /* RTU */
  2947.     if (kill(0,SIGSTOP) < 0
  2948. #ifdef MIPS
  2949. /* Let's try this for MIPS too. */
  2950. && kill(getpid(),SIGSTOP) < 0
  2951. #endif /* MIPS */
  2952. ) { /* If job control, suspend the job */
  2953. perror("suspend");
  2954. debug(F101,"psuspend error","",errno);
  2955. return(-1);
  2956.     }
  2957.     debug(F100,"psuspend ok","",0);
  2958.     return(0);
  2959. #else
  2960.     return(-1);
  2961. #endif /* SIGTSTP */
  2962. #endif /* NOJC */
  2963. }
  2964. /*
  2965.   setuid package, by Kristoffer Eriksson, with contributions from Dean
  2966.   Long and fdc.
  2967. */
  2968. /* The following is for SCO when CK_ANSILIBS is defined... */
  2969. #ifdef M_UNIX
  2970. #ifdef CK_ANSILIBS
  2971. #ifndef NOGETID_PROTOS
  2972. #define NOGETID_PROTOS
  2973. #endif /* NOGETID_PROTOS */
  2974. #endif /* CK_ANSILIBS */
  2975. #endif /* M_UNIX */
  2976. #ifndef _POSIX_SOURCE
  2977. #ifndef SUNOS4
  2978. #ifndef NEXT
  2979. #ifndef PS2AIX10
  2980. #ifndef sequent
  2981. #ifndef HPUX9
  2982. #ifndef COHERENT
  2983. #ifndef NOGETID_PROTOS
  2984. extern UID_T getuid(), geteuid(), getreuid();
  2985. extern GID_T getgid(), getegid(), getregid();
  2986. #endif /* NOGETID_PROTOS */
  2987. #else
  2988. extern UID_T getreuid();
  2989. extern GID_T getregid();
  2990. #endif /* COHERENT */
  2991. #endif /* HPUX9 */
  2992. #endif /* sequent */
  2993. #endif /* PS2AIX10 */
  2994. #endif /* NEXT */
  2995. #endif /* SUNOS4 */
  2996. #endif /* _POSIX_SOURCE */
  2997. /*
  2998. Subject: Set-user-id
  2999. To: fdc@watsun.cc.columbia.edu (Frank da Cruz)
  3000. Date: Sat, 21 Apr 90 4:48:25 MES
  3001. From: Kristoffer Eriksson <ske@pkmab.se>
  3002. This is a set of functions to be used in programs that may be run set-user-id
  3003. and/or set-group-id. They handle both the case where the program is not run
  3004. with such privileges (nothing special happens then), and the case where one
  3005. or both of these set-id modes are used.  The program is made to run with the
  3006. user's real user and group ids most of the time, except for when more
  3007. privileges are needed.  Don't set-user-id to "root".
  3008. This works on System V and POSIX.  In BSD, it depends on the
  3009. "saved-set-user-id" feature.
  3010. */
  3011. #define UID_ROOT 0 /* Root user and group ids */
  3012. #define GID_ROOT 0
  3013. /*
  3014.   The following code defines the symbol SETEUID for UNIX systems based
  3015.   on BSD4.4 (either -Encumbered or -Lite).  This program will then use
  3016.   seteuid() and setegid() instead of setuid() and setgid(), which still
  3017.   don't allow arbitrary switching.  It also avoids setreuid() and
  3018.   setregid(), which are included in BSD4.4 for compatibility only, are
  3019.   insecure, and print warnings to stderr under at least one system (NetBSD
  3020.   1.0).  Note that POSIX systems should still use setuid() and setgid();
  3021.   the seteuid() and setegid() functions are BSD4.4 extensions to the
  3022.   POSIX model.  Mike Long <mike.long@analog.com>, 8/94.
  3023. */
  3024. #ifdef BSD44
  3025. #define SETEUID
  3026. #endif /* BSD44 */
  3027. /*
  3028.   The following construction automatically defines the symbol SETREUID for
  3029.   UNIX versions based on Berkeley Unix 4.2 and 4.3.  If this symbol is
  3030.   defined, then this program will use getreuid() and getregid() calls in
  3031.   preference to getuid() and getgid(), which in Berkeley-based Unixes do
  3032.   not allow arbitrary switching back and forth of real & effective uid.
  3033.   This construction also allows -DSETREUID to be put on the cc command line
  3034.   for any system that has and wants to use setre[ug]id().  It also prevents
  3035.   automatic definition of SETREUID if -DNOSETREU is included on the cc
  3036.   command line (or otherwise defined).
  3037. */
  3038. #ifdef FT18 /* None of this for Fortune. */
  3039. #define NOSETREU
  3040. #endif /* FT18 */
  3041. #ifdef ANYBSD
  3042. #ifndef BSD29
  3043. #ifndef BSD41
  3044. #ifndef SETREUID
  3045. #ifndef NOSETREU
  3046. #ifndef SETEUID
  3047. #define SETREUID
  3048. #endif /* SETEUID */
  3049. #endif /* NOSETREU */
  3050. #endif /* SETREUID */
  3051. #endif /* !BSD41 */
  3052. #endif /* !BSD29 */
  3053. #endif /* ANYBSD */
  3054. /* Variables for user and group IDs. */
  3055. static UID_T realuid = (UID_T) -1, privuid = (UID_T) -1;
  3056. static GID_T realgid = (GID_T) -1, privgid = (GID_T) -1;
  3057. /* P R I V _ I N I  --  Initialize privileges package  */
  3058. /* Called as early as possible in a set-uid or set-gid program to store the
  3059.  * set-to uid and/or gid and step down to the users real uid and gid. The
  3060.  * stored id's can be temporarily restored (allowed in System V) during
  3061.  * operations that require the privilege.  Most of the time, the program
  3062.  * should execute in unpriviliged state, to not impose any security threat.
  3063.  *
  3064.  * Note: Don't forget that access() always uses the real id:s to determine
  3065.  * file access, even with privileges restored.
  3066.  *
  3067.  * Returns an error mask, with error values or:ed together:
  3068.  *   1 if setuid() fails,
  3069.  *   2 if setgid() fails, and
  3070.  *   4 if the program is set-user-id to "root", which can't be handled.
  3071.  *
  3072.  * Only the return value 0 indicates real success. In case of failure,
  3073.  * those privileges that could be reduced have been, at least, but the
  3074.  * program should be aborted none-the-less.
  3075.  *
  3076.  * Also note that these functions do not expect the uid or gid to change
  3077.  * without their knowing. It may work if it is only done temporarily, but
  3078.  * you're on your own.
  3079.  */
  3080. int
  3081. priv_ini() {
  3082.     int err = 0;
  3083.     /* Save real ID:s. */
  3084.     realuid = getuid();
  3085.     realgid = getgid();
  3086.     /* Save current effective ID:s, those set to at program exec. */
  3087.     privuid = geteuid();
  3088.     privgid = getegid();
  3089.     /* If running set-uid, go down to real uid, otherwise remember that
  3090.      * no privileged uid is available.
  3091.      *
  3092.      * Exceptions:
  3093.      *
  3094.      * 1) If the real uid is already "root" and the set-uid uid (the
  3095.      * initial effective uid) is not "root", then we would have trouble
  3096.      * if we went "down" to "root" here, and then temporarily back to the
  3097.      * set-uid uid (not "root") and then again tried to become "root". I
  3098.      * think the "saved set-uid" is lost when changing uid from effective
  3099.      * uid "root", which changes all uid, not only the effective uid. But
  3100.      * in this situation, we can simply go to "root" and stay there all
  3101.      * the time. That should give sufficient privilege (understatement!),
  3102.      * and give the right uids for subprocesses.
  3103.      *
  3104.      * 2) If the set-uid (the initial effective uid) is "root", and we
  3105.      * change uid to the real uid, we can't change it back to "root" when
  3106.      * we need the privilege, for the same reason as in 1). Thus, we can't
  3107.      * handle programs that are set-user-id to "root" at all. The program
  3108.      * should be stopped.  Use some other uid.  "root" is probably too
  3109.      * privileged for such things, anyway. (The uid is reverted to the
  3110.      * real uid until termination.)
  3111.      *
  3112.      * These two exceptions have the effect that the "root" uid will never
  3113.      * be one of the two uids that are being switched between, which also
  3114.      * means we don't have to check for such cases in the switching
  3115.      * functions.
  3116.      *
  3117.      * Note that exception 1) is handled by these routines (by constantly
  3118.      * running with uid "root", while exception 2) is a serious error, and
  3119.      * is not provided for at all in the switching functions.
  3120.      */
  3121.     if (realuid == privuid)
  3122. privuid = (UID_T) -1; /* Not running set-user-id. */
  3123.     /* If running set-gid, go down to real gid, otherwise remember that
  3124.      * no privileged gid is available.
  3125.      *
  3126.      * There are no exception like there is for the user id, since there
  3127.      * is no group id that is privileged in the manner of uid "root".
  3128.      * There could be equivalent problems for group changing if the
  3129.      * program sometimes ran with uid "root" and sometimes not, but
  3130.      * that is already avoided as explained above.
  3131.      *
  3132.      * Thus we can expect always to be able to switch to the "saved set-
  3133.      * gid" when we want, and back to the real gid again. You may also
  3134.      * draw the conclusion that set-gid provides for fewer hassles than
  3135.      * set-uid.
  3136.      */
  3137.     if (realgid == privgid) /* If not running set-user-id, */
  3138.       privgid = (GID_T) -1; /*  remember it this way. */
  3139.     err = priv_off(); /* Turn off setuid privilege. */
  3140.     if (privuid == UID_ROOT) /* If setuid to root, */
  3141.       err |= 4; /* return this error. */
  3142.     if (realuid == UID_ROOT) { /* If real id is root, */
  3143. privuid = (UID_T) -1; /* stay root at all times. */
  3144. #ifdef ATT7300
  3145. /* If Kermit installed SUID uucp and user is running as root */
  3146. err &= ~1; /* System V R0 does not save UID */
  3147. #endif /* ATT7300 */
  3148.     }
  3149.     return(err);
  3150. }
  3151. /* Macros for hiding the differences in UID/GID setting between various Unix
  3152.  * systems. These macros should always be called with both the privileged ID
  3153.  * and the non-privileged ID. The one in the second argument, will become the
  3154.  * effective ID. The one in the first argument will be retained for later
  3155.  * retrieval.
  3156.  */
  3157. #ifdef SETREUID
  3158. #ifdef SAVEDUID
  3159. /* On BSD systems with the saved-UID feature, we just juggle the effective
  3160.  * UID back and forth, and leave the real UID at its true value.  The kernel
  3161.  * allows switching to both the current real UID, the effective UID, and the
  3162.  * UID which the program is set-UID to.  The saved set-UID always holds the
  3163.  * privileged UID for us, and the real UID will always be the non-privileged,
  3164.  * and we can freely choose one of them for the effective UID at any time.
  3165.  */
  3166. #define switchuid(hidden,active) setreuid( (UID_T) -1, active)
  3167. #define switchgid(hidden,active) setregid( (GID_T) -1, active)
  3168. #else   /* SETREUID,!SAVEDUID */
  3169. /* On systems with setreXid() but without the saved-UID feature, notably
  3170.  * BSD 4.2, we swap the real and effective UIDs each time.  It's
  3171.  * the effective UID that we are interested in, but we have to retain the
  3172.  * unused UID somewhere to enable us to restore it later, and we do this
  3173.  * in the real UID.  The kernel only allows switching to either the current
  3174.  * real or the effective UID, unless you're "root".
  3175.  */
  3176. #define switchuid(hidden,active) setreuid(hidden,active)
  3177. #define switchgid(hidden,active) setregid(hidden,active)
  3178. #endif
  3179. #else /* !SETREUID, !SAVEDUID */
  3180. #ifdef SETEUID
  3181. /*
  3182.   BSD 4.4 works similarly to System V and POSIX (see below), but uses
  3183.   seteXid() instead of setXid() to change effective IDs.  In addition, the
  3184.   seteXid() functions work the same for "root" as for other users.
  3185. */
  3186. #define switchuid(hidden,active) seteuid(active)
  3187. #define switchgid(hidden,active) setegid(active)
  3188. #else /* !SETEUID */
  3189. /* On System V and POSIX, the only thing we can change is the effective UID
  3190.  * (unless the current effective UID is "root", but initsuid() avoids that for
  3191.  * us).  The kernel allows switching to the current real UID or to the saved
  3192.  * set-UID.  These are always set to the non-privileged UID and the privileged
  3193.  * UID, respectively, and we only change the effective UID.  This breaks if
  3194.  * the current effective UID is "root", though, because for "root" setuid/gid
  3195.  * becomes more powerful, which is why initsuid() treats "root" specially.
  3196.  * Note: That special treatment maybe could be ignored for BSD?  Note: For
  3197.  * systems that don't fit any of these four cases, we simply can't support
  3198.  * set-UID.
  3199.  */
  3200. #define switchuid(hidden,active) setuid(active)
  3201. #define switchgid(hidden,active) setgid(active)
  3202. #endif /* SETEUID */
  3203. #endif /* SETREUID */
  3204. /* P R I V _ O N  --  Turn on the setuid and/or setgid */
  3205. /* Go to the privileged uid (gid) that the program is set-user-id
  3206.  * (set-group-id) to, unless the program is running unprivileged.
  3207.  * If setuid() fails, return value will be 1. If getuid() fails it
  3208.  * will be 2.  Return immediately after first failure, and the function
  3209.  * tries to restore any partial work done.  Returns 0 on success.
  3210.  * Group id is changed first, since it is less serious than user id.
  3211.  */
  3212. int
  3213. priv_on() {
  3214.     if (privgid != (GID_T) -1)
  3215.       if (switchgid(realgid,privgid))
  3216.         return(2);
  3217.     if (privuid != (UID_T) -1)
  3218.       if (switchuid(realuid,privuid)) {
  3219.   if (privgid != (GID_T) -1)
  3220.     switchgid(privgid,realgid);
  3221.   return(1);
  3222.       }
  3223.     return(0);
  3224. }
  3225. /* P R I V _ O F F  --  Turn on the real uid and gid */
  3226. /* Return to the unprivileged uid (gid) after an temporary visit to
  3227.  * privileged status, unless the program is running without set-user-id
  3228.  * (set-group-id). Returns 1 for failure in setuid() and 2 for failure
  3229.  * in setgid() or:ed together. The functions tries to return both uid
  3230.  * and gid to unprivileged state, regardless of errors. Returns 0 on
  3231.  * success.
  3232.  */
  3233. int
  3234. priv_off() {
  3235.     int err = 0;
  3236.     if (privuid != (UID_T) -1)
  3237.        if (switchuid(privuid,realuid))
  3238.   err |= 1;
  3239.     if (privgid != (GID_T) -1)
  3240.        if (switchgid(privgid,realgid))
  3241. err |= 2;
  3242.     return(err);
  3243. }
  3244. /* Turn off privilege permanently.  No going back.  This is necessary before
  3245.  * a fork() on BSD43 machines that don't save the setUID or setGID, because
  3246.  * we swap the real and effective ids, and we don't want to let the forked
  3247.  * process swap them again and get the privilege back. It will work on other
  3248.  * machines too, such that you can rely on its effect always being the same,
  3249.  * for instance, even when you're in priv_on() state when this is called.
  3250.  * (Well, that part about "permanent" is on System V only true if you follow
  3251.  * this with a call to exec(), but that's what we want it for anyway.)
  3252.  * Added by Dean Long -- dlong@midgard.ucsc.edu
  3253.  */
  3254. int
  3255. priv_can() {
  3256. #ifdef SETREUID
  3257.     int err = 0;
  3258.     if (privuid != (UID_T) -1)
  3259.        if (setreuid(realuid,realuid))
  3260.   err |= 1;
  3261.     if (privgid != (GID_T) -1)
  3262.         if (setregid(realgid,realgid))
  3263.     err |= 2;
  3264.     return(err);
  3265. #else
  3266. #ifdef SETEUID
  3267.     int err = 0;
  3268.     if (privuid != (UID_T) -1)
  3269. if (setuid(realuid)) {
  3270.     debug(F101,"setuid failed","",errno);
  3271.     err |= 1;
  3272.     debug(F101,"ruid","",getuid());
  3273.     debug(F101,"euid","",geteuid());
  3274. }
  3275.     debug(F101,"setuid","",realuid);
  3276.     if (privgid != (GID_T) -1)
  3277.         if (setgid(realgid)) {
  3278.     debug(F101,"setgid failed","",errno);
  3279.     err |= 2;
  3280.     debug(F101,"rgid","",getgid());
  3281.     debug(F101,"egid","",getegid());
  3282. }
  3283.     debug(F101,"setgid","",realgid);
  3284.     return(err);
  3285. #else
  3286.     /* Easy way of using setuid()/setgid() instead of setreuid()/setregid().*/
  3287.     return(priv_off());
  3288. #endif /* SETEUID */
  3289. #endif /* SETREUID */
  3290. }
  3291. /* P R I V _ O P N  --  For opening protected files or devices. */
  3292. int
  3293. priv_opn(name, modes) char *name; int modes; {
  3294.     int x;
  3295.     priv_on(); /* Turn privileges on */
  3296.     x = open(name, modes); /* Try to open the device */
  3297.     priv_off(); /* Turn privileges off */
  3298.     return(x); /* Return open's return code */
  3299. }
  3300. /*  P R I V _ C H K  --  Check privileges.  */
  3301. /*  Try to turn them off.  If turning them off did not succeed, cancel them */
  3302. int
  3303. priv_chk() {
  3304.     int x, y = 0;
  3305.     x = priv_off(); /* Turn off privs. */
  3306.     if (x != 0 || getuid() == privuid || geteuid() == privuid)
  3307.       y = priv_can();
  3308.     if (x != 0 || getgid() == privgid || getegid() == privgid)
  3309.       y = y | priv_can();
  3310.     return(y);
  3311. }
  3312. UID_T
  3313. real_uid() {
  3314.     return(realuid);
  3315. }
  3316. VOID
  3317. ttimoff() { /* Turn off any timer interrupts */
  3318.     /* int xx; */
  3319. /*
  3320.   As of 5A(183), we set SIGALRM to SIG_IGN (to ignore alarms) rather than to
  3321.   SIG_DFL (to catch alarms, or if there is no handler, to exit).  This is to
  3322.   cure (mask, really) a deeper problem with stray alarms that occurs on some
  3323.   systems, possibly having to do with sleep(), that caused core dumps.  It
  3324.   should be OK to do this, because no code in this module uses nested alarms.
  3325.   (But we still have to watch out for SCRIPT and DIAL...)
  3326. */
  3327.     /* xx = */ alarm(0);
  3328.     /* debug(F101,"ttimoff alarm","",xx); */
  3329.     if (saval) { /* Restore any previous */
  3330. signal(SIGALRM,saval); /* alarm handler. */
  3331. /* debug(F101,"ttimoff alarm restoring saval","",saval); */
  3332. saval = NULL;
  3333.     } else {
  3334. signal(SIGALRM,SIG_IGN); /* Used to be SIG_DFL */
  3335. /* debug(F100,"ttimoff alarm SIG_IGN","",0); */
  3336.     }
  3337. }
  3338. #ifdef CK_REDIR
  3339. #ifdef COMMENT
  3340. /* Old way - not portable */
  3341. int
  3342. ttruncmd(s) char *s; {
  3343.     int r = 0; /* Return code */
  3344. /* 0 = failure, 1 = success */
  3345. #ifdef WIFEXITED
  3346. #ifndef WEXITSTATUS
  3347. #ifdef w_retcode
  3348. #define WEXITSTATUS(x) ((x).w_retcode)
  3349. #endif /* w_retcode */
  3350. #endif /* WEXITSTATUS */
  3351. #ifdef WEXITSTATUS
  3352. #define CK_FUN_OK
  3353. #endif /* WEXITSTATUS */
  3354. #endif /* WIFEXITED */
  3355. #ifdef NEXT
  3356. #define waitpid(pid,status,option) wait4((pid),(status),(option),NULL)
  3357. #else
  3358. #ifdef sony_news
  3359. #define waitpid(pid,status,option) wait4((pid),(status),(option),NULL)
  3360. #endif /* sony_news */
  3361. #endif /* NEXT */
  3362. #ifdef CK_FUN_OK
  3363.     PID_T pid;
  3364.     if (ttyfd == -1) {
  3365. printf("?Sorry, device is not openn");
  3366. return(0);
  3367.     }
  3368.     if (nopush) {
  3369. debug(F100,"ttruncmd fail: nopush","",0);
  3370. return(0);
  3371.     }
  3372.     conres(); /* Make console normal  */
  3373.     if ((pid = fork()) == 0) { /* Make a child fork */
  3374. /* give it stdin,out to the line */
  3375. if (priv_can()) /* Turn off privs. */
  3376.   exit(1);
  3377. dup2(ttyfd, 0);
  3378. dup2(ttyfd, 1);
  3379. _exit(system(s) ? BAD_EXIT : 0);
  3380.     } else {
  3381. WAIT_T status; /* This is int for all but NeXT */
  3382. SIGTYP (*istat)(), (*qstat)();
  3383. if (pid == (PID_T) -1) /* fork() failed? */
  3384.   return(0);
  3385. istat = signal(SIGINT,SIG_IGN); /* Let the fork handle keyboard */
  3386. qstat = signal(SIGQUIT,SIG_IGN); /* interrupts itself... */
  3387. if (waitpid(pid, &status, 0) != pid) {
  3388.     printf("?Can't wait for child process?rn");
  3389. } else {
  3390.     if (WIFEXITED(status)) {
  3391. if (WEXITSTATUS(status)) {
  3392.     printf("?Command exit status: %drn",
  3393.    WEXITSTATUS(status));
  3394. } else r = 1;
  3395.     } else {
  3396. printf("?Command did not exit - cancelling it now.rn");
  3397. kill(pid, SIGKILL);
  3398.     }
  3399. }
  3400. signal(SIGINT,istat); /* Restore interrupts */
  3401. signal(SIGQUIT,qstat);
  3402.     }
  3403.     concb((char)escchr); /* Restore console to CBREAK mode */
  3404. #else
  3405.     printf("?Sorry, can't execute this command - pieces missing.n");
  3406. #endif /* CK_FUN_OK */
  3407.     return(r);
  3408. }
  3409. #else
  3410. int
  3411. ttruncmd(s) char *s; {
  3412.     PID_T pid; /* pid of lower fork */
  3413.     int wstat; /* for wait() */
  3414.     int x;
  3415. #ifdef OSF40
  3416. /*
  3417.   This is to shut up warnings from DECC - if it causes trouble, just remove
  3418.   it, since the warnings don't seem to affect correct operation at runtime.
  3419. */
  3420.     union wait statusp_w;
  3421.     int statusp;
  3422. #else
  3423.     int statusp;
  3424. #endif /* OSF40 */
  3425.     if (ttyfd == -1) {
  3426. printf("?Sorry, device is not openn");
  3427. return(0);
  3428.     }
  3429.     if (nopush) {
  3430. debug(F100,"ttruncmd fail: nopush","",0);
  3431. return(0);
  3432.     }
  3433.     conres(); /* Make console normal  */
  3434.     pexitstat = -4;
  3435.     if ((pid = fork()) == 0) { /* Make a child fork */
  3436. if (priv_can()) /* Child: turn off privs. */
  3437.   exit(1);
  3438. dup2(ttyfd, 0); /* Give stdin/out to the line */
  3439. dup2(ttyfd, 1);
  3440. x = system(s);
  3441. debug(F101,"ttruncmd system",s,x);
  3442. _exit(x ? BAD_EXIT : 0);
  3443.     } else {
  3444. SIGTYP (*istat)(), (*qstat)();
  3445. if (pid == (PID_T) -1) /* fork() failed? */
  3446.   return(0);
  3447. istat = signal(SIGINT,SIG_IGN); /* Let the fork handle keyboard */
  3448. qstat = signal(SIGQUIT,SIG_IGN); /* interrupts itself... */
  3449. #ifdef COMMENT
  3450.      while (((wstat = wait(
  3451. #ifdef OSF40
  3452.       &statusp_w
  3453. #else
  3454.       &statusp
  3455. #endif /* OSF40 */
  3456.       )) != pid)
  3457.        && (wstat != -1))
  3458.   ;
  3459. #else  /* Not COMMENT */
  3460.      while (1) {
  3461.     wstat = wait(
  3462. #ifdef OSF40
  3463.  &statusp_w
  3464. #else
  3465.  &statusp
  3466. #endif /* OSF40 */
  3467.  );
  3468.     debug(F101,"ttruncmd wait","",wstat);
  3469.     if (wstat == pid || wstat == -1)
  3470.       break;
  3471. }
  3472. #endif /* COMMENT */
  3473. #ifdef OSF40
  3474. statusp = (*(int *)&(statusp_w));
  3475. #endif /* OSF40 */
  3476. pexitstat = (statusp & 0xff) ? statusp : statusp >> 8;
  3477. debug(F101,"ttruncmd wait statusp","",statusp);
  3478. debug(F101,"ttruncmd wait pexitstat","",pexitstat);
  3479. signal(SIGINT,istat); /* Restore interrupts */
  3480. signal(SIGQUIT,qstat);
  3481.     }
  3482.     concb((char)escchr); /* Restore console to CBREAK mode */
  3483.     return(statusp == 0 ? 1 : 0);
  3484. }
  3485. #endif /* COMMENT */
  3486. #endif /* CK_REDIR */
  3487. struct tm *
  3488. #ifdef CK_ANSIC
  3489. cmdate2tm(char * date, int gmt)         /* date as "yyyymmdd hh:mm:ss" */
  3490. #else
  3491. cmdate2tm(date,gmt) char * date; int gmt;
  3492. #endif
  3493. {
  3494.     /* date as "yyyymmdd hh:mm:ss" */
  3495.     static struct tm _tm;
  3496.     time_t now;
  3497.     if (strlen(date) != 17 ||
  3498. date[8] != ' ' ||
  3499. date[11] != ':' ||
  3500. date[14] != ':')
  3501.       return(NULL);
  3502.     time(&now);
  3503.     if (gmt)
  3504.       _tm = *gmtime(&now);
  3505.     else
  3506.       _tm = *localtime(&now);
  3507.     _tm.tm_year = (date[0]-'0')*1000 + (date[1]-'0')*100 +
  3508.                   (date[2]-'0')*10   + (date[3]-'0')-1900;
  3509.     _tm.tm_mon  = (date[4]-'0')*10   + (date[5]-'0')-1;
  3510.     _tm.tm_mday = (date[6]-'0')*10   + (date[7]-'0');
  3511.     _tm.tm_hour = (date[9]-'0')*10   + (date[10]-'0');
  3512.     _tm.tm_min  = (date[12]-'0')*10  + (date[13]-'0');
  3513.     _tm.tm_sec  = (date[15]-'0')*10  + (date[16]-'0');
  3514.     _tm.tm_wday = 0;
  3515.     _tm.tm_yday = 0;
  3516.     return(&_tm);
  3517. }
  3518. #ifdef OXOS
  3519. #undef kill
  3520. #endif /* OXOS */
  3521. #ifdef OXOS
  3522. int
  3523. priv_kill(pid, sig) int pid, sig; {
  3524.     int i;
  3525.     if (priv_on())
  3526. debug(F100,"priv_kill priv_on failed","",0);
  3527.     i = kill(pid, sig);
  3528.     if (priv_off())
  3529. debug(F100,"priv_kill priv_off failed","",0);
  3530.     return(i);
  3531. }
  3532. #endif /* OXOS */
  3533. #ifdef BEOSORBEBOX
  3534. /* #ifdef BE_DR_7 */
  3535. /*
  3536.   alarm() function not supplied with Be OS DR7 - this one contributed by
  3537.   Neal P. Murphy.
  3538. */
  3539. /*
  3540.   This should mimic the UNIX/POSIX alarm() function well enough, with the
  3541.   caveat that one's SIGALRM handler must call alarm_expired() to clean up vars
  3542.   and wait for the alarm thread to finish.
  3543. */
  3544. unsigned int
  3545. alarm(unsigned int seconds) {
  3546.     long time_left = 0;
  3547. /* If an alarm is active, turn it off, saving the unused time */
  3548.     if (alarm_thread != -1) {
  3549.         /* We'll be generous and count partial seconds as whole seconds. */
  3550.         time_left = alarm_struct.time -
  3551.   ((system_time() - time_started) / 1000000.0);
  3552.         /* Kill the alarm thread */
  3553.         kill_thread (alarm_thread);
  3554.         /* We need to clean up as though the alarm occured. */
  3555.         time_started = 0;
  3556.         alarm_struct.thread = -1;
  3557.         alarm_struct.time = 0;
  3558.         alarm_expired();
  3559.     }
  3560. /* Set a new alarm clock, if requested. */
  3561.     if (seconds > 0) {
  3562.         alarm_struct.thread = find_thread(NULL);
  3563.         alarm_struct.time = seconds;
  3564.         time_started = system_time();
  3565.         alarm_thread = spawn_thread (do_alarm,
  3566.                                      "alarm_thread",
  3567.                                      B_NORMAL_PRIORITY,
  3568.                                      (void *) &alarm_struct
  3569.      );
  3570.         resume_thread (alarm_thread);
  3571.     }
  3572. /* Now return [unused time | 0] */
  3573.     return ((unsigned int) time_left);
  3574. }
  3575. /*
  3576.   This function is the departure from UNIX/POSIX alarm handling. In the case
  3577.   of Be's missing alarm() function, this stuff needs to be done in the SIGALRM
  3578.   handler. When Be implements alarm(), this function call can be eliminated
  3579.   from user's SIGALRM signal handlers.
  3580. */
  3581. void
  3582. alarm_expired(void) {
  3583.     long ret_val;
  3584.     if (alarm_thread != -1) {
  3585.         wait_for_thread (alarm_thread, &ret_val);
  3586.         alarm_thread = -1;
  3587.     }
  3588. }
  3589. /*
  3590.   This is the function that snoozes the requisite number of seconds and then
  3591.   SIGALRMs the calling thread. Note that kill() wants a pid_t arg, whilst Be
  3592.   uses thread_id; currently they are both typdef'ed as long, but I'll do the
  3593.   cast anyway. This function is run in a separate thread.
  3594. */
  3595. long
  3596. do_alarm (void *alarm_struct) {
  3597.     snooze ((double) ((struct ALARM_STRUCT *) alarm_struct)->time * 1000000.0);
  3598.     kill ((pid_t)((struct ALARM_STRUCT *) alarm_struct)->thread, SIGALRM);
  3599.     time_started = 0;
  3600.     ((struct ALARM_STRUCT *) alarm_struct)->thread = -1;
  3601.     ((struct ALARM_STRUCT *) alarm_struct)->time = 0;
  3602. }
  3603. /* #endif */ /* BE_DR_7 */
  3604. #endif /* BEOSORBEBOX */
  3605. #ifdef Plan9
  3606. int
  3607. p9ttyctl(char letter, int num, int param) {
  3608.     char cmd[20];
  3609.     int len;
  3610.     if (ttyctlfd < 0)
  3611.       return -1;
  3612.     cmd[0] = letter;
  3613.     if (num)
  3614.       len = sprintf(cmd + 1, "%d", param) + 1;
  3615.     else {
  3616. cmd[1] = param;
  3617. len = 2;
  3618.     }
  3619.     if (write(ttyctlfd, cmd, len) == len) {
  3620. cmd[len] = 0;
  3621. /* fprintf(stdout, "wrote '%s'n", cmd); */
  3622. return 0;
  3623.     }
  3624.     return -1;
  3625. }
  3626. int
  3627. p9ttyparity(char l) {
  3628.     return p9ttyctl('p', 0, l);
  3629. }
  3630. int
  3631. p9tthflow(int flow, int status) {
  3632.     return p9ttyctl('m', 1, status);
  3633. }
  3634. int
  3635. p9ttsspd(int cps) {
  3636.     if (p9ttyctl('b', 1, cps * 10) < 0)
  3637.       return -1;
  3638.     ttylastspeed = cps * 10;
  3639.     return 0;
  3640. }
  3641. int
  3642. p9openttyctl(char *ttname) {
  3643.     char name[100];
  3644.     if (ttyctlfd >= 0) {
  3645. close(ttyctlfd);
  3646. ttyctlfd = -1;
  3647. ttylastspeed = -1;
  3648.     }
  3649.     sprintf(name, "%sctl", ttname);
  3650.     ttyctlfd = open(name, 1);
  3651.     return ttyctlfd;
  3652. }
  3653. int
  3654. p9concb() {
  3655.     if (consctlfd >= 0) {
  3656. if (write(consctlfd, "rawon", 5) == 5)
  3657.   return 0;
  3658.     }
  3659.     return -1;
  3660. }
  3661. int
  3662. p9conbin() {
  3663.     return p9concb();
  3664. }
  3665. int
  3666. p9conres() {
  3667.     if (consctlfd >= 0) {
  3668. if (write(consctlfd, "rawoff", 6) == 6)
  3669.   return 0;
  3670.     }
  3671.     return -1;
  3672. }
  3673. int
  3674. p9sndbrk(int msec) {
  3675.     if (ttyctlfd >= 0) {
  3676. char cmd[20];
  3677. int i = sprintf(cmd, "k%d", msec);
  3678. if (write(ttyctlfd, cmd, i) == i)
  3679.   return 0;
  3680.     }
  3681.     return -1;
  3682. }
  3683. int
  3684. conwrite(char *buf, int n) {
  3685.     int x;
  3686.     static int length = 0;
  3687.     static int holdingcr = 0;
  3688.     int normal = 0;
  3689.     for (x = 0; x < n; x++) {
  3690. char c = buf[x];
  3691. if (c == 007) {
  3692.     if (normal) {
  3693. write(1, buf + (x - normal), normal);
  3694. length += normal;
  3695. normal = 0;
  3696.     }
  3697.     /* write(noisefd, "1000 300", 8); */
  3698.     holdingcr = 0;
  3699. } else if (c == 'r') {
  3700.     if (normal) {
  3701. write(1, buf + (x - normal), normal);
  3702. length += normal;
  3703. normal = 0;
  3704.     }
  3705.     holdingcr = 1;
  3706. } else if (c == 'n') {
  3707.     write(1, buf + (x - normal), normal + 1);
  3708.     normal = 0;
  3709.     length = 0;
  3710.     holdingcr = 0;
  3711. } else if (c == 'b') {
  3712.     if (normal) {
  3713. write(1, buf + (x - normal), normal);
  3714. length += normal;
  3715. normal = 0;
  3716.     }
  3717.     if (length) {
  3718. write(1, &c, 1);
  3719. length--;
  3720.     }
  3721.     holdingcr = 0;
  3722. } else {
  3723.     if (holdingcr) {
  3724. char b = 'b';
  3725. while (length-- > 0)
  3726.   write(1, &b, 1);
  3727. length = 0; /* compiler bug */
  3728.     }
  3729.     holdingcr = 0;
  3730.     normal++;
  3731. }
  3732.     }
  3733.     if (normal) {
  3734. write(1, buf + (x - normal), normal);
  3735. length += normal;
  3736.     }
  3737.     return n;
  3738. }
  3739. void
  3740. conprint(char *fmt, ...) {
  3741.     char buf[1000];
  3742.     va_list ap;
  3743.     int i;
  3744.     va_start(ap, fmt);
  3745.     i = vsprintf(buf, fmt, ap);
  3746.     conwrite(buf, i);
  3747. }
  3748. #endif /* Plan9 */
  3749. /* fprintf, printf, perror replacements... */
  3750. /* f p r i n t f */
  3751. #ifdef UNIX
  3752. #ifdef CK_ANSIC
  3753. #include <stdarg.h>
  3754. #else /* CK_ANSIC */
  3755. #include <varargs.h>
  3756. #endif /* CK_ANSIC */
  3757. static char str1[1024];
  3758. static char str2[1024];
  3759. #ifdef fprintf
  3760. #undef fprintf
  3761. int
  3762. #ifdef CK_ANSIC
  3763. ckxfprintf(FILE * file, const char * format, ...)
  3764. #else /* CK_ANSIC */
  3765. ckxfprintf(va_alist) va_dcl
  3766. #endif /* CK_ANSIC */
  3767. /* ckxfprintf */ {
  3768.     int i, j, len, got_cr;
  3769.     va_list args;
  3770.     int rc = 0;
  3771. #ifdef CK_ANSIC
  3772.     va_start(args, format);
  3773. #else /* CK_ANSIC */
  3774.     char * format;
  3775.     FILE * file;
  3776.     va_start(args);
  3777.     file = va_arg(args,FILE *);
  3778.     format = va_arg(args,char *);
  3779. #endif /* CK_ANSIC */
  3780.     if (!inserver || (file != stdout && file != stderr && file != stdin)) {
  3781. rc = vfprintf(file,format,args);
  3782.     } else {
  3783. unsigned int c;
  3784.         rc = vsprintf(str1, format, args);
  3785.         for (i = 0, j = 0, len = strlen(str1), got_cr = 0;
  3786.      i < len && j < 1022;
  3787.      i++, j++ ) {
  3788.     /* We can't use 255 as a case label because of signed chars */
  3789.     c = (unsigned)(str1[i] & 0xff);
  3790. #ifdef TNCODE
  3791.     if (c == 255) {
  3792. if (got_cr && !TELOPT_ME(TELOPT_BINARY))
  3793.   str2[j++] = '';
  3794. str2[j++] = IAC;
  3795. str2[j] = IAC;
  3796. got_cr = 0;
  3797.     } else
  3798. #endif /* TNCODE */
  3799.     switch (c) {
  3800.       case 'r':
  3801.                 if (got_cr
  3802. #ifdef TNCODE
  3803.     && !TELOPT_ME(TELOPT_BINARY)
  3804. #endif /* TNCODE */
  3805.     )
  3806.   str2[j++] = '';
  3807.                 str2[j] = str1[i];
  3808.                 got_cr = 1;
  3809.                 break;
  3810.       case 'n':
  3811.                 if (!got_cr)
  3812.   str2[j++] = 'r';
  3813.                 str2[j] = str1[i];
  3814.                 got_cr = 0;
  3815.                 break;
  3816.       default:
  3817.                 if (got_cr
  3818. #ifdef TNCODE
  3819.     && !TELOPT_ME(TELOPT_BINARY)
  3820. #endif /* TNCODE */
  3821.     )
  3822.   str2[j++] = '';
  3823.                 str2[j] = str1[i];
  3824.                 got_cr = 0;
  3825.             }
  3826.         }
  3827.         if (got_cr
  3828. #ifdef TNCODE
  3829.              && !TELOPT_ME(TELOPT_BINARY)
  3830. #endif /* TNCODE */
  3831.              )
  3832.             str2[j++] = '';
  3833. #ifdef CK_ENCRYPTION
  3834. #ifdef TNCODE
  3835.         if (TELOPT_ME(TELOPT_ENCRYPTION))
  3836.   ck_tn_encrypt(str2,j);
  3837. #endif /* TNCODE */
  3838. #endif /* CK_ENCRYPTION */
  3839. #ifdef CK_SSL
  3840. if (inserver && ssl_active_flag) {
  3841.     /* Write using SSL */
  3842.     rc = SSL_write(ssl_con, str2, j);
  3843.     debug(F111,"ckxfprintf","SSL_write",rc);
  3844. } else if (inserver && tls_active_flag) {
  3845.     /* Write using SSL */
  3846.     rc = SSL_write(tls_con, str2, j);
  3847.     debug(F111,"ckxfprintf","TLS_write",rc);
  3848. } else
  3849. #endif /* CK_SSL */
  3850.         fwrite(str2,sizeof(char),j,stdout);
  3851.     }
  3852.     va_end(args);
  3853.     return(rc);
  3854. }
  3855. #endif /* fprintf */
  3856. /* p r i n t f */
  3857. #ifdef printf
  3858. #undef printf
  3859. int
  3860. #ifdef CK_ANSIC
  3861. ckxprintf(const char * format, ...)
  3862. #else /* CK_ANSIC */
  3863. ckxprintf(va_alist) va_dcl
  3864. #endif /* CK_ANSIC */
  3865. /* ckxprintf */ {
  3866.     int i, j, len, got_cr;
  3867.     va_list args;
  3868.     int rc = 0;
  3869. #ifdef CK_ANSIC
  3870.     va_start(args, format);
  3871. #else /* CK_ANSIC */
  3872.     char * format;
  3873.     va_start(args);
  3874.     format = va_arg(args,char *);
  3875. #endif /* CK_ANSIC */
  3876.     if (!inserver) {
  3877. rc = vprintf(format, args);
  3878.     } else {
  3879. unsigned int c;
  3880.         rc = vsprintf(str1, format, args);
  3881.         for (i = 0, j = 0, len = strlen(str1), got_cr=0;
  3882.      i < len && j < 1022;
  3883.      i++, j++ ) {
  3884.     c = (unsigned)(str1[i] & 0xff);
  3885. #ifdef TNCODE
  3886.     if (c == 255) {
  3887. if (got_cr && !TELOPT_ME(TELOPT_BINARY))
  3888.   str2[j++] = '';
  3889. str2[j++] = IAC;
  3890. str2[j] = IAC;
  3891. got_cr = 0;
  3892.     } else
  3893. #endif /* TNCODE */
  3894.     switch (c) {
  3895.       case 'r':
  3896.                 if (got_cr
  3897. #ifdef TNCODE
  3898.     && !TELOPT_ME(TELOPT_BINARY)
  3899. #endif /* TNCODE */
  3900.     )
  3901.   str2[j++] = '';
  3902.                 str2[j] = str1[i];
  3903.                 got_cr = 1;
  3904.                 break;
  3905.       case 'n':
  3906.                 if (!got_cr)
  3907.   str2[j++] = 'r';
  3908.                 str2[j] = str1[i];
  3909.                 got_cr = 0;
  3910.                 break;
  3911.       default:
  3912.                 if (got_cr
  3913. #ifdef TNCODE
  3914.     && !TELOPT_ME(TELOPT_BINARY)
  3915. #endif /* TNCODE */
  3916.     )
  3917.   str2[j++] = '';
  3918.                 str2[j] = str1[i];
  3919.                 got_cr = 0;
  3920.                 break;
  3921.     }
  3922.         }
  3923.         if (got_cr
  3924. #ifdef TNCODE
  3925.              && !TELOPT_ME(TELOPT_BINARY)
  3926. #endif /* TNCODE */
  3927.              )
  3928.             str2[j++] = '';
  3929. #ifdef CK_ENCRYPTION
  3930. #ifdef TNCODE
  3931.         if (TELOPT_ME(TELOPT_ENCRYPTION))
  3932.   ck_tn_encrypt(str2,j);
  3933. #endif /* TNCODE */
  3934. #endif /* CK_ENCRYPTION */
  3935. #ifdef CK_SSL
  3936.           if (inserver && ssl_active_flag) {
  3937.               /* Write using SSL */
  3938.               rc = SSL_write(ssl_con, str2, j);
  3939.               debug(F111,"ckxprintf","SSL_write",rc);
  3940.           } else if (inserver && tls_active_flag) {
  3941.               /* Write using SSL */
  3942.               rc = SSL_write(tls_con, str2, j);
  3943.               debug(F111,"ckxprintf","TLS_write",rc);
  3944.           } else
  3945. #endif /* CK_SSL */
  3946.     rc = fwrite(str2,sizeof(char),j,stdout);
  3947.     }
  3948.     va_end(args);
  3949.     return(rc);
  3950. }
  3951. #endif /* printf */
  3952. /*  p e r r o r  */
  3953. #ifdef perror
  3954. #undef perror
  3955. _PROTOTYP(char * ck_errstr,(VOID));
  3956. #ifdef NEXT
  3957. void
  3958. #else
  3959. #ifdef CK_SCOV5
  3960. void
  3961. #else
  3962. int
  3963. #endif /* CK_SCOV5 */
  3964. #endif /* NEXT */
  3965. #ifdef CK_ANSIC
  3966. ckxperror(const char * str)
  3967. #else /* CK_ANSIC */
  3968. ckxperror(str) char * str;
  3969. #endif /* CK_ANSIC */
  3970. /* ckxperror */ {
  3971.     char * errstr = ck_errstr();
  3972. #ifndef NEXT
  3973. #ifndef CK_SCOV5
  3974.     return
  3975. #endif /* CK_SCOV5 */
  3976. #endif /* NEXT */
  3977.       ckxprintf("%s%s %sn",str,*errstr?":":"",errstr);
  3978. }
  3979. #endif /* perror */
  3980. #endif /* UNIX */
  3981. #ifdef MINIX2
  3982. /* Minix doesn't have a gettimeofday call. We fake one here using time(2) */
  3983. int
  3984. gettimeofday(struct timeval *tp, struct timezone *tzp) {
  3985.     tp->tv_usec = 0L; /* Close enough for horseshoes */
  3986.     if(time(&(tp->tv_sec))==-1)
  3987.       return(-1);
  3988.     return(0);
  3989. }
  3990. /* Minix does not support symbolic links. We implement a version of
  3991.    readlink that always fails */
  3992. int
  3993. readlink(const char *path, void *buf, size_t bufsiz) {
  3994.     errno = ENOSYS;
  3995.     return(-1);
  3996. }
  3997. #endif /* MINIX2 */