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

通讯/手机编程

开发平台:

Windows_Unix

  1.     printf("UUCP not installed or Kermit misconfiguredn");
  2. } else {
  3.     if (!quiet)
  4.       perror(lockdir);
  5.     unlink(tmpnam); /* Get rid of the temporary file. */
  6. }
  7. priv_off(); /* Turn off privileges!!! */
  8. return(-1); /* Return failure code. */
  9.     }
  10. /* Now write the pid into the temp lockfile in the appropriate format */
  11. #ifdef PIDSTRING /* For Honey DanBer UUCP, */
  12.     sprintf( /* write PID as decimal string */
  13.     pid_str,
  14. #ifdef LINUXFSSTND /* The "Linux File System Standard" */
  15. #ifdef FSSTND10 /* Version 1.0 calls for */
  16.     "%010dn", /* leading zeros */
  17. #else /* while version 1.2 calls for */
  18.     "%10dn", /* leading spaces */
  19. #endif /* FSSTND10 */
  20. #else
  21. #ifdef COHERENT
  22.     "%dn", /* with leading nothing */
  23. #else
  24.     "%10dn", /* with leading blanks */
  25. #endif /* COHERENT */
  26. #endif /* LINUXFSSTND */
  27.     (int) pid
  28.     );
  29.     write(lockfd, pid_str, 11);
  30.     debug(F111,"ttlock hdb pid string",pid_str,(int) pid);
  31. #else /* Not PIDSTRING, use integer PID */
  32.     write(lockfd, (char *)&pid, sizeof(pid) );
  33.     debug(F101,"ttlock pid","",(int) pid);
  34. #endif /* PIDSTRING */
  35. /* Now try to rename the temp file to the real lock file name. */
  36. /* This will fail if a lock file of that name already exists.  */
  37.     close(lockfd); /* Close the temp lockfile. */
  38.     chmod(tmpnam,0444); /* Permission for a valid lock. */
  39.     tries = 0;
  40.     while (!haslock && tries++ < 2) {
  41. haslock = (link(tmpnam,flfnam) == 0); /* Create a link to it. */
  42. if (haslock) {       /* If we got the lockfile */
  43. #ifdef RTAIX
  44.     link(flfnam,lkflfn);
  45. #endif /* RTAIX */
  46. #ifdef CKSYMLINK
  47.     if (islink && lock2[0])
  48.       link(flfnam,lock2);
  49. #endif /* CKSYMLINK */
  50. #ifdef LOCKF
  51. /*
  52.   Advisory file locking works on SVR4, so we use it.  In fact, it is
  53.   necessary in some cases, e.g. when SLIP is involved.  But it still doesn't
  54.   seem to prevent multiple users accessing the same device by different names.
  55. */
  56.             while (lockf(ttyfd, F_TLOCK, 0L) != 0) {
  57.                 debug(F111, "ttlock: lockf returns errno", "", errno);
  58.                 if ((++tries >= 3) || (errno != EAGAIN)) {
  59.                     x = unlink(flfnam); /* remove the lockfile */
  60. #ifdef RTAIX
  61.     unlink(lkflfn); /* And any links to it... */
  62. #endif /* RTAIX */
  63. #ifdef CKSYMLINK
  64.     if (islink && lock2[0])
  65.       unlink(lock2); /* ditto... */
  66. #endif /* CKSYMLINK */
  67.                     debug(F111,"ttlock unlink",flfnam,x);
  68.                     haslock = 0;
  69.     break;
  70. }
  71.                 sleep(2);
  72.     }
  73.     if (haslock) /* If we got an advisory lock */
  74. #endif /* LOCKF */
  75.       break; /* We're done. */
  76. } else { /* We didn't create a new lockfile. */
  77.     priv_off();
  78.     if (ttchkpid(flfnam)) { /* Check existing lockfile */
  79. priv_on(); /* cause ttchkpid turns priv_off... */
  80. unlink(tmpnam); /* Delete the tempfile */
  81. debug(F100,"ttlock found tty locked","",0);
  82. priv_off(); /* Turn off privs */
  83. return(-2); /* Code for device is in use. */
  84.     }
  85.     priv_on();
  86. }
  87.     }
  88.     unlink(tmpnam); /* Unlink (remove) the temp file. */
  89.     priv_off(); /* Turn off privs */
  90.     return(haslock ? 0 : -1); /* Return link's return code. */
  91. #else /* HPUX */
  92. /*
  93.   HP-UX gets its own copy of this routine, modeled after the observed behavior
  94.   of the HP-UX 'cu' program.  HP-UX serial device names consist of a base name
  95.   such as "tty", "ttyd", "cua", "cul", "cuad", or "culd", followed by a unit
  96.   designator which is a string of digits, possibly containing an imbedded
  97.   letter "p".  Examples (for base name "tty"):
  98.      /dev/tty0, /dev/tty00, dev/ttyd00, /dev/tty0p0
  99.   According to the HP-UX UUCP manual of 1988, the "0p0" notation has been
  100.   used on Series 800 since HP-UX 2.00, and the "non-p" notation was used
  101.   on other models.  In HP-UX 10.00, "0p0" notation was adopted for all models.
  102.   However, we make and enforce no such distinctions; either notation is
  103.   accepted on any model or HP-UX version as a valid unit designator.
  104.   If a valid unit is specified (as opposed to a designer name or symlink), we
  105.   check for all aliases of the given unit according to the devprefix[] array.
  106.   If no lockfiles are found for the given unit, we can have the device; we
  107.   create a lockfile LCK..name in the lockfile directory appropriate for the
  108.   HP-UX version (/var/spool/locks for 10.00 and later, /usr/spool/uucp for
  109.   9.xx and earlier).  If it is a "cua" or "cul" device, a second lockfile is
  110.   created with the "ttyd" prefix.  This is exactly what cu does.
  111.   If the "set line" device does not have a valid unit designator, then it is
  112.   used literally and no synomyms are searched for and only one lockfile is
  113.   created.
  114.   -fdc, March 1998.
  115. */
  116. #define LFNAML 80 /* Max length for lock file name. */
  117.     int lockfd; /* File descriptor for lock file. */
  118.     PID_T pid; /* Process ID of this process. */
  119.     int fpid; /* pid found in existing lockfile. */
  120.     int tries; /* How many times we've tried... */
  121.     int i, k; /* Workers */
  122.     char *device, *devname; /* "/dev/xxx", "xxx" */
  123.     char *unit, *p; /* <instance>p<port> part of xxx */
  124.     char lockfil[LFNAML]; /* Lockfile name (no path) */
  125.     char tmpnam[LFNAML]; /* Temporary lockfile name. */
  126. #ifdef HPUX10 /* Lockfile directory */
  127.     char *lockdir = "/var/spool/locks"; /* Always this for 10.00 and higher */
  128. #else  /* HP-UX 9.xx and below */
  129. #ifdef LOCK_DIR
  130.     char *lockdir = LOCK_DIR; /* Defined near top of this file */
  131. #else
  132.     char *lockdir = "/usr/spool/uucp"; /* or not... */
  133. #endif /* LOCK_DIR */
  134. #endif /* HPUX10 */
  135.     haslock = 0;                        /* Not locked yet. */
  136.     *flfnam = ''; /* Lockfile name is empty. */
  137.     lock2[0] = ''; /* Second one too. */
  138.     pid = getpid(); /* Get my process ID */
  139. /*
  140.   Construct name of lockfile and temporary file...
  141.   device  = name of tty device without the path, e.g. "tty0p0"
  142.   lockfil = name of lock file, without path, e.g. "LCK..tty0p0"
  143. */
  144.     device = ((devname = xxlast(ttdev,'/')) != NULL ? devname+1 : ttdev);
  145.     debug(F110,"TTLOCK device",device,0);
  146.     sprintf(lockfil,"LCK..%s", device);
  147.     k = 0; /* Assume device is not locked */
  148.     n = 0; /* Digit counter */
  149.     unit = device; /* Unit = <instance>p<port> */
  150.     while (*unit && !isdigit(*unit)) /* Search for digit... */
  151.       unit++;
  152.     p = unit; /* Verify <num>p<num> format... */
  153.     debug(F110,"TTLOCK unit 1",unit,0);
  154. /*
  155.   The unit number is recognized as:
  156.   (a) any sequence of digits that runs to the end of the string.
  157.   (b) any (a) that includes one and only one letter "p", with at least
  158.       one digit before and after it.
  159. */
  160.     while (isdigit(*p)) p++, n++; /* Get a run of digits */
  161.     if (*p && n > 0) { /* Have a "p"? */
  162. if (*p == 'p' && isdigit(*(p+1))) {
  163.     p++;
  164.     n = 0;
  165.     while (isdigit(*p)) p++, n++;
  166. }
  167.     }
  168.     if (n == 0 || *p) unit = "";
  169.     debug(F110,"TTLOCK unit 2",unit,0);
  170.     if (*unit) { /* Device name has unit number. */
  171. /* The following loop not only searches for the various lockfile    */
  172. /* synonyms, but also removes all -- not just one -- stale lockfile */
  173. /* for the device, should there be more than one.  See ttchkpid().  */
  174. ttydexists = 0;
  175. for (i = 0; *devprefix[i]; i++) { /* For each driver... */
  176.     /* Make device name */
  177.     sprintf(lock2,"/dev/%s%s",devprefix[i],unit);
  178.     priv_on(); /* Privs on */
  179.     k = zchki(lock2) != -1; /* See if device exists */
  180.     priv_off(); /* Privs off */
  181.     debug(F111,"TTLOCK exist",lock2,k);
  182.             if (k) {
  183. if (!strcmp(devprefix[i],"ttyd")) /* ttyd device exists */
  184.   ttydexists = 1;
  185. /* Make lockfile name */
  186. sprintf(lock2,"%s/LCK..%s%s",lockdir,devprefix[i],unit);
  187. debug(F110,"TTLOCK checking",lock2,0);
  188. priv_on(); /* Privs on */
  189. k = zchki(lock2) != -1; /* See if lockfile exists */
  190. priv_off(); /* Privs off */
  191. debug(F111,"TTLOCK check for lock A",lock2,k);
  192. if (k) if (ttchkpid(lock2)) { /* If pid still active, fail. */
  193.     ckstrncpy(flfnam,lock2,FLFNAML);
  194.     return(-2);
  195. }
  196.     }
  197. }
  198.     } else { /* Some other device-name format */
  199. /* This takes care of symbolic links, etc... */
  200. /* But does not chase them down! */
  201. sprintf(lock2,"%s/LCK..%s",lockdir,device); /* Use the name as-is */
  202. priv_on();
  203. k = zchki(lock2) != -1; /* Check for existing lockfile */
  204. priv_off();
  205. debug(F111,"TTLOCK check for lock B",lock2,k);
  206. if (k) if (ttchkpid(lock2)) { /* Check pid from lockfile */
  207.     ckstrncpy(flfnam,lock2,FLFNAML);
  208.     debug(F110,"TTLOCK in use",device,0);
  209.     debug(F101,"TTLOCK returns","",-2);
  210.     return(-2);
  211. }
  212.     }
  213. /*
  214.   Get here only if there is no (more) lockfile, so now we make one (or two)...
  215.   flfnam = full lockfile pathname, e.g. "/usr/spool/uucp/LCK..cul0p0".
  216.   tmpnam = unique temporary filname, e.g. "/usr/spool/uucp/LTMP..pid".
  217. */
  218.     sprintf(flfnam,"%s/%s",lockdir,lockfil); /* Our SET LINE device */
  219.     /* If dialout device, also make one for corresponding dialin device */
  220.     lock2[0] = '';
  221.     if (!strncmp(device,"cu",2) && *unit && ttydexists)
  222.       sprintf(lock2, "%s/LCK..ttyd%s", lockdir, unit);
  223.     sprintf(tmpnam,"%s/LTMP.%05d",lockdir,(int) pid); /* Make temporary name */
  224. #ifdef DEBUG
  225.     if (deblog) {
  226. debug(F110,"TTLOCK flfnam",flfnam,0);
  227. debug(F110,"TTLOCK lock2",lock2,0);
  228. debug(F110,"TTLOCK tmpnam",tmpnam,0);
  229.     }
  230. #endif /* DEBUG */
  231. /*
  232.    Lockfile permissions...
  233.    444 is standard, HP-UX 10.00 uses 664.  It doesn't matter.
  234.    Kermit uses 444; the difference lets us tell whether Kermit created
  235.    the lock file.
  236. */
  237.     priv_on(); /* Turn on privileges. */
  238.     lockfd = creat(tmpnam, 0444); /* Try to create temporary file. */
  239.     if (lockfd < 0) { /* Create failed. */
  240. debug(F111,"TTLOCK creat failed",tmpnam,errno);
  241. if (errno == ENOENT) {
  242.     perror(lockdir);
  243.     printf("UUCP not installed or Kermit misconfiguredn");
  244. } else {
  245.     if (!quiet)
  246.       perror(lockdir);
  247.     unlink(tmpnam); /* Get rid of the temporary file. */
  248. }
  249. priv_off(); /* Turn off privileges!!! */
  250. debug(F101,"TTLOCK returns","",-1);
  251. return(-1); /* Return failure code. */
  252.     }
  253.     debug(F110,"TTLOCK temp ok",tmpnam,0);
  254. /* Now write our pid into the temp lockfile in integer format. */
  255.     i = write(lockfd, (char *)&pid, sizeof(pid));
  256. #ifdef DEBUG
  257.     if (deblog) {
  258. debug(F101,"TTLOCK pid","",pid);
  259. debug(F101,"TTLOCK sizeof pid","",sizeof(pid));
  260. debug(F101,"TTLOCK write pid returns","",i);
  261.     }
  262. #endif /* DEBUG */
  263. /*
  264.   Now try to rename the temporary file to the real lockfile name.
  265.   This will fail if a lock file of that name already exists, which
  266.   will catch race conditions with other users.
  267. */
  268.     close(lockfd); /* Close the temp lockfile. */
  269.     chmod(tmpnam,0444);
  270.     tries = 0;
  271.     while (!haslock && tries++ < 2) {
  272. haslock = (link(tmpnam,flfnam) == 0); /* Create a link to it. */
  273. debug(F101,"TTLOCK link","",haslock);
  274. if (haslock) { /* If we made the lockfile... */
  275. #ifdef LOCKF /* Can be canceled with -DNOLOCKF */
  276. /*
  277.   Create an advisory lock on the device through its file descriptor.
  278.   This code actually seems to work.  If it is executed, and then another
  279.   process tries to open the same device under a different name to circumvent
  280.   the lockfile, they get a "device busy" error.
  281. */
  282.     debug(F100,"TTLOCK LOCKF code...","",0);
  283.             while ( lockf(ttyfd, F_TLOCK, 0L) != 0 ) {
  284.                 debug(F111, "TTLOCK lockf error", "", errno);
  285.                 if ((++tries >= 3) || (errno != EAGAIN)) {
  286.                     x = unlink(flfnam); /* Remove the lockfile */
  287.     if (errno == EACCES && !quiet)
  288.       printf("Device already locked by another processn");
  289.                     haslock = 0;
  290.     break;
  291. }
  292.                 sleep(2);
  293.     }
  294. #endif /* LOCKF */
  295.     if (haslock) { /* If we made the lockfile ... */
  296. if (lock2[0]) { /* if there is to be a 2nd lockfile */
  297.     lockfd = creat(lock2, 0444); /* Create it */
  298.     debug(F111,"TTLOCK lock2 creat", lock2, lockfd);
  299.     if (lockfd > -1) { /* Created OK, write pid. */
  300. write(lockfd, (char *)&pid, sizeof(pid) );
  301. close(lockfd); /* Close and */
  302. chmod(lock2, 0444); /* set permissions. */
  303.     } else {  /* Not OK, but don't fail. */
  304. lock2[0] = ''; /* Just remember it's not there. */
  305.     }
  306. }
  307. break; /* and we're done. */
  308.     }
  309. }
  310.     }
  311.     unlink(tmpnam); /* Unlink (remove) the temp file. */
  312.     priv_off(); /* Turn off privs */
  313.     i = haslock ? 0 : -1; /* Our return value */
  314.     debug(F101,"TTLOCK returns","",i);
  315.     return(i);
  316. #endif /* HPUX */
  317. #endif /* USETTYLOCK */
  318. #endif /* !NOUUCP */
  319. }
  320. /*  T T U N L O C K  */
  321. static int
  322. ttunlck() {                             /* Remove UUCP lockfile(s). */
  323. #ifndef NOUUCP
  324.     int x;
  325.     debug(F111,"ttunlck",flfnam,haslock);
  326. #ifdef USETTYLOCK
  327.     if (haslock && *flfnam) {
  328. int x;
  329. priv_on(); /* Turn on privs */
  330. #ifdef USE_UU_LOCK
  331. x = uu_unlock(lockname);
  332. #else  /* USE_UU_LOCK */
  333. x = ttyunlock(lockname); /* Try to unlock */
  334. #endif /* USE_UU_LOCK */
  335. priv_off(); /* Turn off privs */
  336. if (x < 0 && !quiet)
  337.   printf("Warning - Can't remove lockfile: %sn", flfnam);
  338. *flfnam = ''; /* Erase the name. */
  339. haslock = 0;
  340. return(0);
  341.     }
  342. #else  /* No ttylock()... */
  343.     if (haslock && *flfnam) {
  344. /* Don't remove lockfile if we didn't make it ourselves */
  345. if ((x = ttrpid(flfnam)) != (int)getpid()) {
  346.     debug(F111,"ttunlck lockfile seized",flfnam,x);
  347.     printf("Warning - Lockfile %s seized by pid %dn",
  348.    flfnam,
  349.    x
  350.    );
  351.     return(0);
  352. }
  353. priv_on(); /* Turn privileges on.  */
  354. errno = 0;
  355. x = unlink(flfnam); /* Remove the lockfile. */
  356. debug(F111,"ttunlck unlink",flfnam,x);
  357. if (x < 0) {
  358.     if (errno && !quiet)
  359.       perror(ttnmsv);
  360.     printf("Warning - Can't remove lockfile: %sn", flfnam);
  361. }
  362. haslock = 0;
  363. *flfnam = ''; /* Erase the name. */
  364. #ifdef RTAIX
  365. errno = 0;
  366. x = unlink(lkflfn); /* Remove link to lockfile */
  367. debug(F111,"ttunlck AIX link unlink",lkflfn,x);
  368. if (x < 0) {
  369.     if (errno && !quiet)
  370.       perror(ttnmsv);
  371.     printf("Warning - Can't remove link to lockfile: %sn", lkflfn);
  372. }
  373. *lkflfn = '';
  374. #else
  375. if (lock2[0]) { /* If there is a second lockfile, */
  376.     errno = 0;
  377.     x = unlink(lock2); /*  remove it too. */
  378.     debug(F111,"ttunlck lock2 unlink",lock2,x);
  379.     if (x < 0) {
  380. if (errno && !quiet)
  381.   perror(ttnmsv);
  382. printf("Warning - Can't remove secondary lockfile: %sn",
  383.        lock2
  384.        );
  385.     }
  386.     lock2[0] = ''; /* Forget its name. */
  387. }
  388. #endif /* RTAIX */
  389. #ifdef LOCKF
  390.         (VOID) lockf(ttyfd, F_ULOCK, 0L); /* Remove advisory lock */
  391. #endif /* LOCKF */
  392. priv_off(); /* Turn privileges off. */
  393.     }
  394. #endif /* USETTYLOCK */
  395. #endif /* !NOUUCP */
  396.     return(0);
  397. }
  398. /*
  399.   4.3BSD-style UUCP line direction control.
  400.   (Stan Barber, Rice U, 1980-something...)
  401. */
  402. #ifndef NOUUCP
  403. #ifdef ACUCNTRL
  404. VOID
  405. acucntrl(flag,ttname) char *flag, *ttname; {
  406.     char x[DEVNAMLEN+32], *device, *devname;
  407.     if (strcmp(ttname,CTTNAM) == 0 || xlocal == 0) /* If not local, */
  408.       return; /* just return. */
  409.     device = ((devname = xxlast(ttname,'/')) != NULL ? devname+1 : ttname);
  410.     if (strncmp(device,"LCK..",4) == 0) device += 5;
  411.     sprintf(x,"/usr/lib/uucp/acucntrl %s %s",flag,device);
  412.     debug(F110,"called ",x,0);
  413.     zsyscmd(x);
  414. }
  415. #endif /* ACUCNTRL */
  416. #endif /* NOUUCP */
  417. /*
  418.   T T H F L O W  --  Set or Reset hardware flow control.
  419.   This is an attempt to collect all hardware-flow-control related code
  420.   into a single module.  Thanks to Rick Sladkey and John Kohl for lots of
  421.   help here.  Overview:
  422.   Hardware flow control is not supported in many UNIX implementions.  Even
  423.   when it is supported, there is no (ha ha) "standard" for the programming
  424.   interface.  In general, 4.3BSD and earlier (sometimes), 4.4BSD, System V,
  425.   SunOS, AIX, etc, have totally different methods.  (And, not strictly
  426.   relevant here, the programming interface often brings one only to a no-op
  427.   in the device driver!)
  428.   Among all these, we have two major types of APIs: those in which hardware
  429.   flow control is determined by bits in the same termio/termios/sgtty mode
  430.   word(s) that are used for controlling such items as CBREAK vs RAW mode, and
  431.   which are also used by the ttvt(), ttpkt(), conbin(), and concb() routines
  432.   for changing terminal modes.  And those that use entirely different
  433.   mechanisms.
  434.   In the first category, it is important that any change in the mode bits be
  435.   reflected in the relevant termio(s)/sgtty structure, so that subsequent
  436.   changes to that structure do not wipe out the effects of this routine.  That
  437.   is why a pointer, attrs, to the appropriate structure is passed as a
  438.   parameter to this routine.
  439.   The second category should give us no worries, since any changes to hardware
  440.   flow control accomplished by this routine should not affect the termio(s)/
  441.   sgtty structures, and therefore will not be undone by later changes to them.
  442.   The second argument, status, means to turn on hardware flow control if
  443.   nonzero, and to turn it off if zero.
  444.   Returns: 0 on apparent success, -1 on probable failure.
  445. */
  446. static int
  447. tthflow(flow, status, attrs)
  448.     int flow, /* Type of flow control (ckcdeb.h) */
  449.     status; /* Nonzero = turn it on */
  450. /* Zero = turn it off */
  451. #ifdef BSD44ORPOSIX /* POSIX or BSD44 */
  452.     struct termios *attrs;
  453. #else /* System V */
  454. #ifdef ATTSV
  455. #ifdef ATT7300
  456. #ifdef UNIX351M
  457. /* AT&T UNIX 3.51m can set but not test for hardware flow control */
  458. #define RTSFLOW CTSCD
  459. #define CTSFLOW CTSCD
  460. #endif /* ATT7300 */
  461. #endif /* UNIX351M */
  462.     struct termio *attrs;
  463. #else /* BSD, V7, etc */
  464.     struct sgttyb *attrs; /* sgtty info... */
  465. #endif /* ATTSV */
  466. #endif /* BSD44ORPOSIX */
  467. /* tthflow */ {
  468.     int x = 0; /* tthflow() return code */
  469. #ifdef Plan9
  470.     return p9tthflow(flow, status);
  471. #else
  472. #ifndef OXOS /* NOT Olivetti X/OS... */
  473. /*
  474.   For SunOS 4.0 and later in the BSD environment ...
  475.   The declarations are copied and interpreted from the System V header files,
  476.   so we don't actually have to pull in all the System V junk when building
  477.   C-Kermit for SunOS in the BSD environment, which would be dangerous because
  478.   having those symbols defined would cause us to take the wrong paths through
  479.   the code.  The code in this section is used in both the BSD and Sys V SunOS
  480.   versions.
  481. */
  482. #ifdef SUNOS41
  483. /*
  484.   In SunOS 4.1 and later, we use the POSIX calls rather than ioctl calls
  485.   because GNU CC uses different formats for the _IOxxx macros than regular CC;
  486.   the POSIX forms work for both.  But the POSIX calls are not available in
  487.   SunOS 4.0.
  488. */
  489. #define CRTSCTS 0x80000000 /* RTS/CTS flow control */
  490. #define TCSANOW 0 /* Do it now */
  491.     struct termios {
  492. unsigned long c_iflag; /* Input modes */
  493. unsigned long c_oflag; /* Output modes */
  494. unsigned long c_cflag; /* Control modes */
  495. unsigned long c_lflag; /* Line discipline modes */
  496. char c_line;
  497. CHAR c_cc[17];
  498.     };
  499.     struct termios temp;
  500. _PROTOTYP( int tcgetattr, (int, struct termios *) );
  501. _PROTOTYP( int tcsetattr, (int, int, struct termios *) );
  502. /*
  503.   When CRTSCTS is set, SunOS won't do output unless both CTS and CD are
  504.   asserted.  So we don't set CRTSCTS unless CD is up.  This should be OK,
  505.   since we don't need RTS/CTS during dialing, and after dialing is complete,
  506.   we should have CD.  If not, we still communicate, but without RTS/CTS.
  507. */
  508.     int mflags; /* Modem signal flags */
  509. #ifdef NETCMD
  510.     if (ttpipe) return(0);
  511. #endif /* NETCMD */
  512. #ifdef NETPTY
  513.     if (ttpty) return(0);
  514. #endif /* NETPTY */
  515.     debug(F101,"tthflow SUNOS41 entry status","",status);
  516.     if (!status) { /* Turn hard flow off */
  517. if (tcgetattr(ttyfd, &temp) > -1 && /* Get device attributes */
  518.     (temp.c_cflag & CRTSCTS)) { /* Check for RTS/CTS */
  519.     temp.c_cflag &= ~CRTSCTS; /* It's there, remove it */
  520.     x = tcsetattr(ttyfd,TCSANOW,&temp);
  521. }
  522.     } else { /* Turn hard flow on */
  523. if (ioctl(ttyfd,TIOCMGET,&mflags) > -1 && /* Get modem signals */
  524.     (mflags & TIOCM_CAR)) { /* Check for CD */
  525.     debug(F100,"tthflow SunOS has CD","",0);
  526.     if (tcgetattr(ttyfd, &temp) > -1 && /* Get device attributes */
  527. !(temp.c_cflag & CRTSCTS)) { /* Check for RTS/CTS */
  528. temp.c_cflag |= CRTSCTS; /* Not there, add it */
  529. x = tcsetattr(ttyfd,TCSANOW,&temp);
  530.     }
  531. } else {
  532.     x = -1;
  533.     debug(F100,"tthflow SunOS no CD","",0);
  534. }
  535.     }
  536. #else
  537. #ifdef QNX
  538.     struct termios temp;
  539. #ifdef NETCMD
  540.     if (ttpipe) return(0);
  541. #endif /* NETCMD */
  542. #ifdef NETPTY
  543.     if (ttpty) return(0);
  544. #endif /* NETPTY */
  545.     debug(F101,"tthflow QNX entry status","",status);
  546.     if (tcgetattr(ttyfd, &temp) > -1) { /* Get device attributes */
  547. if (!status) { /* Turn hard flow off */
  548.     if ((temp.c_cflag & (IHFLOW|OHFLOW)) == (IHFLOW|OHFLOW)) {
  549. temp.c_cflag &= ~(IHFLOW|OHFLOW); /* It's there, remove it */
  550. attrs->c_cflag &= ~(IHFLOW|OHFLOW);
  551. x = tcsetattr(ttyfd,TCSANOW,&temp);
  552.     }
  553. } else { /* Turn hard flow on */
  554.     if ((temp.c_cflag & (IHFLOW|OHFLOW)) != (IHFLOW|OHFLOW)) {
  555. temp.c_cflag |= (IHFLOW|OHFLOW); /* Not there, add it */
  556. temp.c_iflag &= ~(IXON|IXOFF);   /* Bye to IXON/IXOFF */
  557. ttraw.c_lflag |= IEXTEN;         /* Must be on */
  558. x = tcsetattr(ttyfd,TCSANOW,&temp);
  559. attrs->c_cflag |= (IHFLOW|OHFLOW);
  560. attrs->c_iflag &= ~(IXON|IXOFF);
  561.     }
  562. }
  563.     } else {
  564. x = -1;
  565. debug(F100, "tthflow QNX getattr fails", "", 0);
  566.     }
  567. #else
  568. #ifdef POSIX_CRTSCTS
  569. /*
  570.   POSIX_CRTSCTS is defined in ckcdeb.h or on CC command line.
  571.   Note: Do not assume CRTSCTS is a one-bit field!
  572. */
  573.     struct termios temp;
  574. #ifdef NETCMD
  575.     if (ttpipe) return(0);
  576. #endif /* NETCMD */
  577. #ifdef NETPTY
  578.     if (ttpty) return(0);
  579. #endif /* NETPTY */
  580.     debug(F101,"tthflow POSIX_CRTSCTS entry status","",status);
  581.     errno = 0;
  582.     x = tcgetattr(ttyfd, &temp);
  583.     debug(F111,"tthflow POSIX_CRTSCTS tcgetattr",ckitoa(x),errno);
  584.     errno = 0;
  585.     if (x < 0) {
  586. x = -1;
  587.     } else {
  588. if (!status) { /* Turn hard flow off */
  589.     if (
  590. #ifdef COMMENT
  591. /* This can fail because of sign extension */
  592. /* e.g. in Linux where it's Bit 31 */
  593. (temp.c_cflag & CRTSCTS) == CRTSCTS
  594. #else
  595. (temp.c_cflag & CRTSCTS) != 0
  596. #endif /* COMMENT */
  597. ) {
  598. temp.c_cflag &= ~CRTSCTS; /* It's there, remove it */
  599. attrs->c_cflag &= ~CRTSCTS;
  600. x = tcsetattr(ttyfd,TCSANOW,&temp);
  601. debug(F111,"tthflow POSIX_CRTSCTS OFF tcsetattr",
  602.       ckitoa(x),errno);
  603.     }
  604. } else { /* Turn hard flow on */
  605.     if (
  606. #ifdef COMMENT
  607. /* This can fail because of sign extension */
  608. (temp.c_cflag & CRTSCTS) != CRTSCTS
  609. #else
  610. (temp.c_cflag & CRTSCTS) == 0
  611. #endif /* COMMENT */
  612. ) {
  613. temp.c_cflag |= CRTSCTS; /* Not there, add it */
  614. temp.c_iflag &= ~(IXON|IXOFF|IXANY); /* Bye to IXON/IXOFF */
  615. x = tcsetattr(ttyfd,TCSANOW,&temp);
  616. debug(F111,"tthflow POSIX_CRTSCTS ON tcsetattr",
  617.       ckitoa(x),errno);
  618. attrs->c_cflag |= CRTSCTS;
  619. attrs->c_iflag &= ~(IXON|IXOFF|IXANY);
  620.     }
  621. }
  622.     }
  623. #else
  624. #ifdef SUNOS4
  625. /*
  626.   SunOS 4.0 (and maybe earlier?).  This code is dangerous because it
  627.   prevents compilation with GNU gcc, which uses different formats for the
  628.   _IORxxx macros than regular cc.  SunOS 4.1 and later can use the POSIX
  629.   routines above, which work for both cc and gcc.
  630. */
  631. #define TCGETS _IOR(T, 8, struct termios) /* Get modes into termios struct */
  632. #define TCSETS _IOW(T, 9, struct termios) /* Set modes from termios struct */
  633. #define CRTSCTS 0x80000000   /* RTS/CTS flow control */
  634.     struct termios {
  635. unsigned long c_iflag; /* Input modes */
  636. unsigned long c_oflag; /* Output modes */
  637. unsigned long c_cflag; /* Control modes */
  638. unsigned long c_lflag; /* Line discipline modes */
  639. char c_line;
  640. CHAR c_cc[17];
  641.     };
  642.     struct termios temp;
  643. #ifdef NETCMD
  644.     if (ttpipe) return(0);
  645. #endif /* NETCMD */
  646. #ifdef NETPTY
  647.     if (ttpty) return(0);
  648. #endif /* NETPTY */
  649.     debug(F101,"tthflow entry status","",status);
  650.     if (ioctl(ttyfd,TCGETS,&temp) > -1) { /* Get terminal modes. */
  651. if (status) { /* Turn hard flow on */
  652.     temp.c_cflag |= CRTSCTS; /* Add RTS/CTS to them. */
  653.     x = ioctl(ttyfd,TCSETS,&temp); /* Set them again. */
  654.     attrs->c_cflag |= CRTSCTS; /* Add to global info. */
  655. } else { /* Turn hard flow off */
  656.     temp.c_cflag &= ~CRTSCTS;
  657.     x = ioctl(ttyfd,TCSETS,&temp);
  658.     attrs->c_cflag &= ~CRTSCTS;
  659. }
  660.     }
  661. #else /* Not SunOS 4.0 or later */
  662. #ifdef AIXRS /* IBM AIX RS/6000 */
  663. #ifndef AIX41 /* But only pre-4.x == SVR4 */
  664. #ifdef NETCMD
  665.     if (ttpipe) return(0);
  666. #endif /* NETCMD */
  667. #ifdef NETPTY
  668.     if (ttpty) return(0);
  669. #endif /* NETPTY */
  670.     if (status) {
  671. if ((x = ioctl(ttyfd, TXADDCD, "rts")) < 0 && errno != EBUSY)
  672.   debug(F100,"hardflow TXADDCD (rts) error", "", 0);
  673.     } else {
  674. if ((x = ioctl(ttyfd, TXDELCD, "rts")) < 0 && errno != EINVAL)
  675.   debug(F100,"hardflow TXDELCD (rts) error", "", 0);
  676.     }
  677. #endif /* AIX41 */
  678. #else /* Not AIX RS/6000 */
  679. #ifdef ATTSV /* System V... */
  680. #ifdef CK_SCOV5 /* SCO Open Server 5.0 */
  681. #define CK_SCOUNIX
  682. #else
  683. #ifdef M_UNIX /* SCO UNIX 3.2v4.x or earlier */
  684. #define CK_SCOUNIX
  685. #endif /* M_UNIX */
  686. #endif /* CK_SCOV5 */
  687. #ifdef SCO_FORCE_RTSXOFF
  688. #ifdef CK_SCOUNIX /* But not SCO OpenServer 5.0.4 */
  689. #ifdef SCO_OSR504 /* or later... */
  690. #undef CK_SCOUNIX
  691. #endif /* SCO_OSR504 */
  692. #endif /* CK_SCOUNIX */
  693. #endif /* SCO_FORCE_RTSXOFF */
  694. #ifdef CK_SCOUNIX
  695. #ifdef POSIX
  696.     struct termios temp;
  697. #ifdef NETCMD
  698.     if (ttpipe) return(0);
  699. #endif /* NETCMD */
  700. #ifdef NETPTY
  701.     if (ttpty) return(0);
  702. #endif /* NETPTY */
  703.     debug(F101,"tthflow SCOUNIX POSIX entry status","",status);
  704.     errno = 0;
  705.     x = tcgetattr(ttyfd, &temp);
  706.     debug(F111,"tthflow SCO UNIX POSIX tcgetattr",ckitoa(x),errno);
  707. #else /* POSIX */
  708.     struct termio temp;
  709. #ifdef NETCMD
  710.     if (ttpipe) return(0);
  711. #endif /* NETCMD */
  712. #ifdef NETPTY
  713.     if (ttpty) return(0);
  714. #endif /* NETPTY */
  715.     debug(F101,"tthflow SCOUNIX non-POSIX entry status","",status);
  716.     x = ioctl(ttyfd, TCGETA, &temp);
  717.     debug(F111,"tthflow SCO UNIX non-POSIX TCGETA",ckitoa(x),errno);
  718. #endif /* POSIX */
  719. /*
  720.   This is not really POSIX, since POSIX does not deal with hardware flow
  721.   control, but we are using the POSIX APIs.  In fact, RTSFLOW and CTSFLOW
  722.   are defined in termio.h, but within #ifndef _POSIX_SOURCE..#endif.  So
  723.   let's try forcing their definitions here.
  724. */
  725. #ifndef CTSFLOW
  726. #define CTSFLOW 0020000
  727.     debug(F101,"tthflow SCO defining CTSFLOW","",CTSFLOW);
  728. #else
  729.     debug(F101,"tthflow SCO CTSFLOW","",CTSFLOW);
  730. #endif /* CTSFLOW */
  731. #ifndef RTSFLOW
  732. #define RTSFLOW 0040000
  733.     debug(F101,"tthflow SCO defining RTSFLOW","",RTSFLOW);
  734. #else
  735.     debug(F101,"tthflow SCO RTSFLOW","",RTSFLOW);
  736. #endif /* RTSFLOW */
  737. #ifndef ORTSFL
  738. #define ORTSFL 0100000
  739.     debug(F101,"tthflow SCO defining ORTSFL","",ORTSFL);
  740. #else
  741.     debug(F101,"tthflow SCO ORTSFL","",ORTSFL);
  742. #endif /* ORTSFL */
  743.     if (x != -1) {
  744. if (status) { /* Turn it ON */
  745.     temp.c_cflag |= RTSFLOW|CTSFLOW;
  746.     attrs->c_cflag |= RTSFLOW|CTSFLOW;
  747. #ifdef ORTSFL
  748.     temp.c_cflag &= ~ORTSFL;
  749.     attrs->c_cflag &= ~ORTSFL;
  750. #endif /* ORTSFL */
  751.     temp.c_iflag &= ~(IXON|IXOFF|IXANY);
  752.     attrs->c_iflag &= ~(IXON|IXOFF|IXANY);
  753. } else { /* Turn it OFF */
  754. #ifdef ORTSFL
  755.     temp.c_cflag &= ~(RTSFLOW|CTSFLOW|ORTSFL);
  756.     attrs->c_cflag &= ~(RTSFLOW|CTSFLOW|ORTSFL);
  757. #else  /* ORTSFL */
  758.     temp.c_cflag &= ~(RTSFLOW|CTSFLOW);
  759.     attrs->c_cflag &= ~(RTSFLOW|CTSFLOW);
  760. #endif /* ORTSFL */
  761. }
  762. #ifdef POSIX
  763. x = tcsetattr(ttyfd, TCSADRAIN, &temp);
  764. #else
  765. x = ioctl(ttyfd, TCSETA, &temp);
  766. #endif /* POSIX */
  767. debug(F101,"tthflow SCO set modes","",x);
  768.     }
  769. #else /* Not SCO UNIX */
  770. #ifdef NETCMD
  771.     if (ttpipe) return(0);
  772. #endif /* NETCMD */
  773. #ifdef NETPTY
  774.     if (ttpty) return(0);
  775. #endif /* NETPTY */
  776.     if (!status) { /* Turn it OFF */
  777. #ifdef RTSXOFF
  778. debug(F100,"tthflow ATTSV RTS/CTS OFF","",0);
  779. rctsx.x_hflag &= ~(RTSXOFF|CTSXON);
  780. #ifdef TCSETX
  781. x = ioctl(ttyfd,TCSETX,&rctsx);
  782. debug(F101,"tthflow ATTSV TCSETX OFF","",x);
  783. #else
  784. x = -1
  785. debug(F100,"tthflow TCSETX not defined","",0);
  786. #endif /* TCSETX */
  787. #else
  788. debug(F100,"tthflow ATTSV RTSXOFF not defined","",0);
  789. #endif /* RTSXOFF */
  790. #ifdef DTRXOFF
  791. debug(F100,"tthflow ATTSV DTR/CD OFF","",0);
  792. rctsx.x_hflag &= ~(DTRXOFF|CDXON);
  793. x = ioctl(ttyfd,TCSETX,&rctsx);
  794. debug(F101,"tthflow ATTSV DTRXOFF OFF","",x);
  795. #else
  796. debug(F100,"tthflow ATTSV DTRXOFF not defined","",0);
  797. #endif /* DTRXOFF */
  798.     } else { /* Turn it ON. */
  799. if (flow == FLO_RTSC) { /* RTS/CTS Flow control... */
  800.     debug(F100,"tthflow ATTSV RTS/CTS ON","",0);
  801. #ifdef RTSXOFF
  802.     /* This is the preferred way, according to SVID3 */
  803. #ifdef TCGETX
  804.     x = ioctl(ttyfd,TCGETX,&rctsx);
  805.     debug(F101,"tthflow TCGETX","",x);
  806.     if (x > -1) {
  807. rctsx.x_hflag |= RTSXOFF | CTSXON;
  808. x = ioctl(ttyfd,TCSETX,&rctsx);
  809. debug(F100,"tthflow ATTSV ioctl","",x);
  810.     }
  811. #else
  812.     debug(F100,"tthflow TCGETX not defined","",0);
  813.     x = -1
  814. #endif /* TCGETX */
  815. #else
  816.     debug(F100,"tthflow RTSXOFF not defined","",0);
  817.     x = -1;
  818. #endif /* RTSXOFF */
  819. } else if (flow == FLO_DTRC) { /* DTR/CD Flow control... */
  820.     debug(F100,"tthflow ATTSV DTR/CD ON","",0);
  821. #ifdef DTRXOFF
  822.     /* This is straight out of SVID R4 */
  823.     if (ioctl(ttyfd,TCGETX,&rctsx) > -1) {
  824. rctsx.x_hflag &= ~(DTRXOFF|CDXON);
  825. x = ioctl(ttyfd,TCSETX,&rctsx);
  826.     }
  827. #else
  828.     debug(F100,"tthflow ATTSV DTRXOFF not defined","",0);
  829.     x = -1;
  830. #endif /* DTRXOFF */
  831. }
  832.     }
  833. #endif /* CK_SCOUNIX */
  834. #else /* not System V... */
  835. #ifdef CK_DTRCTS
  836. #ifdef LDODTR
  837. #ifdef LDOCTS
  838. #ifdef NETCMD
  839.     if (ttpipe) return(0);
  840. #endif /* NETCMD */
  841. #ifdef NETPTY
  842.     if (ttpty) return(0);
  843. #endif /* NETPTY */
  844.     x = LDODTR | LDOCTS; /* Found only on UTEK? */
  845.     if (flow == FLO_DTRT && status) { /* Use hardware flow control */
  846. if (lmodef) {
  847.     x = ioctl(ttyfd,TIOCLBIS,&x);
  848.     if (x < 0) {
  849.         debug(F100,"hardflow TIOCLBIS error","",0);
  850.     } else {
  851. lmodef++;
  852. debug(F100,"hardflow TIOCLBIS ok","",0);
  853.     }
  854. }
  855.     } else {
  856. if (lmodef) {
  857.     x = ioctl(ttyfd,TIOCLBIC,&x);
  858.     if (x < 0) {
  859.         debug(F100,"hardflow TIOCLBIC error","",0);
  860.     } else {
  861. lmodef++;
  862. debug(F100,"hardflow TIOCLBIC ok","",0);
  863.     }
  864. }
  865.     }
  866. #endif /* LDODTR */
  867. #endif /* LDOCTS */
  868. #endif /* CK_DTRCTS */
  869. #endif /* ATTSV */
  870. #endif /* AIXRS */
  871. #endif /* SUNOS4 */
  872. #endif /* QNX */
  873. #endif /* POSIX_CRTSCTS */
  874. #endif /* SUNOS41 */
  875. #else /* OXOS */
  876.     struct termios temp; /* Olivetti X/OS ... */
  877. #ifdef NETCMD
  878.     if (ttpipe) return(0);
  879. #endif /* NETCMD */
  880. #ifdef NETPTY
  881.     if (ttpty) return(0);
  882. #endif /* NETPTY */
  883.     x = ioctl(ttyfd,TCGETS,&temp);
  884.     if (x == 0) {
  885. temp.c_cflag &= ~(CRTSCTS|CDTRCTS|CBRKFLOW|CDTRDSR|CRTSDSR);
  886. if (status) {
  887.     switch (flow) {
  888.       case FLO_RTSC: temp.c_cflag |= CRTSCTS; /* RTS/CTS (hard) */
  889. break;
  890.       case FLO_DTRT: temp.c_cflag |= CDTRCTS; /* DTR/CTS (hard) */
  891. break;
  892.     }
  893. }
  894. x = ioctl(ttyfd,TCSETS,&temp);
  895.     }
  896. #endif /* OXOS */
  897.     return(x);
  898. #endif /* Plan9 */
  899. }
  900. /*  T T P K T  --  Condition the communication line for packets */
  901. /*                 or for modem dialing */
  902. /*
  903.   If called with speed > -1, also set the speed.
  904.   Returns 0 on success, -1 on failure.
  905.   NOTE: the "xflow" parameter is supposed to be the currently selected
  906.   type of flow control, but for historical reasons, this parameter is also
  907.   used to indicate that we are dialing.  Therefore, when the true flow
  908.   control setting is needed, we access the external variable "flow", rather
  909.   than trusting our "xflow" argument.
  910. */
  911. int
  912. #ifdef CK_ANSIC
  913. ttpkt(long speed, int xflow, int parity)
  914. #else
  915. ttpkt(speed,xflow,parity) long speed; int xflow, parity;
  916. #endif /* CK_ANSIC */
  917. /* ttpkt */ {
  918. #ifndef NOLOCAL
  919.     int s2;
  920.     int s = -1;
  921. #endif /* NOLOCAL */
  922. #ifndef SVORPOSIX
  923.     int x;
  924. #endif /* SVORPOSIX */
  925.     extern int flow; /* REAL flow-control setting */
  926.     if (ttyfd < 0) return(-1);          /* Not open. */
  927.     debug(F101,"ttpkt parity","",parity);
  928.     debug(F101,"ttpkt xflow","",xflow);
  929.     debug(F101,"ttpkt speed","",(int) speed);
  930.     ttprty = parity;                    /* Let other tt functions see these. */
  931.     ttspeed = speed; /* Make global copy for this module */
  932.     ttpmsk = ttprty ? 0177 : 0377; /* Parity stripping mask */
  933. #ifdef PARSENSE
  934.     needpchk = ttprty ? 0 : 1; /* Parity check needed? */
  935. #else
  936.     needpchk = 0;
  937. #endif /* PARSENSE */
  938.     debug(F101,"ttpkt ttpmsk","",ttpmsk);
  939.     debug(F101,"ttpkt netconn","",netconn);
  940. #ifdef NETCONN /* No mode-changing for telnet */
  941.     if (netconn) {
  942. #ifdef TCPSOCKET
  943. #ifdef TCP_NODELAY
  944.         if (ttnet == NET_TCPB) { /* But turn off Nagle */
  945.             extern int tcp_nodelay;
  946.             nodelay_sav = tcp_nodelay;
  947.             no_delay(1);
  948.         }
  949. #endif /* TCP_NODELAY */
  950. #endif /* TCPSOCKET */
  951.         return(0);
  952.     }
  953. #endif /* NETCONN */
  954. #ifdef NETCMD
  955.     if (ttpipe) return(0);
  956. #endif /* NETCMD */
  957. #ifdef NETPTY
  958.     if (ttpty) return(0);
  959. #endif /* NETPTY */
  960. #ifndef Plan9
  961.     if (ttfdflg && !isatty(ttyfd)) return(0);
  962. #endif /* Plan9 */
  963. #ifdef COHERENT
  964. #define SVORPOSIX
  965. #endif /* COHERENT */
  966. #ifndef SVORPOSIX /* Berkeley, V7, etc. */
  967. #ifdef LPASS8
  968. /*
  969.  For some reason, with BSD terminal drivers, you can't set FLOW to XON/XOFF
  970.  after having previously set it to NONE without closing and reopening the
  971.  device.  Unless there's something I overlooked below...
  972. */
  973.     if (ttflow == FLO_NONE && flow == FLO_XONX && xlocal == 0) {
  974. debug(F101,"ttpkt executing horrible flow kludge","",0);
  975. ttclos(0); /* Close it */
  976. x = 0;
  977. ttopen(ttnmsv,&x,ttmdm,0); /* Open it again */
  978.     }
  979. #endif /* LPASS8 */
  980. #endif /* SVORPOSIX */
  981. #ifdef COHERENT /* This must be vestigial since we */
  982. #undef SVORPOSIX /* reverse it a few lines below... */
  983. #endif /* COHERENT */
  984.     if (xflow != FLO_DIAL && xflow != FLO_DIAX)
  985.       ttflow = xflow; /* Now make this available too. */
  986. #ifndef NOLOCAL
  987.     if (xlocal) {
  988. s2 = (int) (speed / 10L); /* Convert bps to cps */
  989. debug(F101,"ttpkt calling ttsspd","",s2);
  990. s = ttsspd(s2); /* Check and set the speed */
  991. debug(F101,"ttpkt ttsspd result","",s);
  992.   carrctl(&ttraw, xflow != FLO_DIAL /* Carrier control */
  993. && (ttcarr == CAR_ON || (ttcarr == CAR_AUT && ttmdm != 0)));
  994. tvtflg = 0; /* So ttvt() will work next time */
  995.     }
  996. #endif /* NOLOCAL */
  997. #ifdef COHERENT
  998. #define SVORPOSIX
  999. #endif /* COHERENT */
  1000. #ifndef SVORPOSIX /* BSD section */
  1001.     if (flow == FLO_RTSC || /* Hardware flow control */
  1002. flow == FLO_DTRC ||
  1003. flow == FLO_DTRT) {
  1004. tthflow(flow, 1, &ttraw);
  1005. debug(F100,"ttpkt hard flow, TANDEM off, RAW on","",0);
  1006. ttraw.sg_flags &= ~TANDEM; /* Turn off software flow control */
  1007. ttraw.sg_flags |= RAW; /* Enter raw mode */
  1008.     } else if (flow == FLO_NONE) { /* No flow control */
  1009. debug(F100,"ttpkt no flow, TANDEM off, RAW on","",0);
  1010. ttraw.sg_flags &= ~TANDEM; /* Turn off software flow control */
  1011. tthflow(flow, 0, &ttraw); /* Turn off any hardware f/c too */
  1012. ttraw.sg_flags |= RAW; /* Enter raw mode */
  1013.     } else if (flow == FLO_KEEP) { /* Keep device's original setting */
  1014. debug(F100,"ttpkt keeping original TANDEM","",0);
  1015. ttraw.sg_flags &= ~TANDEM;
  1016. ttraw.sg_flags |= (ttold.sg_flags & TANDEM);
  1017. /* NOTE: We should also handle hardware flow control here! */
  1018.     }
  1019. /* SET FLOW XON/XOFF is in effect, or SET FLOW KEEP resulted in Xon/Xoff */
  1020.     if ((flow == FLO_XONX) || (ttraw.sg_flags & TANDEM)) {
  1021. debug(F100,"ttpkt turning on TANDEM","",0);
  1022. ttraw.sg_flags |= TANDEM; /* So ask for it. */
  1023. #ifdef LPASS8 /* Can pass 8-bit data through? */
  1024. /* If the LPASS8 local mode is available, then flow control can always  */
  1025. /* be used, even if parity is none and we are transferring 8-bit data.  */
  1026. /* But we only need to do all this if Xon/Xoff is requested. */
  1027. /* BUT... this tends not to work through IP or LAT connections, terminal */
  1028. /* servers, telnet, rlogin, etc, so it is currently disabled. */
  1029. x = LPASS8; /* If LPASS8 defined, then */
  1030. debug(F100,"ttpkt executing LPASS8 code","",0);
  1031. if (lmodef) { /* TIOCLBIS must be too. */
  1032.     x = ioctl(ttyfd,TIOCLBIS,&x); /* Try to set LPASS8. */
  1033.     if (x < 0) {
  1034. debug(F100,"ttpkt TIOCLBIS error","",0);
  1035.     } else {
  1036. lmodef++;
  1037. debug(F100,"ttpkt TIOCLBIS ok","",0);
  1038.     }
  1039. }
  1040. /*
  1041.  But if we use LPASS8 mode, we must explicitly turn off
  1042.  terminal interrupts of all kinds.
  1043. */
  1044. #ifdef TIOCGETC /* Not rawmode, */
  1045. if (tcharf && (xlocal == 0)) { /* must turn off */
  1046.     tchnoi.t_intrc = -1; /* interrupt character */
  1047.     tchnoi.t_quitc = -1; /* and quit character. */
  1048.     tchnoi.t_startc = 17; /* Make sure xon */
  1049.     tchnoi.t_stopc = 19; /* and xoff not ignored. */
  1050. #ifndef NOBRKC
  1051.     tchnoi.t_eofc = -1; /* eof character. */
  1052.     tchnoi.t_brkc = -1; /* brk character. */
  1053. #endif /* NOBRKC */
  1054.     if (ioctl(ttyfd,TIOCSETC,&tchnoi) < 0) {
  1055. debug(F100,"ttpkt TIOCSETC failed","",0);
  1056.     } else {
  1057. tcharf = 1;
  1058. debug(F100,"ttpkt TIOCSETC ok","",0);
  1059.     }
  1060. #ifdef COMMENT
  1061. /* only for paranoid debugging */
  1062.     if (tcharf) {
  1063. struct tchars foo;
  1064. char tchbuf[100];
  1065. ioctl(0,TIOCGETC,&foo);
  1066. sprintf(tchbuf,
  1067.     "intr=%d,quit=%d, start=%d, stop=%d, eof=%d, brk=%d",
  1068.     foo.t_intrc, foo.t_quitc, foo.t_startc,
  1069.     foo.t_stopc, foo.t_eofc,  foo.t_brkc);
  1070. debug(F110,"ttpkt chars",tchbuf,0);
  1071.     }
  1072. #endif /* COMMENT */
  1073. }
  1074. ttraw.sg_flags |= CBREAK; /* Needed for unknown reason */
  1075. #endif /* TIOCGETC */
  1076. /* Prevent suspend during packet mode */
  1077. #ifdef TIOCGLTC /* Not rawmode, */
  1078. if (ltcharf && (xlocal == 0)) { /* must turn off */
  1079.     ltchnoi.t_suspc = -1; /* suspend character */
  1080.     ltchnoi.t_dsuspc = -1; /* and delayed suspend character */
  1081.     if (ioctl(ttyfd,TIOCSLTC,&tchnoi) < 0) {
  1082. debug(F100,"ttpkt TIOCSLTC failed","",0);
  1083.     } else {
  1084. ltcharf = 1;
  1085. debug(F100,"ttpkt TIOCSLTC ok","",0);
  1086.     }
  1087. }
  1088. #endif /* TIOCGLTC */
  1089. #else /* LPASS8 not defined */
  1090. /* Previously, BSD-based implementations always */
  1091. /* used rawmode for packets.  Now, we use rawmode only if parity is NONE. */
  1092. /* This allows the flow control requested above to actually work, but only */
  1093. /* if the user asks for parity (which also means they get 8th-bit quoting). */
  1094. if (parity) { /* If parity, */
  1095.     ttraw.sg_flags &= ~RAW; /* use cooked mode */
  1096. #ifdef COMMENT
  1097. /* WHY??? */
  1098.     if (xlocal)
  1099. #endif /* COMMENT */
  1100.       ttraw.sg_flags |= CBREAK;
  1101.     debug(F101,"ttpkt cooked, cbreak, parity","",parity);
  1102. #ifdef TIOCGETC /* Not rawmode, */
  1103.     if (tcharf && (xlocal == 0)) { /* must turn off */
  1104. tchnoi.t_intrc = -1; /* interrupt character */
  1105. tchnoi.t_quitc = -1; /* and quit character. */
  1106. tchnoi.t_startc = 17; /* Make sure xon */
  1107. tchnoi.t_stopc = 19; /* and xoff not ignored. */
  1108. #ifndef NOBRKC
  1109. tchnoi.t_eofc = -1; /* eof character. */
  1110. tchnoi.t_brkc = -1; /* brk character. */
  1111. #endif /* NOBRKC */
  1112. if (ioctl(ttyfd,TIOCSETC,&tchnoi) < 0) {
  1113.     debug(F100,"ttpkt TIOCSETC failed","",0);
  1114. } else {
  1115.     tcharf = 1;
  1116.     debug(F100,"ttpkt TIOCSETC ok","",0);
  1117. }
  1118.     }
  1119. #endif /* TIOCGETC */
  1120. #ifdef TIOCGLTC /* Not rawmode, */
  1121. /* Prevent suspend during packet mode */
  1122.     if (ltcharf && (xlocal == 0)) { /* must turn off */
  1123. ltchnoi.t_suspc = -1; /* suspend character */
  1124. ltchnoi.t_dsuspc = -1; /* and delayed suspend character */
  1125. if (ioctl(ttyfd,TIOCSLTC,&tchnoi) < 0) {
  1126.     debug(F100,"ttpkt TIOCSLTC failed","",0);
  1127. } else {
  1128.     ltcharf = 1;
  1129.     debug(F100,"ttpkt TIOCSLTC ok","",0);
  1130. }
  1131.     }
  1132. #endif /* TIOCGLTC */
  1133. } else { /* If no parity, */
  1134.     ttraw.sg_flags |= RAW; /* must use 8-bit raw mode. */
  1135.     debug(F101,"ttpkt setting rawmode, parity","",parity);
  1136. }
  1137. #endif /* LPASS8 */
  1138.     } /* End of Xon/Xoff section */
  1139.     /* Don't echo, don't map CR to CRLF on output, don't fool with case */
  1140. #ifdef LCASE
  1141.     ttraw.sg_flags &= ~(ECHO|CRMOD|LCASE);
  1142. #else
  1143.     ttraw.sg_flags &= ~(ECHO|CRMOD);
  1144. #endif /* LCASE */
  1145. #ifdef TOWER1
  1146.     ttraw.sg_flags &= ~ANYP;            /* Must set this on old Towers */
  1147. #endif /* TOWER1 */
  1148. #ifdef BELLV10
  1149.     if (ioctl(ttyfd,TIOCSETP,&ttraw) < 0) /* Set the new modes. */
  1150.       return(-1);
  1151. #else
  1152.     errno = 0;
  1153.     if (stty(ttyfd,&ttraw) < 0) {       /* Set the new modes. */
  1154.         debug(F101,"ttpkt stty failed","",errno);
  1155.         return(-1);
  1156.     }
  1157. #endif /* BELLV10 */
  1158.     debug(F100,"ttpkt stty ok","",0);
  1159. #ifdef sony_news
  1160.     x = xlocal ? km_ext : km_con; /* Put line in ASCII mode. */
  1161.     if (x != -1) { /* Make sure we know original modes. */
  1162. x &= ~KM_TTYPE;
  1163. x |= KM_ASCII;
  1164. if (ioctl(ttyfd,TIOCKSET, &x) < 0) {
  1165.     perror("ttpkt can't set ASCII mode");
  1166.     debug(F101,"ttpkt error setting ASCII mode","",x);
  1167.     return(-1);
  1168. }
  1169.     }
  1170.     debug(F100,"ttpkt set ASCII mode ok","",0);
  1171. #endif /* sony_news */
  1172.     if (xlocal == 0) { /* Turn this off so we can read */
  1173. signal(SIGINT,SIG_IGN); /* Ctrl-C chars typed at console */
  1174. sigint_ign = 1;
  1175.     }
  1176.     tvtflg = 0; /* So ttvt() will work next time */
  1177.     debug(F100,"ttpkt success","",0);
  1178.     return(0);
  1179. #endif /* Not ATTSV or POSIX */
  1180. /* AT&T UNIX and POSIX */
  1181. #ifdef COHERENT
  1182. #define SVORPOSIX
  1183. #endif /* COHERENT */
  1184. #ifdef SVORPOSIX
  1185.     if (flow == FLO_XONX) { /* Xon/Xoff */
  1186. ttraw.c_iflag |= (IXON|IXOFF);
  1187. tthflow(flow, 0, &ttraw);
  1188.     } else if (flow == FLO_NONE) { /* None */
  1189. /* NOTE: We should also turn off hardware flow control here! */
  1190. ttraw.c_iflag &= ~(IXON|IXOFF);
  1191. tthflow(flow, 0, &ttraw);
  1192.     } else if (flow == FLO_KEEP) { /* Keep */
  1193. ttraw.c_iflag &= ~(IXON|IXOFF); /* Turn off Xon/Xoff flags */
  1194. ttraw.c_iflag |= (ttold.c_iflag & (IXON|IXOFF)); /* OR in old ones */
  1195. /* NOTE: We should also handle hardware flow control here! */
  1196. #ifdef POSIX_CRTSCTS
  1197. /* In Linux case, we do this, which is unlikely to be portable */
  1198.         ttraw.c_cflag &= ~CRTSCTS; /* Turn off RTS/CTS flag */
  1199.         ttraw.c_cflag |= (ttold.c_cflag & CRTSCTS); /* OR in old one */
  1200. #endif /* POSIX_CRTSCTS */
  1201.     } else if (flow == FLO_RTSC || /* Hardware */
  1202.        flow == FLO_DTRC ||
  1203.        flow == FLO_DTRT) {
  1204. ttraw.c_iflag &= ~(IXON|IXOFF); /* (190) */
  1205. tthflow(flow, 1, &ttraw);
  1206.     }
  1207.     ttraw.c_lflag &= ~(ICANON|ECHO);
  1208.     ttraw.c_lflag &= ~ISIG; /* Do NOT check for interrupt chars */
  1209. #ifndef OXOS
  1210. #ifdef QNX
  1211.     if (flow != FLO_RTSC && flow != FLO_DTRC && flow != FLO_DTRT)
  1212. #endif /* QNX */
  1213. #ifndef COHERENT
  1214.       ttraw.c_lflag &= ~IEXTEN; /* Turn off ^O/^V processing */
  1215. #endif /* COHERENT */
  1216. #else /* OXOS */
  1217.     ttraw.c_cc[VDISCARD] = ttraw.c_cc[VLNEXT] = CDISABLE;
  1218. #endif /* OXOS */
  1219.     ttraw.c_lflag |= NOFLSH; /* Don't flush */
  1220.     ttraw.c_iflag |= IGNPAR; /* Ignore parity errors */
  1221. #ifdef ATTSV
  1222. #ifdef BSD44
  1223.     ttraw.c_iflag &= ~(IGNBRK|INLCR|IGNCR|ICRNL|INPCK|ISTRIP|IXANY);
  1224. #else
  1225.     ttraw.c_iflag &= ~(IGNBRK|INLCR|IGNCR|ICRNL|IUCLC|INPCK|ISTRIP|IXANY);
  1226. #endif /* BSD44 */
  1227. #else /* POSIX */
  1228.     ttraw.c_iflag &= ~(IGNBRK|INLCR|IGNCR|ICRNL|INPCK|ISTRIP);
  1229. #endif /* ATTSV */
  1230.     ttraw.c_oflag &= ~OPOST;
  1231.     ttraw.c_cflag &= ~(CSIZE);
  1232.     ttraw.c_cflag |= (CS8|CREAD|HUPCL);
  1233. #ifdef HWPARITY
  1234.     if (hwparity && xlocal) { /* Hardware parity & stop bits */
  1235. #ifdef CSTOPB
  1236. if (stopbits == 2) {
  1237.     ttraw.c_cflag |= CSTOPB; /* 2 stop bits */
  1238.     debug(F100,"ttpkt 2 stopbits","",0);
  1239. } else if (stopbits == 1) {
  1240.     ttraw.c_cflag &= ~(CSTOPB); /* 1 stop bit */
  1241.     debug(F100,"ttpkt 1 stopbit","",0);
  1242. }
  1243. #else
  1244. debug(F101,"ttpkt CSTOPB not def","",stopbits);
  1245. #endif /* CSTOPB */
  1246. ttraw.c_cflag |= PARENB; /* Enable parity */
  1247. switch (hwparity) {
  1248.   case 'e': /* Even */
  1249.     ttraw.c_cflag &= ~(PARODD);
  1250.     debug(F100,"ttpkt 8 bits + even parity","",0);
  1251.     break;
  1252.   case 'o': /* Odd */
  1253.     ttraw.c_cflag |= PARODD;
  1254.     debug(F100,"ttpkt 8 bits + odd parity","",0);
  1255.     break;
  1256.   case 'm': /* Mark */
  1257.   case 's': /* Space */
  1258.     debug(F100,"ttpkt 8 bits + invalid parity","",0);
  1259.     break;
  1260. }
  1261.     } else { /* We handle parity ourselves */
  1262. #endif /* HWPARITY */
  1263. ttraw.c_cflag &= ~(PARENB); /* Don't enable parity */
  1264. #ifdef HWPARITY
  1265.     }
  1266. #endif /* HWPARITY */
  1267. #ifdef IX370
  1268.     ttraw.c_cc[4] = 48;  /* So Series/1 doesn't interrupt on every char */
  1269.     ttraw.c_cc[5] = 1;
  1270. #else
  1271. #ifndef VEOF /* for DGUX this is VEOF, not VMIN */
  1272.     ttraw.c_cc[4] = 1;   /* [VMIN]  return max of this many characters or */
  1273. #else
  1274. #ifndef OXOS
  1275. #ifdef VMIN
  1276.     ttraw.c_cc[VMIN] = 1;
  1277. #endif /* VMIN */
  1278. #else /* OXOS */
  1279.     ttraw.c_min = 1;
  1280. #endif /* OXOS */
  1281. #endif /* VEOF */
  1282. #ifndef VEOL /* for DGUX this is VEOL, not VTIME */
  1283.     ttraw.c_cc[5] = 0;  /* [VTIME] when this many secs/10 expire w/no input */
  1284. #else
  1285. #ifndef OXOS
  1286. #ifdef VTIME
  1287.     ttraw.c_cc[VTIME] = 0;
  1288. #endif /* VTIME */
  1289. #else /* OXOS */
  1290.     ttraw.c_time = 0;
  1291. #endif /* OXOS */
  1292. #endif /* VEOL */
  1293. #endif /* IX370 */
  1294. #ifdef VINTR /* Turn off interrupt character */
  1295.     if (xlocal == 0) /* so ^C^C can break us out of */
  1296.       ttraw.c_cc[VINTR] = 0; /* packet mode. */
  1297. #endif /* VINTR */
  1298. #ifdef Plan9
  1299.     if (p9ttyparity('n') < 0)
  1300. return -1;
  1301. #else
  1302. #ifdef BSD44ORPOSIX
  1303. #ifdef BEOSORBEBOX
  1304.     ttraw.c_cc[VMIN] = 0; /* DR7 can only poll. */
  1305. #endif /* BEOSORBEBOX */
  1306.     debug(F100,"ttpkt calling tcsetattr(TCSETAW)","",0);
  1307.     errno = 0;
  1308.     if (tcsetattr(ttyfd,TCSADRAIN,&ttraw) < 0) {
  1309.         debug(F101,"ttpkt BSD44ORPOSIX tcsetattr(TCSADRAIN) fail","",errno);
  1310.         return(-1);
  1311.     }
  1312. #else /* BSD44ORPOSIX */
  1313.     errno = 0;
  1314.     debug(F100,"ttpkt calling ioctl(TCSETAW)","",0);
  1315.     if (ioctl(ttyfd,TCSETAW,&ttraw) < 0) {  /* set new modes . */
  1316.         debug(F100,"ttpkt ATTSV ioctl(TCSETAW) fail","",errno);
  1317.         return(-1);
  1318.     }
  1319. #endif /* BSD44ORPOSIX */
  1320. #endif /* Plan9 */
  1321.     tvtflg = 0;
  1322.     debug(F100,"ttpkt success","",0);
  1323.     return(0);
  1324. #endif /* ATTSV */
  1325. #ifdef COHERENT
  1326. #undef SVORPOSIX
  1327. #endif /* COHERENT */
  1328. }
  1329. /*  T T S E T F L O W  --  Set flow control immediately.  */
  1330. #ifdef COHERENT
  1331. #define SVORPOSIX
  1332. #endif /* COHERENT */
  1333. int
  1334. ttsetflow(flow) int flow; {
  1335.     if (ttyfd < 0) /* Communications channel must open */
  1336.       return(-1);
  1337.     debug(F101,"ttsetflow","",flow);
  1338. #ifdef NETCMD
  1339.     if (ttpipe) return(0);
  1340. #endif /* NETCMD */
  1341. #ifdef NETPTY
  1342.     if (ttpty) return(0);
  1343. #endif /* NETPTY */
  1344. #ifdef COMMENT
  1345.     /* This seems to hurt... */
  1346.     if (flow == FLO_KEEP)
  1347.       return(0);
  1348. #endif /* COMMENT */
  1349.     if (flow == FLO_RTSC || /* Hardware flow control... */
  1350. flow == FLO_DTRC ||
  1351. flow == FLO_DTRT) {
  1352. tthflow(flow, 1, &ttraw);
  1353. #ifndef SVORPOSIX
  1354. ttraw.sg_flags &= ~TANDEM; /* Turn off software flow control */
  1355. #else
  1356. ttraw.c_iflag &= ~(IXON|IXOFF);
  1357. #endif /* SVORPOSIX */
  1358.     } else if (flow == FLO_XONX) { /* Xon/Xoff... */
  1359. #ifndef SVORPOSIX
  1360. ttraw.sg_flags |= TANDEM;
  1361. #else
  1362. ttraw.c_iflag |= (IXON|IXOFF);
  1363. #endif /* SVORPOSIX */
  1364. tthflow(FLO_RTSC, 0, &ttraw); /* Turn off hardware flow control */
  1365.     } else if (flow == FLO_NONE) { /* No flow control */
  1366. #ifndef SVORPOSIX
  1367. ttraw.sg_flags &= ~TANDEM; /* Turn off software flow control */
  1368. #else
  1369. ttraw.c_iflag &= ~(IXON|IXOFF);
  1370. #endif /* SVORPOSIX */
  1371. tthflow(FLO_RTSC, 0, &ttraw); /* Turn off any hardware f/c too */
  1372.     }
  1373. /* Set the new modes... */
  1374. #ifndef SVORPOSIX /* BSD and friends */
  1375. #ifdef BELLV10
  1376.     if (ioctl(ttyfd,TIOCSETP,&ttraw) < 0)
  1377.       return(-1);
  1378. #else
  1379. #ifndef MINIX2
  1380.     if (stty(ttyfd,&ttraw) < 0)
  1381.       return(-1);
  1382. #endif /* MINIX2 */
  1383. #endif /* BELLV10 */
  1384. #else
  1385. #ifdef BSD44ORPOSIX /* POSIX */
  1386.     if (tcsetattr(ttyfd,TCSADRAIN,&ttraw) < 0)
  1387.       return(-1);
  1388. #else /* System V */
  1389.     if (ioctl(ttyfd,TCSETAW,&ttraw) < 0)
  1390.       return(-1);
  1391. #endif /* BSD44ORPOSIX */
  1392. #endif /* SVORPOSIX */
  1393.     return(0);
  1394. }
  1395. #ifdef COHERENT
  1396. #undef SVORPOSIX
  1397. #endif /* COHERENT */
  1398. /*  T T V T -- Condition communication device for use as virtual terminal. */
  1399. int
  1400. #ifdef CK_ANSIC
  1401. ttvt(long speed, int flow)
  1402. #else
  1403. ttvt(speed,flow) long speed; int flow;
  1404. #endif /* CK_ANSIC */
  1405. /* ttvt */ {
  1406.     int s, s2;
  1407.     debug(F101,"ttvt ttyfd","",ttyfd);
  1408.     debug(F101,"ttvt tvtflg","",tvtflg);
  1409.     debug(F101,"ttvt speed","",speed);
  1410.     debug(F101,"ttvt flow","",flow);
  1411.     ttpmsk = 0xff;
  1412. #ifdef NOLOCAL
  1413.     return(conbin((char)escchr));
  1414. #else
  1415.     if (ttyfd < 0) { /* Not open. */
  1416. if (ttchk() < 0)
  1417.   return(-1);
  1418. else /* But maybe something buffered. */
  1419.   return(0);
  1420.     }
  1421. #ifdef NETCMD
  1422.     if (ttpipe) return(0);
  1423. #endif /* NETCMD */
  1424. #ifdef NETPTY
  1425.     if (ttpty) return(0);
  1426. #endif /* NETPTY */
  1427. #ifdef NETCONN
  1428.     if (netconn) {
  1429. tvtflg = 1; /* Network connections... */
  1430. debug(F100,"ttvt network connection, skipping...","",0);
  1431. #ifdef TCPSOCKET
  1432. #ifdef TCP_NODELAY
  1433.         {
  1434.     extern int tcp_nodelay;
  1435.     if (ttnet == NET_TCPB) {
  1436. if (nodelay_sav > -1) {
  1437.     no_delay(nodelay_sav);
  1438.     nodelay_sav = -1;
  1439. }
  1440.     }
  1441.         }
  1442. #endif /* TCP_NODELAY */
  1443. #endif /* TCPSOCKET */
  1444. return(0); /* ... require no special setup */
  1445.     }
  1446. #endif /* NETCONN */
  1447.     if (tvtflg != 0 && speed == ttspeed && flow == ttflow && ttcarr == curcarr)
  1448.       {
  1449.   debug(F100,"ttvt modes already set, skipping...","",0);
  1450.   return(0); /* Already been called. */
  1451.       }
  1452.     if (ttfdflg
  1453. #ifndef Plan9
  1454. && !isatty(ttyfd)
  1455. #endif /* Plan9 */
  1456. ) {
  1457. debug(F100,"ttvt using external fd, skipping...","",0);
  1458. return(0);
  1459.     }
  1460.     debug(F100,"ttvt setting modes...","",0);
  1461.     if (xlocal) { /* For external lines... */
  1462. s2 = (int) (speed / 10L);
  1463. s = ttsspd(s2); /* Check/set the speed */
  1464. carrctl(&tttvt, flow != FLO_DIAL /* Do carrier control */
  1465. && (ttcarr == CAR_ON || (ttcarr == CAR_AUT && ttmdm != 0)));
  1466.     } else
  1467.       s = s2 = -1;
  1468. #ifdef COHERENT
  1469. #define SVORPOSIX
  1470. #endif /* COHERENT */
  1471. #ifndef SVORPOSIX
  1472.     /* Berkeley, V7, etc */
  1473.     if (flow == FLO_RTSC || /* Hardware flow control */
  1474. flow == FLO_DTRC ||
  1475. flow == FLO_DTRT) {
  1476. tthflow(flow, 1, &tttvt);
  1477. debug(F100,"ttvt hard flow, TANDEM off","",0);
  1478. tttvt.sg_flags &= ~TANDEM; /* Turn off software flow control */
  1479.     } else if (flow == FLO_XONX) { /* Xon/Xoff flow control */
  1480. debug(F100,"ttvt TANDEM on","",0);
  1481. tttvt.sg_flags |= TANDEM; /* Ask for it. */
  1482. tthflow(flow, 0, &tttvt); /* Turn off hardware f/c */
  1483.     } else if (flow == FLO_NONE) {
  1484. debug(F100,"ttvt no flow, TANDEM off, RAW on","",0);
  1485. tttvt.sg_flags &= ~TANDEM; /* Turn off software flow control */
  1486. tthflow(flow, 0, &tttvt); /* Turn off any hardware f/c too */
  1487. tttvt.sg_flags |= RAW; /* Enter raw mode */
  1488.     } else if (flow == FLO_KEEP) { /* Keep device's original setting */
  1489. debug(F100,"ttvt keeping original TANDEM","",0);
  1490. tttvt.sg_flags &= ~TANDEM;
  1491. tttvt.sg_flags |= (ttold.sg_flags & TANDEM);
  1492. /* NOTE: We should also handle hardware flow control here! */
  1493.     }
  1494.     tttvt.sg_flags |= RAW;              /* Raw mode in all cases */
  1495. #ifdef TOWER1
  1496.     tttvt.sg_flags &= ~(ECHO|ANYP);     /* No echo or parity */
  1497. #else
  1498.     tttvt.sg_flags &= ~ECHO;            /* No echo */
  1499. #endif /* TOWER1 */
  1500. #ifdef BELLV10
  1501.     if (ioctl(ttyfd,TIOCSETP,&tttvt) < 0) /* Set the new modes */
  1502.       return(-1);
  1503. #else
  1504.     if (stty(ttyfd,&tttvt) < 0) /* Set the new modes */
  1505.       return(-1);
  1506. #endif /* BELLV10 */
  1507. #else /* It is ATTSV or POSIX */
  1508.     if (flow == FLO_XONX) { /* Software flow control */
  1509. tttvt.c_iflag |= (IXON|IXOFF); /* On if requested. */
  1510. tthflow(flow, 0, &tttvt); /* Turn off hardware f/c */
  1511. debug(F100,"ttvt SVORPOSIX flow XON/XOFF","",0);
  1512.     } else if (flow == FLO_NONE) { /* NONE */
  1513. tttvt.c_iflag &= ~(IXON|IXOFF); /* Turn off Xon/Xoff */
  1514. tthflow(flow, 0, &tttvt); /* Turn off hardware f/c */
  1515. debug(F100,"ttvt SVORPOSIX flow NONE","",0);
  1516.     } else if (flow == FLO_KEEP) {
  1517. tttvt.c_iflag &= ~(IXON|IXOFF); /* Turn off Xon/Xoff flags */
  1518. tttvt.c_iflag |= (ttold.c_iflag & (IXON|IXOFF)); /* OR in old ones */
  1519. #ifdef POSIX_CRTSCTS
  1520.         tttvt.c_cflag &= ~CRTSCTS; /* Turn off RTS/CTS flag */
  1521.         tttvt.c_cflag |= (ttold.c_cflag & CRTSCTS); /* OR in old one */
  1522. #endif /* POSIX_CRTSCTS */
  1523. debug(F100,"ttvt SVORPOSIX flow KEEP","",0);
  1524.     } else if (flow == FLO_RTSC || /* Hardware flow control */
  1525.        flow == FLO_DTRC ||
  1526.        flow == FLO_DTRT) {
  1527. tttvt.c_iflag &= ~(IXON|IXOFF); /* (196) */
  1528. tthflow(flow, 1, &tttvt);
  1529. debug(F100,"ttvt SVORPOSIX flow HARD","",0);
  1530.     }
  1531. #ifndef OXOS
  1532. #ifdef COHERENT
  1533.     tttvt.c_lflag &= ~(ISIG|ICANON|ECHO);
  1534. #else
  1535.     tttvt.c_lflag &= ~(ISIG|ICANON|ECHO|IEXTEN);
  1536. #endif /* COHERENT */
  1537. #ifdef QNX
  1538.     /* Needed for hwfc */
  1539.     if (flow == FLO_RTSC || flow == FLO_DTRC || flow == FLO_DTRT)
  1540.       tttvt.c_lflag |= IEXTEN;
  1541. #endif /* QNX */
  1542. #else /* OXOS */
  1543.     tttvt.c_lflag &= ~(ISIG|ICANON|ECHO);
  1544.     tttvt.c_cc[VDISCARD] = tttvt.c_cc[VLNEXT] = CDISABLE;
  1545. #endif /* OXOS */
  1546.     tttvt.c_iflag |= (IGNBRK|IGNPAR);
  1547. /* Parity */
  1548. #ifdef HWPARITY
  1549.     if (hwparity && xlocal) { /* Hardware parity */
  1550. #ifdef CSTOPB
  1551. if (stopbits == 2) {
  1552.     ttraw.c_cflag |= CSTOPB; /* 2 stop bits */
  1553.     debug(F100,"ttpkt 2 stopbits","",0);
  1554. } else if (stopbits == 1) {
  1555.     ttraw.c_cflag &= ~(CSTOPB); /* 1 stop bit */
  1556.     debug(F100,"ttpkt 1 stopbit","",0);
  1557. }
  1558. #endif /* CSTOPB */
  1559. tttvt.c_cflag |= PARENB; /* Enable parity */
  1560. switch (hwparity) {
  1561.   case 'e': /* Even */
  1562.     tttvt.c_cflag &= ~(PARODD);
  1563.     debug(F100,"ttvt 8 bits + even parity","",0);
  1564.     break;
  1565.   case 'o': /* Odd */
  1566.     tttvt.c_cflag |= PARODD;
  1567.     debug(F100,"ttvt 8 bits + odd parity","",0);
  1568.     break;
  1569.   case 'm': /* Mark */
  1570.   case 's': /* Space */
  1571.     debug(F100,"ttvt 8 bits + invalid parity","",0);
  1572.     break;
  1573. }
  1574.     } else { /* We handle parity ourselves */
  1575. #endif /* HWPARITY */
  1576. tttvt.c_cflag &= ~(PARENB); /* Don't enable parity */
  1577. #ifdef HWPARITY
  1578.     }
  1579. #endif /* HWPARITY */
  1580. #ifdef ATTSV
  1581. #ifdef BSD44
  1582.     /* Things not to do... */
  1583.     tttvt.c_iflag &= ~(INLCR|IGNCR|ICRNL|INPCK|ISTRIP|IXANY);
  1584. #else
  1585.     tttvt.c_iflag &= ~(INLCR|IGNCR|ICRNL|IUCLC|INPCK|ISTRIP|IXANY);
  1586. #endif /* BSD44 */
  1587. #else /* POSIX */
  1588.     tttvt.c_iflag &= ~(INLCR|IGNCR|ICRNL|INPCK|ISTRIP);
  1589. #endif /* ATTSV */
  1590.     tttvt.c_cflag &= ~(CSIZE); /* Zero out the char size field */
  1591.     tttvt.c_cflag |= (CS8|CREAD|HUPCL); /* Char size 8, enable receiver, hup */
  1592.     tttvt.c_oflag &= ~OPOST; /* Don't postprocess output */
  1593. #ifndef VEOF /* DGUX termio has VEOF at entry 4, see comment above */
  1594.     tttvt.c_cc[4] = 1;
  1595. #else
  1596. #ifndef OXOS
  1597. #ifdef VMIN
  1598.     tttvt.c_cc[VMIN] = 1;
  1599. #endif /* VMIN */
  1600. #else /* OXOS */
  1601.     tttvt.c_min = 1;
  1602. #endif /* OXOS */
  1603. #endif /* VEOF */
  1604. #ifndef VEOL /* DGUX termio has VEOL at entry 5, see comment above */
  1605.     tttvt.c_cc[5] = 0;
  1606. #else
  1607. #ifndef OXOS
  1608. #ifdef VTIME
  1609.     tttvt.c_cc[VTIME] = 0;
  1610. #endif /* VTIME */
  1611. #else /* OXOS */
  1612.     tttvt.c_time = 0;
  1613. #endif /* OXOS */
  1614. #endif /* VEOL */
  1615. #ifdef Plan9
  1616.     if (p9ttyparity('n') < 0)
  1617.       return -1;
  1618. #else
  1619. #ifdef BSD44ORPOSIX
  1620. #ifdef BEOSORBEBOX
  1621.     tttvt.c_cc[VMIN] = 0; /* DR7 can only poll. */
  1622. #endif /* BEOSORBEBOX */
  1623.     if (tcsetattr(ttyfd,TCSADRAIN,&tttvt) < 0) return(-1);
  1624. #else /* ATTSV */
  1625.     if (ioctl(ttyfd,TCSETAW,&tttvt) < 0) return(-1);  /* set new modes . */
  1626. #endif /* BSD44ORPOSIX */
  1627. #endif /* Plan9 */
  1628. #endif /* ATTSV */
  1629.     ttspeed = speed; /* Done, remember how we were */
  1630.     ttflow = flow; /* called, so we can decide how to */
  1631.     tvtflg = 1; /* respond next time. */
  1632.     debug(F101,"ttvt done","",tvtflg);
  1633.     return(0);
  1634. #ifdef COHERENT
  1635. #undef SVORPOSIX
  1636. #endif /* COHERENT */
  1637. #endif /* NOLOCAL */
  1638. }
  1639. #ifndef NOLOCAL
  1640. /* Serial speed department . . . */
  1641. /*
  1642.   Plan 9's native speed setting interface lets you set anything you like,
  1643.   but will fail if the hardware doesn't like it, so we allow all the common
  1644.   speeds.
  1645. */
  1646. #ifdef Plan9
  1647. #ifndef B50
  1648. #define B50 50
  1649. #endif /* B50 */
  1650. #ifndef B75
  1651. #define B75 75
  1652. #endif /* B75 */
  1653. #ifndef B110
  1654. #define B110 110
  1655. #endif /* B110 */
  1656. #ifndef B134
  1657. #define B134 134
  1658. #endif /* B134 */
  1659. #ifndef B200
  1660. #define B200 200
  1661. #endif /* B200 */
  1662. #ifndef B300
  1663. #define B300 300
  1664. #endif /* B300 */
  1665. #ifndef B1200
  1666. #define B1200 1200
  1667. #endif /* B1200 */
  1668. #ifndef B1800
  1669. #define B1800 1800
  1670. #endif /* B1800 */
  1671. #ifndef B2400
  1672. #define B2400 2400
  1673. #endif /* B2400 */
  1674. #ifndef B4800
  1675. #define B4800 4800
  1676. #endif /* B4800 */
  1677. #ifndef B9600
  1678. #define B9600 9600
  1679. #endif /* B9600 */
  1680. #ifndef B14400
  1681. #define B14400 14400
  1682. #endif /* B14400 */
  1683. #ifndef B19200
  1684. #define B19200 19200
  1685. #endif /* B19200 */
  1686. #ifndef B28800
  1687. #define B28800 28800
  1688. #endif /* B28800 */
  1689. #ifndef B38400
  1690. #define B38400 38400
  1691. #endif /* B38400 */
  1692. #ifndef B57600
  1693. #define B57600 57600
  1694. #endif /* B57600 */
  1695. #ifndef B76800
  1696. #define B76800 76800
  1697. #endif /* B76800 */
  1698. #ifndef B115200
  1699. #define B115200 115200
  1700. #endif /* B115200 */
  1701. #ifndef B230400
  1702. #define B230400 230400
  1703. #endif /* B230400 */
  1704. #ifndef B460800
  1705. #define B460800 460800
  1706. #endif /* B460800 */
  1707. #ifndef B921600
  1708. #define B921600 921600
  1709. #endif /* B921600 */
  1710. #endif /* Plan9 */
  1711. /*  T T S S P D  --  Checks and sets transmission rate.  */
  1712. /*  Call with speed in characters (not bits!) per second. */
  1713. /*  Returns -1 on failure, 0 if it did nothing, 1 if it changed the speed. */
  1714. #ifdef USETCSETSPEED
  1715. /*
  1716.   The tcsetspeed() / tcgetspeed() interface lets you pass any number at all
  1717.   to be used as a speed to be set, rather than forcing a choice from a
  1718.   predefined list.  It seems to be peculiar to UnixWare 7.
  1719.   These are the function codes to be passed to tc[gs]etspeed(),
  1720.   but for some reason they don't seem to be picked up from termios.h.
  1721. */
  1722. #ifndef TCS_ALL
  1723. #define TCS_ALL 0
  1724. #endif /* TCS_ALL */
  1725. #ifndef TCS_IN
  1726. #define TCS_IN 1
  1727. #endif /* TCS_IN */
  1728. #ifndef TCS_OUT
  1729. #define TCS_OUT 2
  1730. #endif /* TCS_OUT */
  1731. #endif /* USETCSETSPEED */
  1732. int
  1733. ttsspd(cps) int cps; {
  1734.     int x;
  1735. #ifdef POSIX
  1736. /* Watch out, speed_t should be unsigned, so don't compare with -1, etc... */
  1737.     speed_t
  1738. #else
  1739.     int
  1740. #endif /* POSIX */
  1741.       s, s2;
  1742.     int ok = 1; /* Speed check result, assume ok */
  1743. #ifdef OLINUXHISPEED
  1744.     unsigned int spd_flags = 0;
  1745.     struct serial_struct serinfo;
  1746. #endif /* OLINUXHISPEED */
  1747.     debug(F101,"ttsspd cps","",cps);
  1748.     debug(F101,"ttsspd ttyfd","",ttyfd);
  1749.     debug(F101,"ttsspd xlocal","",xlocal);
  1750.     if (ttyfd < 0 || xlocal == 0 ) /* Don't set speed on console */
  1751.       return(0);
  1752. #ifdef NETCONN
  1753.     if (netconn)
  1754.       return(0);
  1755. #endif /* NETCONN */
  1756. #ifdef NETCMD
  1757.     if (ttpipe) return(0);
  1758. #endif /* NETCMD */
  1759. #ifdef NETPTY
  1760.     if (ttpty) return(0);
  1761. #endif /* NETPTY */
  1762.     if (cps < 0) return(-1);
  1763.     s = s2 = 0; /* NB: s and s2 might be unsigned */
  1764. #ifdef USETCSETSPEED
  1765.     s = cps * 10L;
  1766.     x = tcgetattr(ttyfd,&ttcur); /* Get current speed */
  1767.     debug(F101,"ttsspd tcgetattr","",x);
  1768.     if (x < 0)
  1769.       return(-1);
  1770.     debug(F101,"ttsspd TCSETSPEED speed","",s);
  1771.     errno = 0;
  1772.     if (s == 8880L) { /* 75/1200 split speed requested */
  1773. tcsetspeed(TCS_IN, &ttcur, 1200L);
  1774. tcsetspeed(TCS_OUT, &ttcur, 75L);
  1775.     } else
  1776.       tcsetspeed(TCS_ALL, &ttcur, s); /* Put new speed in structs */
  1777. #ifdef DEBUG
  1778.     if (errno & deblog) {
  1779. debug(F101,"ttsspd TCSETSPEED errno","",errno);
  1780.     }
  1781. #endif /* DEBUG */
  1782. #ifdef COMMENT
  1783.     tcsetspeed(TCS_ALL, &ttraw, s);
  1784.     tcsetspeed(TCS_ALL, &tttvt, s);
  1785.     tcsetspeed(TCS_ALL, &ttold, s);
  1786. #else
  1787.     if (s == 8880L) { /* 75/1200 split speed requested */
  1788. tcsetspeed(TCS_IN, &ttraw, 1200L);
  1789. tcsetspeed(TCS_OUT, &ttraw, 75L);
  1790. tcsetspeed(TCS_IN, &tttvt, 1200L);
  1791. tcsetspeed(TCS_OUT, &tttvt, 75L);
  1792. tcsetspeed(TCS_IN, &ttold, 1200L);
  1793. tcsetspeed(TCS_OUT, &ttold, 75L);
  1794.     } else {
  1795. tcsetspeed(TCS_ALL, &ttraw, s);
  1796. tcsetspeed(TCS_ALL, &tttvt, s);
  1797. tcsetspeed(TCS_ALL, &ttold, s);
  1798.     }
  1799. #endif /* COMMENT */
  1800.     x = tcsetattr(ttyfd,TCSADRAIN,&ttcur); /* Set the speed */
  1801.     debug(F101,"ttsspd tcsetattr","",x);
  1802.     if (x < 0)
  1803.       return(-1);
  1804. #else  /* Not USETCSETSPEED */
  1805. #ifdef MINIX2        /* Hack alert */
  1806. #define MINIX        /* Use pre-2.0 speed selection for Minix 2.0 as well */
  1807. #endif /* MINIX2 */
  1808.     /* First check that the given speed is valid. */
  1809.     switch (cps) {
  1810. #ifndef MINIX
  1811.       case 0:   s = B0;    break;
  1812.       case 5:   s = B50;   break;
  1813.       case 7:   s = B75;   break;
  1814. #endif /* MINIX */
  1815.       case 11:  s = B110;  break;
  1816. #ifndef MINIX
  1817.       case 13:  s = B134;  break;
  1818.       case 15:  s = B150;  break;
  1819.       case 20:  s = B200;  break;
  1820. #endif /* MINIX */
  1821.       case 30:  s = B300;  break;
  1822. #ifndef MINIX
  1823.       case 60:  s = B600;  break;
  1824. #endif /* MINIX */
  1825.       case 120: s = B1200; break;
  1826. #ifndef MINIX
  1827.       case 180: s = B1800; break;
  1828. #endif /* MINIX */
  1829.       case 240: s = B2400; break;
  1830.       case 480: s = B4800; break;
  1831. #ifndef MINIX
  1832.       case 888: s = B75; s2 = B1200; break; /* 888 = 75/1200 split speed */
  1833. #endif /* MINIX */
  1834. #ifdef B7200
  1835.       case 720: s = B7200; break;
  1836. #endif /* B7200 */
  1837.       case 960: s = B9600; break;
  1838. #ifdef B14400
  1839.       case 1440: s = B14400; break;
  1840. #endif /* B14400 */
  1841. #ifdef B19200
  1842.       case 1920: s = B19200; break;
  1843. #else
  1844. #ifdef EXTA
  1845.       case 1920: s = EXTA; break;
  1846. #endif /* EXTA */
  1847. #endif /* B19200 */
  1848. #ifdef B28800
  1849.       case 2880: s = B28800; break;
  1850. #endif /* B28800 */
  1851. #ifdef B38400
  1852.       case 3840: s = B38400;
  1853. #ifdef OLINUXHISPEED
  1854.         spd_flags = ~ASYNC_SPD_MASK; /* Nonzero, but zero flags */
  1855. #endif /* OLINUXHISPEED */
  1856. break;
  1857. #else /* B38400 not defined... */
  1858. #ifdef EXTB
  1859.       case 3840: s = EXTB; break;
  1860. #endif /* EXTB */
  1861. #endif /* B38400 */
  1862. #ifdef HPUX
  1863. #ifdef _B57600
  1864.       case 5760: s = _B57600; break;
  1865. #endif /* _B57600 */
  1866. #ifdef _B115200
  1867.       case 11520: s = _B115200; break;
  1868. #endif /* _B115200 */
  1869. #else
  1870. #ifdef OLINUXHISPEED
  1871. /*
  1872.   This bit from <carlo@sg.tn.tudelft.nl>:
  1873.   "Only note to make is maybe this: When the ASYNC_SPD_CUST flags are set then
  1874.   setting the speed to 38400 will set the custom speed (and ttgspd returns
  1875.   38400), but speeds 57600 and 115200 won't work any more because I didn't
  1876.   want to mess up the speed flags when someone is doing sophisticated stuff
  1877.   like custom speeds..."
  1878. */
  1879.       case 5760: s = B38400; spd_flags = ASYNC_SPD_HI; break;
  1880.       case 11520: s = B38400; spd_flags = ASYNC_SPD_VHI; break;
  1881. #else
  1882. #ifdef B57600
  1883.       case 5760: s = B57600; break;
  1884. #endif /* B57600 */
  1885. #ifdef B76800
  1886.       case 7680: s = B76800; break;
  1887. #endif /* B76800 */
  1888. #ifdef B115200
  1889.       case 11520: s = B115200; break;
  1890. #endif /* B115200 */
  1891. #endif /* OLINUXHISPEED */
  1892. #ifdef B153600
  1893.       case 15360: s = B153600; break;
  1894. #endif /* B153600 */
  1895. #ifdef B230400
  1896.       case 23040: s = B230400; break;
  1897. #endif /* B230400 */
  1898. #ifdef B307200
  1899.       case 30720: s = B307200; break;
  1900. #endif /* B307200 */
  1901. #ifdef B460800
  1902.       case 46080: s = B460800; break;
  1903. #endif /* 460800 */
  1904. #ifdef B921600
  1905.       case 92160: s = B921600; break;
  1906. #endif /* B921600 */
  1907. #endif /* HPUX */
  1908.       default:
  1909. ok = 0; /* Good speed not found, so not ok */
  1910. break;
  1911.     }
  1912.     debug(F101,"ttsspd ok","",ok);
  1913.     debug(F101,"ttsspd s","",s);
  1914.     if (!ok) {
  1915. debug(F100,"ttsspd fails","",0);
  1916. return(-1);
  1917.     } else {
  1918. if (!s2) s2 = s; /* Set input speed */
  1919. #ifdef Plan9
  1920. if (p9ttsspd(cps) < 0)
  1921.   return(-1);
  1922. #else
  1923. #ifdef BSD44ORPOSIX
  1924. x = tcgetattr(ttyfd,&ttcur); /* Get current speed */
  1925. debug(F101,"ttsspd tcgetattr","",x);
  1926. if (x < 0)
  1927.   return(-1);
  1928. #ifdef OLINUXHISPEED
  1929. debug(F101,"ttsspd spd_flags","",spd_flags);
  1930. if (spd_flags && spd_flags != ASYNC_SPD_CUST) {
  1931.     if (ioctl(ttyfd, TIOCGSERIAL, &serinfo) < 0) {
  1932. debug(F100,"ttsspd: TIOCGSERIAL failed","",0);
  1933. return(-1);
  1934.     } else debug(F100,"ttsspd: TIOCGSERIAL ok","",0);
  1935.     serinfo.flags &= ~ASYNC_SPD_MASK;
  1936.     serinfo.flags |= (spd_flags & ASYNC_SPD_MASK);
  1937.     if (ioctl(ttyfd, TIOCSSERIAL, &serinfo) < 0)
  1938.       return(-1);
  1939. }
  1940. #endif /* OLINUXHISPEED */
  1941. cfsetospeed(&ttcur,s);
  1942. cfsetispeed(&ttcur,s2);
  1943. cfsetospeed(&ttraw,s);
  1944. cfsetispeed(&ttraw,s2);
  1945. cfsetospeed(&tttvt,s);
  1946. cfsetispeed(&tttvt,s2);
  1947. cfsetospeed(&ttold,s);
  1948. cfsetispeed(&ttold,s2);
  1949. x = tcsetattr(ttyfd,TCSADRAIN,&ttcur);
  1950. debug(F101,"ttsspd tcsetattr","",x);
  1951. if (x < 0) return(-1);
  1952. #else
  1953. #ifdef ATTSV
  1954. if (cps == 888) return(-1); /* No split speeds, sorry. */
  1955. x = ioctl(ttyfd,TCGETA,&ttcur);
  1956. debug(F101,"ttsspd TCGETA ioctl","",x);
  1957. if (x < 0) return(-1);
  1958. ttcur.c_cflag &= ~CBAUD;
  1959. ttcur.c_cflag |= s;
  1960. tttvt.c_cflag &= ~CBAUD;
  1961. tttvt.c_cflag |= s;
  1962. ttraw.c_cflag &= ~CBAUD;
  1963. ttraw.c_cflag |= s;
  1964. ttold.c_cflag &= ~CBAUD;
  1965. ttold.c_cflag |= s;
  1966. x = ioctl(ttyfd,TCSETAW,&ttcur);
  1967. debug(F101,"ttsspd TCSETAW ioctl","",x);
  1968. if (x < 0) return(-1);
  1969. #else
  1970. #ifdef BELLV10
  1971. x = ioctl(ttyfd,TIOCGDEV,&tdcur);
  1972. debug(F101,"ttsspd TIOCGDEV ioctl","",x);
  1973. if (x < 0) return(-1);
  1974. tdcur.ispeed = s2;
  1975. tdcur.ospeed = s;
  1976. errno = 0;
  1977. ok = ioctl(ttyfd,TIOCSDEV,&tdcur);
  1978. debug(F101,"ttsspd BELLV10 ioctl","",ok);
  1979. if (ok < 0) {
  1980.     perror(ttnmsv);
  1981.     debug(F101,"ttsspd BELLV10 errno","",ok);
  1982.     return(-1);
  1983. }
  1984. #else
  1985. x = gtty(ttyfd,&ttcur);
  1986. debug(F101,"ttsspd gtty","",x);
  1987. if (x < 0) return(-1);
  1988. ttcur.sg_ospeed = s; ttcur.sg_ispeed = s2;
  1989. tttvt.sg_ospeed = s; tttvt.sg_ispeed = s2;
  1990. ttraw.sg_ospeed = s; ttraw.sg_ispeed = s2;
  1991. ttold.sg_ospeed = s; ttold.sg_ispeed = s2;
  1992. x = stty(ttyfd,&ttcur);
  1993. debug(F101,"ttsspd stty","",x);
  1994. if (x < 0) return(-1);
  1995. #endif /* BELLV10 */
  1996. #endif /* ATTSV */
  1997. #endif /* BSD44ORPOSIX */
  1998. #endif /* Plan9 */
  1999.     }
  2000.     return(1); /* Return 1 = success. */
  2001. #endif /* USETCSETSPEED */
  2002. }
  2003. #endif /* NOLOCAL */
  2004. /* C O N G S P D  -  Get speed of console terminal  */
  2005. long
  2006. congspd() {
  2007. /*
  2008.   This is a disgusting hack.  The right way to do this would be to pass an
  2009.   argument to ttgspd(), but then we'd need to change the Kermit API and
  2010.   all of the ck?tio.c modules.  (Currently used only for rlogin.)
  2011. */
  2012.     int t1, t2;
  2013.     long spd;
  2014. #ifdef NETCONN
  2015.     t2 = netconn;
  2016.     netconn = 0;
  2017. #endif /* NETCONN */
  2018.     t1 = ttyfd;
  2019.     ttyfd = -1;
  2020.     spd = ttgspd();
  2021.     debug(F101,"congspd","",spd);
  2022. #ifdef NETCONN
  2023.     netconn = t2;
  2024. #endif /* NETCONN */
  2025.     ttyfd = t1;
  2026.     return(spd);
  2027. }
  2028. /*  T T S P D L I S T  -- Get list of serial speeds allowed on this platform */
  2029. #define NSPDLIST 64
  2030. static long spdlist[NSPDLIST];
  2031. /*
  2032.   As written, this picks up the speeds known at compile time, and thus
  2033.   apply to the system where C-Kermit was built, rather than to the one where
  2034.   it is running.  Suggestions for improvement are always welcome.
  2035. */
  2036. long *
  2037. ttspdlist() {
  2038.     int i;
  2039.     for (i = 0; i < NSPDLIST; i++) /* Initialize the list */
  2040.       spdlist[i] = -1L;
  2041.     i = 1;
  2042. #ifdef USETCSETSPEED /* No way to find out what's legal */
  2043.     spdlist[i++] = 50L;
  2044. #ifndef UW7
  2045.     spdlist[i++] = 75L;
  2046. #endif /* UW7 */
  2047.     spdlist[i++] = 110L;
  2048. #ifndef UW7
  2049.     spdlist[i++] = 134L;
  2050. #endif /* UW7 */
  2051.     spdlist[i++] = 150L;
  2052.     spdlist[i++] = 200L;
  2053.     spdlist[i++] = 300L;
  2054.     spdlist[i++] = 600L;
  2055.     spdlist[i++] = 1200L;
  2056.     spdlist[i++] = 1800L;
  2057.     spdlist[i++] = 2400L;
  2058.     spdlist[i++] = 4800L;
  2059.     spdlist[i++] = 8880L;
  2060.     spdlist[i++] = 9600L;
  2061.     spdlist[i++] = 14400L;
  2062.     spdlist[i++] = 19200L;
  2063.     spdlist[i++] = 28800L;
  2064. #ifndef UW7
  2065.     spdlist[i++] = 33600L;
  2066. #endif /* UW7 */
  2067.     spdlist[i++] = 38400L;
  2068.     spdlist[i++] = 57600L;
  2069.     spdlist[i++] = 76800L;
  2070.     spdlist[i++] = 115200L;
  2071. #ifndef UW7
  2072.     spdlist[i++] = 153600L;
  2073.     spdlist[i++] = 230400L;
  2074.     spdlist[i++] = 307200L;
  2075.     spdlist[i++] = 460800L;
  2076.     spdlist[i++] = 921600L;
  2077. #endif /* UW7 */
  2078. #else  /* USETCSETSPEED */
  2079. #ifdef B50
  2080.     spdlist[i++] = 50L;
  2081. #endif /* B50 */
  2082. #ifdef B75
  2083.     spdlist[i++] = 75L;
  2084. #endif /* B75 */
  2085. #ifdef B110
  2086.     spdlist[i++] = 110L;
  2087. #endif /* B110 */
  2088. #ifdef B134
  2089.     spdlist[i++] = 134L;
  2090. #endif /* B134 */
  2091. #ifdef B150
  2092.     spdlist[i++] = 150L;
  2093. #endif /* B150 */
  2094. #ifdef B200
  2095.     spdlist[i++] = 200L;
  2096. #endif /* B200 */
  2097. #ifdef B300
  2098.     spdlist[i++] = 300L;
  2099. #endif /* B300 */
  2100. #ifdef B600
  2101.     spdlist[i++] = 600L;
  2102. #endif /* B600 */
  2103. #ifdef B1200
  2104.     spdlist[i++] = 1200L;
  2105. #endif /* B1200 */
  2106. #ifdef B1800
  2107.     spdlist[i++] = 1800L;
  2108. #endif /* B1800 */
  2109. #ifdef B2400
  2110.     spdlist[i++] = 2400L;
  2111. #endif /* B2400 */
  2112. #ifdef B4800
  2113.     spdlist[i++] = 4800L;
  2114. #endif /* B4800 */
  2115. #ifdef B9600
  2116.     spdlist[i++] = 9600L;
  2117. #endif /* B9600 */
  2118. #ifdef B14400
  2119.     spdlist[i++] = 14400L;
  2120. #endif /* B14400 */
  2121. #ifdef B19200
  2122.     spdlist[i++] = 19200L;
  2123. #else
  2124. #ifdef EXTA
  2125.     spdlist[i++] = 19200L;
  2126. #endif /* EXTA */
  2127. #endif /* B19200 */
  2128. #ifdef B28800
  2129.     spdlist[i++] = 28800L;
  2130. #endif /* B28800 */
  2131. #ifdef B33600
  2132.     spdlist[i++] = 33600L;
  2133. #endif /* B33600 */
  2134. #ifdef B38400
  2135.     spdlist[i++] = 38400L;
  2136. #else
  2137. #ifdef EXTB
  2138.     spdlist[i++] = 38400L;
  2139. #endif /* EXTB */
  2140. #endif /* B38400 */
  2141. #ifdef _B57600
  2142.     spdlist[i++] = 57600L;
  2143. #else
  2144. #ifdef B57600
  2145.     spdlist[i++] = 57600L;
  2146. #endif /* B57600 */
  2147. #endif /* _B57600 */
  2148. #ifdef B76800
  2149.     spdlist[i++] = 76800L;
  2150. #endif /* B76800 */
  2151. #ifdef _B115200
  2152.     spdlist[i++] = 115200L;
  2153. #else
  2154. #ifdef B115200
  2155.     spdlist[i++] = 115200L;
  2156. #endif /* B115200 */
  2157. #endif /* _B115200 */
  2158. #ifdef B153600
  2159.     spdlist[i++] = 153600L;
  2160. #endif /* B153600 */
  2161. #ifdef B230400
  2162.     spdlist[i++] = 230400L;
  2163. #endif /* B230400 */
  2164. #ifdef B307200
  2165.     spdlist[i++] = 307200L;
  2166. #endif /* B307200 */
  2167. #ifdef B460800
  2168.     spdlist[i++] = 460800L;
  2169. #endif /* B460800 */
  2170. #ifdef B921600
  2171.     spdlist[i++] = 921600L;
  2172. #endif /* B921600 */
  2173. #endif /* USETCSETSPEED */
  2174.     spdlist[0] = i - 1; /* Return count in 0th element */
  2175.     return((long *)spdlist);
  2176. }
  2177. /* T T G S P D  -  Get speed of currently selected tty line  */
  2178. /*
  2179.   Unreliable.  After SET LINE, it returns an actual speed, but not necessarily
  2180.   the real speed.  On some systems, it returns the line's nominal speed, from
  2181.   /etc/ttytab.  Even if you SET SPEED to something else, this function might
  2182.   not notice.
  2183. */
  2184. long
  2185. ttgspd() { /* Get current serial device speed */
  2186. #ifdef NOLOCAL
  2187.     return(-1L);
  2188. #else
  2189. #ifdef POSIX
  2190.     speed_t /* Should be unsigned */
  2191. #else
  2192.     int /* Isn't unsigned */
  2193. #endif /* POSIX */
  2194.       s;
  2195.     int x;
  2196.     long ss;
  2197. #ifdef OLINUXHISPEED
  2198.     unsigned int spd_flags = 0;
  2199.     struct serial_struct serinfo;
  2200. #endif /* OLINUXHISPEED */
  2201. #ifdef NETCONN
  2202.     if (netconn) return(-1); /* -1 if network connection */
  2203. #endif /* NETCONN */
  2204. #ifdef NETCMD
  2205.     if (ttpipe) return(-1);
  2206. #endif /* NETCMD */
  2207. #ifdef NETPTY
  2208.     if (ttpty) return(-1);
  2209. #endif /* NETPTY */
  2210.     debug(F101,"ttgspd ttyfd","",ttyfd);
  2211. #ifdef USETCSETSPEED
  2212.     x = tcgetattr(ttyfd,&ttcur); /* Get current speed */
  2213.     debug(F101,"ttgspd tcgetattr","",x);
  2214.     if (x < 0)
  2215.       return(-1);
  2216.     errno = 0;
  2217.     s = tcgetspeed(TCS_ALL, &ttcur);
  2218.     debug(F101,"ttsspd TCGETSPEED speed","",s);
  2219.     if (s == 0) {
  2220. long s1, s2;
  2221. s1 = tcgetspeed(TCS_IN, &ttcur);
  2222. s2 = tcgetspeed(TCS_OUT, &ttcur);
  2223. if (s1 == 1200L && s2 == 75L)
  2224.   return(8880L);
  2225.     }
  2226. #ifdef DEBUG
  2227.     if (errno & deblog) {
  2228. debug(F101,"ttsspd TCGETSPEED errno","",errno);
  2229.     }
  2230. #endif /* DEBUG */
  2231.     return(s);
  2232. #else  /* Not USETCSETSPEED */
  2233. #ifdef Plan9
  2234.     if (ttyfd < 0)
  2235.       ss = -1;
  2236.     else
  2237.       ss = ttylastspeed;
  2238. #else
  2239. #ifdef OLINUXHISPEED
  2240.     debug(F100,"ttgspd Linux OLINUXHISPEED","",0);
  2241. #endif /* OLINUXHISPEED */
  2242.     if (ttyfd < 0) {
  2243. #ifdef BSD44ORPOSIX
  2244. s = cfgetospeed(&ccold);
  2245. debug(F101,"ttgspd cfgetospeed 1 POSIX","",s);
  2246. #else
  2247. #ifdef ATTSV
  2248. s = ccold.c_cflag & CBAUD;
  2249. debug(F101,"ttgspd c_cflag CBAUD 1 ATTSV","",s);
  2250. #else
  2251. s = ccold.sg_ospeed; /* (obtained by congm()) */
  2252. debug(F101,"ttgspd sg_ospeed 1","",s);
  2253. #endif /* ATTSV */
  2254. #endif /* BSD44POSIX */
  2255.     } else {
  2256. #ifdef BSD44ORPOSIX
  2257. if (tcgetattr(ttyfd,&ttcur) < 0) return(-1);
  2258. s = cfgetospeed(&ttcur);
  2259. debug(F101,"ttgspd cfgetospeed 2 BSDORPOSIX","",s);
  2260. #ifdef OLINUXHISPEED
  2261. if (ioctl(ttyfd,TIOCGSERIAL,&serinfo) > -1)
  2262.   spd_flags = serinfo.flags & ASYNC_SPD_MASK;
  2263. debug(F101,"ttgspd spd_flags","",spd_flags);
  2264. #endif /* OLINUXHISPEED */
  2265. #else
  2266. #ifdef ATTSV
  2267. x = ioctl(ttyfd,TCGETA,&ttcur);
  2268. debug(F101,"ttgspd ioctl 2 ATTSV x","",x);
  2269. debug(F101,"ttgspd ioctl 2 ATTSV errno","",errno);
  2270. if (x < 0) return(-1);
  2271. s = ttcur.c_cflag & CBAUD;
  2272. debug(F101,"ttgspd ioctl 2 ATTSV speed","",s);
  2273. #else
  2274. #ifdef BELLV10
  2275. x = ioctl(ttyfd,TIOCGDEV,&tdcur);
  2276. debug(F101,"ttgspd ioctl 2 BELLV10 x","",x);
  2277. if (x < 0) return(-1);
  2278. s = tdcur.ospeed;
  2279. debug(F101,"ttgspd ioctl 2 BELLV10 speed","",s);
  2280. #else
  2281. x = gtty(ttyfd,&ttcur);
  2282. debug(F101,"ttgspd gtty 2 x","",x);
  2283. debug(F101,"ttgspd gtty 2 errno","",errno);
  2284. if (x < 0) return(-1);
  2285. s = ttcur.sg_ospeed;
  2286. debug(F101,"ttgspd gtty 2 speed","",s);
  2287. #endif /* BELLV10 */
  2288. #endif /* ATTSV */
  2289. #endif /* BSD44ORPOSIX */
  2290.     }
  2291.     debug(F101,"ttgspd code","",s);
  2292. #ifdef OLINUXHISPEED
  2293.     debug(F101,"ttgspd spd_flags","",spd_flags);
  2294. #endif /* OLINUXHISPEED */
  2295.     switch (s) {
  2296. #ifdef B0
  2297.       case B0:    ss = 0L; break;
  2298. #endif /* B0 */
  2299. #ifndef MINIX
  2300. /*
  2301.  MINIX defines the Bxx symbols to be bps/100, so B50==B75, B110==B134==B150,
  2302.  etc, making for many "duplicate case in switch" errors, which are fatal.
  2303. */
  2304. #ifdef B50
  2305.       case B50:   ss = 50L; break;
  2306. #endif /* B50 */
  2307. #ifdef B75
  2308.       case B75:   ss = 75L; break;
  2309. #endif /* B75 */
  2310. #endif /* MINIX */
  2311. #ifdef B110
  2312.       case B110:  ss = 110L; break;
  2313. #endif /* B110 */
  2314. #ifndef MINIX
  2315. #ifdef B134
  2316.       case B134:  ss = 134L; break;
  2317. #endif /* B134 */
  2318. #ifdef B150
  2319.       case B150:  ss = 150L; break;
  2320. #endif /* B150 */
  2321. #endif /* MINIX */
  2322. #ifdef B200
  2323.       case B200:  ss = 200L; break;
  2324. #endif /* B200 */
  2325. #ifdef B300
  2326.       case B300:  ss = 300L; break;
  2327. #endif /* B300 */
  2328. #ifdef B600
  2329.       case B600:  ss = 600L; break;
  2330. #endif /* B600 */
  2331. #ifdef B1200
  2332.       case B1200: ss = 1200L; break;
  2333. #endif /* B1200 */
  2334. #ifdef B1800
  2335.       case B1800: ss = 1800L; break;
  2336. #endif /* B1800 */
  2337. #ifdef B2400
  2338.       case B2400: ss = 2400L; break;
  2339. #endif /* B2400 */
  2340. #ifdef B4800
  2341.       case B4800: ss = 4800L; break;
  2342. #endif /* B4800 */
  2343. #ifdef B7200
  2344.       case B7200: ss = 7200L; break;
  2345. #endif /* B7200 */
  2346. #ifdef B9600
  2347.       case B9600: ss = 9600L; break;
  2348. #endif /* B9600 */
  2349. #ifdef B19200
  2350.       case B19200: ss = 19200L; break;
  2351. #else
  2352. #ifdef EXTA
  2353.       case EXTA: ss = 19200L; break;
  2354. #endif /* EXTA */
  2355. #endif /* B19200 */
  2356. #ifdef MINIX2
  2357. /* End of hack to make MINIX2 use MINIX1 speed setting */
  2358. #undef MINIX
  2359. #endif /* MINIX2 */
  2360. #ifndef MINIX
  2361. #ifdef B38400
  2362.       case B38400:
  2363.         ss = 38400L;
  2364. #ifdef OLINUXHISPEED
  2365.         switch(spd_flags) {
  2366.           case ASYNC_SPD_HI:  ss =  57600L; break;
  2367.           case ASYNC_SPD_VHI: ss = 115200L; break;
  2368. }
  2369. #endif /* OLINUXHISPEED */
  2370.         break;
  2371. #else
  2372. #ifdef EXTB
  2373.       case EXTB: ss = 38400L; break;
  2374. #endif /* EXTB */
  2375. #endif /* B38400 */
  2376. #endif /* MINIX */
  2377. #ifdef HPUX
  2378. #ifdef _B57600
  2379.       case _B57600: ss = 57600L; break;
  2380. #endif /* _B57600 */
  2381. #ifdef _B115200
  2382.       case _B115200: ss = 115200L; break;
  2383. #endif /* _B115200 */
  2384. #else
  2385. #ifdef B57600
  2386.       case B57600: ss = 57600L; break;
  2387. #endif /* B57600 */
  2388. #ifdef B76800
  2389.       case B76800: ss = 76800L; break;
  2390. #endif /* B76800 */
  2391. #ifdef B115200
  2392.       case B115200: ss = 115200L; break;
  2393. #endif /* B115200 */
  2394. #ifdef B153600
  2395.       case B153600: ss = 153600L; break;
  2396. #endif /* B153600 */
  2397. #ifdef B230400
  2398.       case B230400: ss = 230400L; break;
  2399. #endif /* B230400 */
  2400. #ifdef B307200
  2401.       case B307200: ss = 307200L; break;
  2402. #endif /* B307200 */
  2403. #ifdef B460800
  2404.       case B460800: ss = 460800L; break;
  2405. #endif /* B460800 */
  2406. #endif /* HPUX */
  2407. #ifdef B921600
  2408.       case 92160: ss = 921600L; break;
  2409. #endif /* B921600 */
  2410.       default:
  2411. ss = -1; break;
  2412.     }
  2413. #endif /* Plan9 */
  2414.     debug(F101,"ttgspd speed","",ss);
  2415.     return(ss);
  2416. #endif /* USETCSETSPEED */
  2417. #endif /* NOLOCAL */
  2418. }
  2419. #ifdef MINIX2 /* Another hack alert */
  2420. #define MINIX
  2421. #endif /* MINIX2 */
  2422. /*
  2423.   FIONREAD data type...  This has been defined as "long" for many, many
  2424.   years, and it worked OK until 64-bit platforms appeared.  Thus we use
  2425.   int for 64-bit platforms, but keep long for the others.  If we changed
  2426.   the default PEEKTYPE to int, this would probably break 16-bit builds
  2427.   (note that sizeof(long) == sizeof(int) on most 32-bit platforms), many
  2428.   of which we have no way of testing any more.  Therefore, do not change
  2429.   the default definition of PEEKTYPE -- only add exceptions to it as needed.
  2430. */
  2431. #ifdef COHERENT
  2432. #ifdef FIONREAD
  2433. #undef FIONREAD
  2434. #endif /* FIONREAD */
  2435. /* #define FIONREAD TIOCQUERY */
  2436. /* #define PEEKTYPE int */
  2437. #else  /* Not COHERENT... */
  2438. #ifdef OSF32 /* Digital UNIX 3.2 or higher */
  2439. #define PEEKTYPE int
  2440. #else
  2441. #define PEEKTYPE long /* Elsewhere (see notes above) */
  2442. #endif /* OSF32 */
  2443. #endif /* COHERENT */
  2444. /* ckumyr.c by Kristoffer Eriksson, ske@pkmab.se, 15 Mar 1990. */
  2445. #ifdef MYREAD
  2446. /* Private buffer for myread() and its companions.  Not for use by anything
  2447.  * else.  ttflui() is allowed to reset them to initial values.  ttchk() is
  2448.  * allowed to read my_count.
  2449.  *
  2450.  * my_item is an index into mybuf[].  Increment it *before* reading mybuf[].
  2451.  *
  2452.  * A global parity mask variable could be useful too.  We could use it to
  2453.  * let myread() strip the parity on its own, instead of stripping sign
  2454.  * bits as it does now.
  2455.  */
  2456. #ifdef BIGBUFOK
  2457. #define MYBUFLEN 32768
  2458. #else
  2459. #ifdef pdp11
  2460. #define MYBUFLEN 256
  2461. #else
  2462. #define MYBUFLEN 1024
  2463. #endif /* pdp11 */
  2464. #endif /* BIGBUFOK */
  2465. #ifdef ANYX25
  2466. #undef MYBUFLEN
  2467. #define MYBUFLEN 256
  2468. /*
  2469.   On X.25 connections, there is an extra control byte at the beginning.
  2470. */
  2471. static CHAR x25buf[MYBUFLEN+1]; /* Communication device input buffer */
  2472. static CHAR  *mybuf = x25buf+1;
  2473. #else
  2474. static CHAR mybuf[MYBUFLEN];
  2475. #endif /* ANYX25 */
  2476. static int my_count = 0; /* Number of chars still in mybuf */
  2477. static int my_item = -1; /* Last index read from mybuf[]   */
  2478. /*  T T P E E K  --  Peek into our internal communications input buffers. */
  2479. /*
  2480.   NOTE: This routine is peculiar to UNIX, and is used only by the
  2481.   select()-based CONNECT module, ckucns.c.  It need not be replicated in
  2482.   the ck?tio.c of other platforms.
  2483. */
  2484. int
  2485. ttpeek() {
  2486.     int rc = 0;
  2487. #ifdef TTLEBUF
  2488.     if (ttpush >= 0)
  2489.       rc++;
  2490.     rc += le_inbuf();
  2491.     if (rc > 0)
  2492.       return(rc);
  2493.     else
  2494. #endif /* TTLEBUF */
  2495. #ifdef MYREAD
  2496.     return(my_count);
  2497. #else
  2498.     return(0);
  2499. #endif /* MYREAD */
  2500. }
  2501. /* myread() -- Efficient read of one character from communications line.
  2502.  *
  2503.  * Uses a private buffer to minimize the number of expensive read() system
  2504.  * calls.  Essentially performs the equivalent of read() of 1 character, which
  2505.  * is then returned.  By reading all available input from the system buffers
  2506.  * to the private buffer in one chunk, and then working from this buffer, the
  2507.  * number of system calls is reduced in any case where more than one character
  2508.  * arrives during the processing of the previous chunk, for instance high
  2509.  * baud rates or network type connections where input arrives in packets.
  2510.  * If the time needed for a read() system call approaches the time for more
  2511.  * than one character to arrive, then this mechanism automatically compensates
  2512.  * for that by performing bigger read()s less frequently.  If the system load
  2513.  * is high, the same mechanism compensates for that too.
  2514.  *
  2515.  * myread() is a macro that returns the next character from the buffer.  If the
  2516.  * buffer is empty, mygetbuf() is called.  See mygetbuf() for possible error
  2517.  * returns.
  2518.  *
  2519.  * This should be efficient enough for any one-character-at-a-time loops.
  2520.  * For even better efficiency you might use memcpy()/bcopy() or such between
  2521.  * buffers (since they are often better optimized for copying), but it may not
  2522.  * be worth it if you have to take an extra pass over the buffer to strip
  2523.  * parity and check for CTRL-C anyway.
  2524.  *
  2525.  * Note that if you have been using myread() from another program module, you
  2526.  * may have some trouble accessing this macro version and the private variables
  2527.  * it uses.  In that case, just add a function in this module, that invokes the
  2528.  * macro.
  2529.  */
  2530. #define myread() (--my_count < 0 ? mygetbuf() : 255 & (int)mybuf[++my_item])
  2531. /* Specification: Push back up to one character onto myread()'s queue.
  2532.  *
  2533.  * This implementation: Push back characters into mybuf. At least one character
  2534.  * must have been read through myread() before myunrd() may be used.  After
  2535.  * EOF or read error, again, myunrd() can not be used.  Sometimes more than
  2536.  * one character can be pushed back, but only one character is guaranteed.
  2537.  * Since a previous myread() must have read its character out of mybuf[],
  2538.  * that guarantees that there is space for at least one character.  If push
  2539.  * back was really needed after EOF, a small addition could provide that.
  2540.  *
  2541.  * myunrd() is currently not called from anywhere inside kermit...
  2542.  */
  2543. #ifdef COMMENT /* not used */
  2544. myunrd(ch) CHAR ch; {
  2545.     if (my_item >= 0) {
  2546. mybuf[my_item--] = ch;
  2547. ++my_count;
  2548.     }
  2549. }
  2550. #endif /* COMMENT */
  2551. /*  T T P U S H B A C K  --  Put n bytes back into the myread buffer */
  2552. static CHAR * pushbuf = NULL;
  2553. static int pushed = 0;
  2554. int
  2555. ttpushback(s,n) CHAR * s; int n; {
  2556.     debug(F101,"ttpushback n","",n);
  2557.     if (pushbuf || n > MYBUFLEN || n < 1)
  2558.       return(-1);
  2559.     debug(F101,"ttpushback my_count","",my_count);
  2560.     if (my_count > 0) {
  2561. if (!(pushbuf = (CHAR *)malloc(n+1)))
  2562.   return(-1);
  2563. memcpy(pushbuf,mybuf,my_count);
  2564. pushed = my_count;
  2565.     }
  2566.     memcpy(mybuf,s,n);
  2567.     my_count = n;
  2568.     my_item = -1;
  2569.     return(0);
  2570. }
  2571. /* mygetbuf() -- Fill buffer for myread() and return first character.
  2572.  *
  2573.  * This function is what myread() uses when it can't get the next character
  2574.  * directly from its buffer.  First, it calls a system dependent myfillbuf()
  2575.  * to read at least one new character into the buffer, and then it returns
  2576.  * the first character just as myread() would have done.  This function also
  2577.  * is responsible for all error conditions that myread() can indicate.
  2578.  *
  2579.  * Returns: When OK => a positive character, 0 or greater.
  2580.  *     When EOF => -2.
  2581.  *     When error => -3, error code in errno.
  2582.  *
  2583.  * Older myread()s additionally returned -1 to indicate that there was nothing
  2584.  * to read, upon which the caller would call myread() again until it got
  2585.  * something.  The new myread()/mygetbuf() always gets something.  If it
  2586.  * doesn't, then make it do so!  Any program that actually depends on the old
  2587.  * behaviour will break.
  2588.  *
  2589.  * The older version also used to return -2 both for EOF and other errors,
  2590.  * and used to set errno to 9999 on EOF.  The errno stuff is gone, EOF and
  2591.  * other errors now return different results, although Kermit currently never
  2592.  * checks to see which it was.  It just disconnects in both cases.
  2593.  *
  2594.  * Kermit lets the user use the quit key to perform some special commands
  2595.  * during file transfer.  This causes read(), and thus also mygetbuf(), to
  2596.  * finish without reading anything and return the EINTR error.  This should
  2597.  * be checked by the caller.  Mygetbuf() could retry the read() on EINTR,
  2598.  * but if there is nothing to read, this could delay Kermit's reaction to
  2599.  * the command, and make Kermit appear unresponsive.
  2600.  *
  2601.  * The debug() call should be removed for optimum performance.
  2602.  */
  2603. int
  2604. mygetbuf() {
  2605.     int x;
  2606.     errno = 0;
  2607. #ifdef DEBUG
  2608.     if (deblog && my_count > 0)
  2609.       debug(F101,"mygetbuf IMPROPERLY CALLED with my_count","",my_count);
  2610. #endif /* DEBUG */
  2611.     if (my_count <= 0)
  2612.       my_count = myfillbuf();
  2613. #ifdef DEBUG
  2614.     if (deblog) debug(F101, "mygetbuf read", "", my_count);
  2615. #endif /* DEBUG */
  2616.     x = my_count;
  2617.     if (my_count <= 0) {
  2618. my_count = 0;
  2619. my_item = -1;
  2620. debug(F101,"mygetbuf errno","",errno);
  2621. #ifdef TCPSOCKET
  2622. if (netconn && ttnet == NET_TCPB && errno != 0) {
  2623.     if (errno != EINTR) {
  2624. debug(F101,"mygetbuf TCP error","",errno);
  2625. ttclos(0); /* Close the connection. */
  2626.     }
  2627.     return(-3);
  2628. }
  2629. #endif /* TCPSOCKET */
  2630. if (!netconn && xlocal && errno) {
  2631.     if (errno != EINTR) {
  2632. debug(F101,"mygetbuf SERIAL error","",errno);
  2633. x = -3;
  2634. ttclos(0); /* Close the connection. */
  2635.     }
  2636. }
  2637. return((x < 0) ? -3 : -2);
  2638.     }
  2639.     --my_count;
  2640.     return((unsigned)(0xff & mybuf[my_item = 0]));
  2641. }
  2642. /* myfillbuf():
  2643.  * System-dependent read() into mybuf[], as many characters as possible.
  2644.  *
  2645.  * Returns: OK => number of characters read, always more than zero.
  2646.  *          EOF => 0
  2647.  *          Error => -1, error code in errno.
  2648.  *
  2649.  * If there is input available in the system's buffers, all of it should be
  2650.  * read into mybuf[] and the function return immediately.  If no input is
  2651.  * available, it should wait for a character to arrive, and return with that
  2652.  * one in mybuf[] as soon as possible.  It may wait somewhat past the first
  2653.  * character, but be aware that any such delay lengthens the packet turnaround
  2654.  * time during kermit file transfers.  Should never return with zero characters
  2655.  * unless EOF or irrecoverable read error.
  2656.  *
  2657.  * Correct functioning depends on the correct tty parameters being used.
  2658.  * Better control of current parameters is required than may have been the
  2659.  * case in older Kermit releases.  For instance, O_NDELAY (or equivalent) can
  2660.  * no longer be sometimes off and sometimes on like it used to, unless a
  2661.  * special myfillbuf() is written to handle that.  Otherwise the ordinary
  2662.  * myfillbuf()s may think they have come to EOF.
  2663.  *
  2664.  * If your system has a facility to directly perform the functioning of
  2665.  * myfillbuf(), then use it.  If the system can tell you how many characters
  2666.  * are available in its buffers, then read that amount (but not less than 1).
  2667.  * If the system can return a special indication when you try to read without
  2668.  * anything to read, while allowing you to read all there is when there is
  2669.  * something, you may loop until there is something to read, but probably that
  2670.  * is not good for the system load.
  2671.  */
  2672. #ifdef SVORPOSIX
  2673. /* This is for System III/V with VMIN>0, VTIME=0 and O_NDELAY off,
  2674.  * and CLOCAL set any way you like.  This way, read() will do exactly
  2675.  * what is required by myfillbuf(): If there is data in the buffers
  2676.  * of the O.S., all available data is read into mybuf, up to the size
  2677.  * of mybuf.  If there is none, the first character to arrive is
  2678.  * awaited and returned.
  2679.  */
  2680. int
  2681. myfillbuf() {
  2682.     int fd, n;
  2683. #ifdef NETCMD
  2684.     if (ttpipe)
  2685.       fd = fdin;
  2686.     else
  2687. #endif /* NETCMD */
  2688.       fd = ttyfd;
  2689. #ifdef sxaE50
  2690.     /* From S. Dezawa at Fujifilm in Japan.  I don't know why this is */
  2691.     /* necessary for the sxa E50, but it is. */
  2692.     return read(fd, mybuf, 255);
  2693. #else
  2694. #ifdef BEOSORBEBOX
  2695.     while (1) {
  2696. #ifdef NETCONN
  2697.         if (netconn) {
  2698.             n = netxin(sizeof(mybuf), (char *)mybuf);
  2699.             debug(F101,"BEBOX SVORPOSIX network myfillbuf","",n);
  2700. }
  2701.         else
  2702. #endif /* NETCONN */
  2703.   n = read(fd, mybuf, sizeof(mybuf));
  2704. debug(F101,"BEBOX SVORPOSIX notnet myfillbuf","",n);
  2705.         if (n > 0)
  2706.   return(n);
  2707.         snooze(1000.0);
  2708.     }
  2709. #else /* BEOSORBEBOX */
  2710.     errno = 0;
  2711.     debug(F100,"SVORPOSIX myfillbuf calling read()","",0);
  2712. #ifdef IBMX25
  2713.     if (netconn && (nettype == NET_IX25)) {
  2714. /* can't use sizeof because mybuf is a pointer, and not an array! */
  2715. n = x25xin( MYBUFLEN, mybuf );
  2716.     } else
  2717. #endif /* IBMX25 */
  2718. #ifdef CK_SSL
  2719.       if (ssl_active_flag || tls_active_flag) {
  2720.   int error, n = 0;
  2721.   while (n == 0) {
  2722.       if (ssl_active_flag)
  2723.                 n = SSL_read(ssl_con, (char *)mybuf, sizeof(mybuf));
  2724.       else if (tls_active_flag)
  2725.                 n = SSL_read(tls_con, (char *)mybuf, sizeof(mybuf));
  2726.               else
  2727. break;
  2728.       switch (SSL_get_error(ssl_active_flag?ssl_con:tls_con,n)) {
  2729. case SSL_ERROR_NONE:
  2730.   if (n > 0)
  2731.                     return(n);
  2732.   if (n < 0)
  2733.                     return(-2);
  2734.   msleep(50);
  2735.   break;
  2736. case SSL_ERROR_WANT_WRITE:
  2737. case SSL_ERROR_WANT_READ:
  2738.   return(-1);
  2739. case SSL_ERROR_SYSCALL:
  2740. case SSL_ERROR_WANT_X509_LOOKUP:
  2741. case SSL_ERROR_SSL:
  2742. case SSL_ERROR_ZERO_RETURN:
  2743. default:
  2744.   ttclos(0);
  2745.   return(-3);
  2746.             }
  2747.         }
  2748.     }
  2749. #endif /* CK_SSL */
  2750. #ifdef RLOGCODE
  2751. #ifdef CK_KERBEROS
  2752. #ifdef KRB4
  2753.     if (ttnproto == NP_EK4LOGIN) {
  2754.         if ((n = krb4_des_read(ttyfd,mybuf,sizeof(mybuf))) < 0)
  2755.   return(-3);
  2756.         else
  2757.   return(n);
  2758.     }
  2759. #endif /* KRB4 */
  2760. #ifdef KRB5
  2761.     if (ttnproto == NP_EK5LOGIN) {
  2762.         if ((n = krb5_des_read(ttyfd,mybuf,sizeof(mybuf))) < 0)
  2763.   return(-3);
  2764.         else
  2765.   return(n);
  2766.     }
  2767. #endif /* KRB5 */
  2768. #endif /* CK_KERBEROS */
  2769. #endif /* RLOGCODE */
  2770. #ifdef NETPTY
  2771. #ifdef HAVE_PTYTRAP
  2772.     /* Special handling for HP-UX pty i/o */
  2773.   ptyread:
  2774.     if (ttpty && pty_trap_pending(ttyfd) > 0) {
  2775.         if (pty_trap_handler(ttyfd) > 0) {
  2776.             ttclos(0);
  2777.             return(-3);
  2778.         }
  2779.     }
  2780. #endif /* HAVE_PTYTRAP */
  2781. #endif /* NETPTY */
  2782.     n = read(fd, mybuf, sizeof(mybuf));
  2783.     debug(F101,"SVORPOSIX myfillbuf","",n);
  2784.     debug(F101,"SVORPOSIX myfillbuf ttcarr","",ttcarr);
  2785.     debug(F101,"SVORPOSIX myfillbuf errno","",errno);
  2786.     if (n < 1) {
  2787. #ifdef NETPTY
  2788. #ifdef HAVE_PTYTRAP
  2789.         /* When we have a PTY trap in place the connection cannot */
  2790.         /* be closed until the trap receives a close indication.  */
  2791.         if (n == 0 && ttpty)
  2792.             goto ptyread;
  2793. #endif /* HAVE_PTYTRAP */
  2794. #endif /* NETPTY */
  2795.         return(-3);
  2796.     }
  2797.     return(n);
  2798. #endif /* BEOSORBEBOX */
  2799. #endif /* sxaE50 */
  2800. }
  2801. #else /* not AT&T or POSIX */
  2802. #ifdef aegis
  2803. /* This is quoted from the old myread().  The semantics seem to be
  2804.  * alright, but maybe errno would not need to be set even when
  2805.  * there is no error?  I don't know aegis.
  2806.  */
  2807. int
  2808. myfillbuf() {
  2809.     int count;
  2810. #ifdef NETCMD
  2811.     if (ttpipe)
  2812.       fd = fdin;
  2813.     else
  2814. #endif /* NETCMD */
  2815.       fd = ttyfd;
  2816.     count = ios_$get((short)fd, ios_$cond_opt, mybuf, 256L, st);
  2817.     errno = EIO;
  2818.     if (st.all == ios_$get_conditional_failed) /* get at least one */
  2819.       count = ios_$get((short)fd, 0, mybuf, 1L, st);
  2820.     if (st.all == ios_$end_of_file)
  2821.       return(-3);
  2822.     else if (st.all != status_$ok) {
  2823. errno = EIO;
  2824. return(-1);
  2825.     }
  2826.     return(count > 0 ? count : -3);
  2827. }
  2828. #else /* !aegis */
  2829. #ifdef FIONREAD
  2830. /* This is for systems with FIONREAD.  FIONREAD returns the number
  2831.  * of characters available for reading. If none are available, wait
  2832.  * until something arrives, otherwise return all there is.
  2833.  */
  2834. int
  2835. myfillbuf() {
  2836.     PEEKTYPE avail = 0;
  2837.     int x, fd;
  2838. #ifdef NETCMD
  2839.     if (ttpipe)
  2840.       fd = fdin;
  2841.     else
  2842. #endif /* NETCMD */
  2843.       fd = ttyfd;
  2844. #ifdef SUNX25
  2845. /*
  2846.   SunLink X.25 support in this routine from Stefaan A. Eeckels, Eurostat (CEC).
  2847.   Depends on SunOS having FIONREAD, not because we use it, but just so this
  2848.   code is grouped correctly within the #ifdefs.  Let's hope Solaris keeps it.
  2849.   We call x25xin() instead of read() so that Q-Bit packets, which contain
  2850.   X.25 service-level information (e.g. PAD parameter changes), can be processed
  2851.   transparently to the upper-level code.  This is a blocking read, and so
  2852.   we depend on higher-level code (such as ttinc()) to set any necessary alarms.
  2853. */
  2854.     extern int nettype;
  2855.     if (netconn && nettype == NET_SX25) {
  2856. while ((x = x25xin(sizeof(x25buf), x25buf)) < 1) ;
  2857. return(x - 1);         /* "-1" compensates for extra status byte */
  2858.     }
  2859. #endif /* SUNX25 */
  2860. #ifdef CK_SSL
  2861.     if (ssl_active_flag || tls_active_flag) {
  2862.         int error, n = 0;
  2863.         while (n == 0) {
  2864.             if (ssl_active_flag)
  2865.       n = SSL_read(ssl_con, (char *)mybuf, sizeof(mybuf));
  2866.             else
  2867.       n = SSL_read(tls_con, (char *)mybuf, sizeof(mybuf));
  2868.             switch (SSL_get_error(ssl_active_flag?ssl_con:tls_con,n)) {
  2869.       case SSL_ERROR_NONE:
  2870.                 if (n > 0)
  2871.   return(n);
  2872.                 if (n < 0)
  2873.   return(-2);
  2874.                 msleep(50);
  2875.                 break;
  2876.       case SSL_ERROR_WANT_WRITE:
  2877.       case SSL_ERROR_WANT_READ:
  2878.                 return(-1);
  2879.       case SSL_ERROR_SYSCALL:
  2880.       case SSL_ERROR_WANT_X509_LOOKUP:
  2881.       case SSL_ERROR_SSL:
  2882.       case SSL_ERROR_ZERO_RETURN:
  2883.       default:
  2884.                 ttclos(0);
  2885.                 return(-2);
  2886.             }
  2887.         }
  2888.     }
  2889. #endif /* CK_SSL */
  2890. #ifdef RLOGCODE
  2891. #ifdef CK_KERBEROS
  2892. #ifdef KRB4
  2893.     if (ttnproto == NP_EK4LOGIN) {
  2894.         if ((x = krb4_des_read(ttyfd,mybuf,sizeof(mybuf))) < 0)
  2895.   return(-1);
  2896.         else
  2897.   return(x);
  2898.     }
  2899. #endif /* KRB4 */
  2900. #ifdef KRB5
  2901.     if (ttnproto == NP_EK5LOGIN) {
  2902.         if ((x = krb5_des_read(ttyfd,mybuf,sizeof(mybuf))) < 0)
  2903.   return(-1);
  2904.         else
  2905.   return(x);
  2906.     }
  2907. #endif /* KRB5 */
  2908. #endif /* CK_KERBEROS */
  2909. #endif /* RLOGCODE */
  2910.     errno = 0;
  2911.     debug(F101,"myfillbuf calling FIONREAD ioctl","",xlocal);
  2912.     x = ioctl(fd, FIONREAD, &avail);
  2913. #ifdef DEBUG
  2914.     if (deblog) {
  2915. debug(F101,"myfillbuf FIONREAD","",x);
  2916. debug(F101,"myfillbuf FIONREAD avail","",avail);
  2917. debug(F101,"myfillbuf FIONREAD errno","",errno);
  2918.     }
  2919. #endif /* DEBUG */
  2920.     if (x < 0 || avail == 0)
  2921.       avail = 1;
  2922.     if (avail > MYBUFLEN)
  2923.       avail = MYBUFLEN;
  2924.     errno = 0;
  2925.     x = read(fd, mybuf, (int) avail);
  2926. #ifdef DEBUG
  2927.     if (deblog) {
  2928. debug(F101,"myfillbuf avail","",avail);
  2929. debug(F101,"myfillbuf read","",x);
  2930. debug(F101,"myfillbuf read errno","",errno);
  2931.         if (x > 0)
  2932.   hexdump("myfillbuf mybuf",mybuf,x);
  2933.     }
  2934. #endif /* DEBUG */
  2935.     if (x < 1) x = -3; /* read 0 == connection loss */
  2936.     return(x);
  2937. }
  2938. #else /* !FIONREAD */
  2939. /* Add other systems here, between #ifdef and #else, e.g. NETCONN. */
  2940. /* When there is no other possibility, read 1 character at a time. */
  2941. int
  2942. myfillbuf() {
  2943.     int x;
  2944. #ifdef CK_SSL
  2945.     if (ssl_active_flag || tls_active_flag) {
  2946.         int error, n = 0;
  2947.         while (n == 0) {
  2948.             if (ssl_active_flag)
  2949.       n = SSL_read(ssl_con, (char *)mybuf, sizeof(mybuf));
  2950.             else
  2951.       count = SSL_read(tls_con, (char *)mybuf, sizeof(mybuf));
  2952.             switch (SSL_get_error(ssl_active_flag?ssl_con:tls_con,n)) {
  2953.       case SSL_ERROR_NONE:
  2954.                 if (n > 0)
  2955.   return(n);
  2956.                 if (n < 0)
  2957.   return(-2);
  2958.                 msleep(50);
  2959.                 break;
  2960.       case SSL_ERROR_WANT_WRITE:
  2961.       case SSL_ERROR_WANT_READ:
  2962.                 return(-1);
  2963.       case SSL_ERROR_SYSCALL:
  2964.       case SSL_ERROR_WANT_X509_LOOKUP:
  2965.       case SSL_ERROR_SSL:
  2966.       case SSL_ERROR_ZERO_RETURN:
  2967.       default:
  2968.                 ttclos(0);
  2969.                 return(-2);
  2970.             }
  2971.         }
  2972.     }
  2973. #endif /* CK_SSL */
  2974. #ifdef RLOGCODE
  2975. #ifdef CK_KERBEROS
  2976. #ifdef KRB4
  2977.     if (ttnproto == NP_EK4LOGIN) {
  2978.         if ((len = krb4_des_read(ttyfd,mybuf,sizeof(mybuf))) < 0)
  2979.   return(-1);
  2980.         else
  2981.   return(len);
  2982.     }
  2983. #endif /* KRB4 */
  2984. #ifdef KRB5
  2985.     if (ttnproto == NP_EK5LOGIN) {
  2986.         if ((len = krb5_des_read(ttyfd,mybuf,sizeof(mybuf))) < 0)
  2987.   return(-1);
  2988.         else
  2989.   return(len);
  2990.     }
  2991. #endif /* KRB5 */
  2992. #endif /* CK_KERBEROS */
  2993. #endif /* RLOGCODE */
  2994. #ifdef NETCMD
  2995.     if (ttpipe)
  2996.       fd = fdin;
  2997.     else
  2998. #endif /* NETCMD */
  2999.       fd = ttyfd;
  3000.     x = read(fd, mybuf, 1);
  3001.     return(x > 0 ? x : -3);
  3002. }
  3003. #endif /* !FIONREAD */
  3004. #endif /* !aegis */
  3005. #endif /* !ATTSV */
  3006. #endif /* MYREAD */
  3007. #ifdef MINIX2
  3008. #undef MINIX
  3009. #endif /* MINIX2 */
  3010. /*  T T _ T N O P T  --  Handle Telnet negotions in incoming data */
  3011. /*
  3012.   Call with the IAC that was encountered.
  3013.   Returns:
  3014.    -3: If connection has dropped or gone bad.
  3015.    -2: On Telnet protocol error resulting in inconsistent states.
  3016.     0: If negotiation OK and caller has nothing to do.
  3017.     1: If packet start character has changed (new value is in global stchr).
  3018.   255: If there was a quoted IAC as data.
  3019.    or: Not at all if we got a legitimate Telnet Logout request.
  3020. */
  3021. #ifdef TCPSOCKET
  3022. static int
  3023. tt_tnopt(n) int n; { /* Handle Telnet options */
  3024.     /* In case caller did not already check these conditions...  */
  3025.     if (n == IAC &&
  3026. ((xlocal && netconn && (ttnproto == NP_TELNET)) ||
  3027.  (!xlocal && sstelnet))) {
  3028. extern int duplex;
  3029. extern int server;
  3030. int tx = 0;
  3031. debug(F100,"ttinl calling tn_doop()","",0);
  3032. tx = tn_doop((CHAR)(n & 0xff),duplex,ttinc);
  3033. debug(F111,"ttinl tn_doop() returned","tx",tx);
  3034. switch (tx) {
  3035.   case 0:
  3036.     return(0);
  3037.   case -1: /* I/O error */
  3038.     ttimoff(); /* Turn off timer */
  3039.     return(-3);
  3040.           case -2: /* Connection failed. */
  3041.           case -3:
  3042.     ttimoff(); /* Turn off timer */
  3043.     ttclos(0);
  3044.     return(-3);
  3045.   case 1: /* ECHO change */
  3046.     duplex = 1;
  3047.     return(0);
  3048.   case 2: /* ECHO change */
  3049.     duplex = 0;
  3050.     return(0);
  3051.   case 3: /* Quoted IAC */
  3052.     n = 255;
  3053.     return((unsigned)255);
  3054. #ifdef IKS_OPTION
  3055.   case 4: {
  3056.       if (TELOPT_SB(TELOPT_KERMIT).kermit.u_start && server
  3057. #ifdef IKSD
  3058.   && !inserver
  3059. #endif /* IKSD */
  3060.   ) { /* Remote in Server mode */
  3061.   ttimoff(); /* Turn off timer */
  3062.   debug(F100,"u_start and !inserver","",0);
  3063.   return(-2); /* End server mode */
  3064.       } else if (!TELOPT_SB(TELOPT_KERMIT).kermit.me_start &&
  3065.  server
  3066.  ) { /* I'm no longer in Server Mode */
  3067.   debug(F100,"me_start and server","",0);
  3068.   ttimoff();
  3069.   return(-2);
  3070.       }
  3071.       return(0);
  3072.   }
  3073.   case 5: { /* Start character change */
  3074.       /* extern CHAR stchr; */
  3075.       /* start = stchr; */
  3076.       return(1);
  3077.   }
  3078. #endif /* IKS_OPTION */
  3079.   case 6: /* Remote Logout */
  3080.     ttimoff();
  3081.     ttclos(0);
  3082. #ifdef IKSD
  3083.     if (inserver && !local)
  3084.       doexit(GOOD_EXIT,0);
  3085.     else
  3086. #endif /* IKSD */
  3087.       return(-2);
  3088.   default:
  3089.     return(0);
  3090. }
  3091.     } else
  3092.       return(0);
  3093. }
  3094. #endif /* TCPSOCKET */
  3095. /*  T T F L U I  --  Flush tty input buffer */
  3096. void
  3097. ttflux() { /* But first... */
  3098. #ifdef MYREAD
  3099. /*
  3100.   Flush internal MYREAD buffer.
  3101. */
  3102. #ifdef TCPSOCKET
  3103.     int dotnopts, x;
  3104.     dotnopts = (((xlocal && netconn && (ttnproto == NP_TELNET)) ||
  3105.  (!xlocal && sstelnet)));
  3106. #endif /* TCPSOCKET */
  3107.     debug(F101,"ttflux my_count","",my_count);
  3108. #ifdef TCPSOCKET
  3109.     if (dotnopts) {
  3110. CHAR ch = '';
  3111.         while (my_count > 0) {
  3112.     ch = myread();
  3113. #ifdef CK_ENCRYPTION
  3114.             if (TELOPT_U(TELOPT_ENCRYPTION))
  3115.       ck_tn_decrypt(&ch,1);
  3116. #endif /* CK_ENCRYPTION */
  3117.             if (ch == IAC)
  3118.       x = tt_tnopt(ch);
  3119.         }
  3120.     } else
  3121. #endif /* TCPSOCKET */
  3122. #ifdef COMMENT
  3123. #ifdef CK_ENCRYPTION
  3124.     if (TELOPT_U(TELOPT_ENCRYPTION) && my_count > 0)
  3125.       ck_tn_decrypt(&mybuf[my_item+1],my_count);
  3126. #endif /* CK_ENCRYPTION */
  3127. #endif /* COMMENT */
  3128.     my_count = 0; /* Reset count to zero */
  3129.     my_item = -1; /* And buffer index to -1 */
  3130. #endif /* MYREAD */
  3131. }
  3132. int
  3133. ttflui() {
  3134.     int n, fd;
  3135. #ifdef TCPSOCKET
  3136.     int dotnopts;
  3137.     dotnopts = (((xlocal && netconn && (ttnproto == NP_TELNET)) ||
  3138.  (!xlocal && sstelnet)));
  3139. #endif /* TCPSOCKET */
  3140. #ifdef NETCMD
  3141.     if (ttpipe)
  3142.       fd = fdin;
  3143.     else
  3144. #endif /* NETCMD */
  3145.       fd = ttyfd;
  3146. #ifdef TTLEBUF
  3147.     ttpush = -1; /* Clear the peek-ahead char */
  3148.     while (le_data && (le_inbuf() > 0)) {
  3149.         CHAR ch = '';
  3150.         if (le_getchar(&ch) > 0) { /* Clear any more... */
  3151.             debug(F101,"ttflui le_inbuf ch","",ch);
  3152.         }
  3153.     }
  3154. #endif /* TTLEBUF */
  3155.     debug(F101,"ttflui ttpipe","",ttpipe);
  3156. #ifdef MYREAD
  3157. /*
  3158.   Flush internal MYREAD buffer *NEXT*, in all cases.
  3159. */
  3160.     ttflux();
  3161. #endif /* MYREAD */
  3162. #ifdef NETCONN
  3163. /* Network flush is done specially, in the network support module. */
  3164.     if ((netconn || sstelnet) && !ttpipe && !ttpty) {
  3165. debug(F100,"ttflui netflui","",0);
  3166. return(netflui());
  3167.     }
  3168. #endif /* NETCONN */
  3169.     debug(F101,"ttflui ttyfd","",ttyfd); /* Not network */
  3170.     if (ttyfd < 0)
  3171.       return(-1);
  3172. #ifdef aegis
  3173.     sio_$control((short)yfd, sio_$flush_in, true, st);
  3174.     if (st.all != status_$ok) {
  3175. fprintf(stderr, "flush failed: "); error_$print(st);
  3176.     } else {      /* sometimes the flush doesn't work */
  3177.         for (;;) {
  3178.     char buf[256];
  3179.             /* eat all the characters that shouldn't be available */
  3180.             ios_$get((short)fd, ios_$cond_opt, buf, 256L, st); /* (void) */
  3181.             if (st.all == ios_$get_conditional_failed) break;
  3182.             fprintf(stderr, "flush failed(2): "); error_$print(st);
  3183.         }
  3184.     }
  3185. #else
  3186. #ifdef BSD44 /* 4.4 BSD */
  3187.     n = FREAD;                          /* Specify read queue */
  3188.     debug(F100,"ttflui BSD44","",0);
  3189.     ioctl(fd,TIOCFLUSH,&n);
  3190. #else
  3191. #ifdef Plan9
  3192. #undef POSIX /* Uh oh... */
  3193. #endif /* Plan9 */
  3194. #ifdef POSIX /* POSIX */
  3195.     debug(F100,"ttflui POSIX","",0);
  3196.     tcflush(fd,TCIFLUSH);
  3197. #else
  3198. #ifdef ATTSV /* System V */
  3199. #ifndef VXVE
  3200.     debug(F100,"ttflui ATTSV","",0);
  3201.     ioctl(fd,TCFLSH,0);
  3202. #endif /* VXVE */
  3203. #else /* Not BSD44, POSIX, or Sys V */
  3204. #ifdef TIOCFLUSH /* Those with TIOCFLUSH defined */
  3205. #ifdef ANYBSD /* Berkeley */
  3206.     n = FREAD;                          /* Specify read queue */
  3207.     debug(F100,"ttflui TIOCFLUSH ANYBSD","",0);
  3208.     ioctl(fd,TIOCFLUSH,&n);
  3209. #else /* Others (V7, etc) */
  3210.     debug(F100,"ttflui TIOCFLUSH","",0);
  3211.     ioctl(fd,TIOCFLUSH,0);
  3212. #endif /* ANYBSD */
  3213. #else /* All others... */
  3214. /*
  3215.   No system call (that we know about) for input buffer flushing.
  3216.   So see how many there are and read them in a loop, using ttinc().
  3217.   ttinc() is buffered, so we're not getting charged with a system call
  3218.   per character, just a function call.
  3219. */
  3220.     if ((n = ttchk()) > 0) {
  3221. debug(F101,"ttflui read loop","",n);
  3222. while ((n--) && ttinc(0) > 0) ;
  3223.     }
  3224. #endif /* TIOCFLUSH */
  3225. #endif /* ATTSV */
  3226. #endif /* POSIX */
  3227. #ifdef Plan9
  3228. #define POSIX
  3229. #endif /* Plan9 */
  3230. #endif /* BSD44 */
  3231. #endif /* aegis */
  3232.     return(0);
  3233. }
  3234. int
  3235. ttfluo() { /* Flush output buffer */
  3236.     int fd;
  3237. #ifdef NETCMD
  3238.     if (ttpipe)
  3239.       fd = fdout;
  3240.     else
  3241. #endif /* NETCMD */
  3242.       fd = ttyfd;
  3243. #ifdef Plan9
  3244.     return 0;
  3245. #else
  3246. #ifdef POSIX
  3247.     return(tcflush(fd,TCOFLUSH));
  3248. #else
  3249. #ifdef OXOS
  3250.     return(ioctl(fd,TCFLSH,1));
  3251. #else
  3252.     return(0); /* All others, nothing */
  3253. #endif /* OXOS */
  3254. #endif /* POSIX */
  3255. #endif /* Plan9 */
  3256. }
  3257. /* Interrupt Functions */
  3258. /* Set up terminal interrupts on console terminal */
  3259. #ifndef FIONREAD /* We don't need esctrp() */
  3260. #ifndef SELECT /* if we have any of these... */
  3261. #ifndef CK_POLL
  3262. #ifndef RDCHK
  3263. #ifndef OXOS
  3264. #ifdef SVORPOSIX
  3265. SIGTYP
  3266. esctrp(foo) int foo; { /* trap console escapes (^) */
  3267.     signal(SIGQUIT,SIG_IGN);            /* ignore until trapped */
  3268.     conesc = 1;
  3269.     debug(F101,"esctrp caught SIGQUIT","",conesc);
  3270. }
  3271. #endif /* SVORPOSIX */
  3272. #endif /* OXOS */
  3273. #ifdef V7
  3274. #ifndef MINIX2
  3275. SIGTYP
  3276. esctrp(foo) int foo; { /* trap console escapes (^) */
  3277.     signal(SIGQUIT,SIG_IGN);            /* ignore until trapped */
  3278.     conesc = 1;
  3279.     debug(F101,"esctrp caught SIGQUIT","",conesc);
  3280. }
  3281. #endif /* MINIX2 */
  3282. #endif /* V7 */
  3283. #ifdef C70
  3284. SIGTYP
  3285. esctrp(foo) int foo; { /* trap console escapes (^) */
  3286.     conesc = 1;
  3287.     signal(SIGQUIT,SIG_IGN);            /* ignore until trapped */
  3288. }
  3289. #endif /* C70 */
  3290. #endif /* RDCHK */
  3291. #endif /* CK_POLL */
  3292. #endif /* SELECT */
  3293. #endif /* FIONREAD */
  3294. /*  C O N B G T  --  Background Test  */
  3295. static int jc = 0; /* 0 = no job control */
  3296. /*
  3297.   Call with flag == 1 to prevent signal test, which can not be expected
  3298.   to work during file transfer, when SIGINT probably *is* set to SIG_IGN.
  3299.   Call with flag == 0 to use the signal test, but only if the process-group
  3300.   test fails, as it does on some UNIX systems, where getpgrp() is buggy,
  3301.   requires an argument when the man page says it doesn't, or vice versa.
  3302.   If flag == 0 and the process-group test fails, then we determine background
  3303.   status simply (but not necessarily reliably) from isatty().
  3304.   conbgt() sets the global backgrd = 1 if we appear to be in the background,
  3305.   and to 0 if we seem to be in the foreground.  conbgt() is highly prone to
  3306.   misbehavior.
  3307. */
  3308. VOID
  3309. conbgt(flag) int flag; {
  3310.     int x = -1, /* process group or SIGINT test */
  3311.         y = 0; /* isatty() test */
  3312. /*
  3313.   Check for background operation, even if not running on real tty, so that
  3314.   background flag can be set correctly.  If background status is detected,
  3315.   then Kermit will not issue its interactive prompt or most messages.
  3316.   If your prompt goes away, you can blame (and fix?) this function.
  3317. */
  3318. /* Use process-group test if possible. */
  3319. #ifdef POSIX /* We can do it in POSIX */
  3320. #define PGROUP_T
  3321. #else
  3322. #ifdef BSD4 /* and in BSD 4.x. */
  3323. #define PGROUP_T
  3324. #else
  3325. #ifdef HPUXJOBCTL /* and in most HP-UX's */
  3326. #define PGROUP_T
  3327. #else
  3328. #ifdef TIOCGPGRP /* and anyplace that has this ioctl. */
  3329. #define PGROUP_T
  3330. #endif /* TIOCGPGRP */
  3331. #endif /* HPUXJOBCTL */
  3332. #endif /* BSD4 */
  3333. #endif /* POSIX */
  3334. #ifdef MIPS /* Except if it doesn't work... */
  3335. #undef PGROUP_T
  3336. #endif /* MIPS */
  3337. #ifdef PGROUP_T
  3338. /*
  3339.   Semi-reliable process-group test.  Check whether this process's group is
  3340.   the same as the controlling terminal's process group.  This works if the
  3341.   getpgrp() call doesn't lie (as it does in the SUNOS System V environment).
  3342. */
  3343.     PID_T mypgrp = (PID_T)0; /* Kermit's process group */
  3344.     PID_T ctpgrp = (PID_T)0; /* The terminal's process group */
  3345. #ifndef _POSIX_SOURCE
  3346. /*
  3347.   The getpgrp() prototype is obtained from system header files for POSIX
  3348.   and Sys V R4 compilations.  Other systems, who knows.  Some complain about
  3349.   a duplicate declaration here, others don't, so it's safer to leave it in
  3350.   if we don't know for certain.
  3351. */
  3352. #ifndef SVR4
  3353. #ifndef PS2AIX10
  3354. #ifndef HPUX9
  3355.     extern PID_T getpgrp();
  3356. #endif /* HPUX9 */
  3357. #endif /* PS2AIX10 */
  3358. #endif /* SVR4 */
  3359. #endif /* _POSIX_SOURCE */
  3360. /* Get my process group. */
  3361. #ifdef SVR3 /* Maybe this should be ATTSV? */
  3362. /* This function is not described in SVID R2 */
  3363.     mypgrp = getpgrp();
  3364.     /* debug(F101,"ATTSV conbgt process group","",(int) mypgrp); */
  3365. #else
  3366. #ifdef POSIX
  3367.     mypgrp = getpgrp();
  3368.     /* debug(F101,"POSIX conbgt process group","",(int) mypgrp); */
  3369. #else
  3370. #ifdef OSFPC
  3371.     mypgrp = getpgrp();
  3372.     /* debug(F101,"OSF conbgt process group","",(int) mypgrp); */
  3373. #else
  3374. #ifdef QNX
  3375.     mypgrp = getpgrp();
  3376.     /* debug(F101,"QNX conbgt process group","",(int) mypgrp); */
  3377. #else
  3378. #ifdef OSF32 /* (was OSF40) */
  3379.     mypgrp = getpgrp();
  3380.     /* debug(F101,"Digital UNIX conbgt process group","",(int) mypgrp); */
  3381. #else /* BSD, V7, etc */
  3382. #ifdef MINIX2
  3383.     mypgrp = getpgrp();
  3384. #else
  3385.     mypgrp = getpgrp(0);
  3386. #endif /* MINIX2 */
  3387.     /* debug(F101,"BSD conbgt process group","",(int) mypgrp); */
  3388. #endif /* OSF32 */
  3389. #endif /* QNX */
  3390. #endif /* OSFPC */
  3391. #endif /* POSIX */
  3392. #endif /* SVR3 */
  3393. #ifdef MINIX2
  3394. #undef BSD44ORPOSIX
  3395. #endif /* MINIX2 */
  3396. /* Now get controlling tty's process group */
  3397. #ifdef BSD44ORPOSIX
  3398.     ctpgrp = tcgetpgrp(1); /* The POSIX way */
  3399.     /* debug(F101,"POSIX conbgt terminal process group","",(int) ctpgrp); */
  3400. #else
  3401.     ioctl(1, TIOCGPGRP, &ctpgrp); /* Or the BSD way */
  3402.    /* debug(F101,"non-POSIX conbgt terminal process group","",(int) ctpgrp); */
  3403. #endif /* BSD44ORPOSIX */
  3404. #ifdef MINIX2
  3405. #define BSD44ORPOSIX
  3406. #endif /* MINIX2 */
  3407.     if ((mypgrp > (PID_T) 0) && (ctpgrp > (PID_T) 0))
  3408.       x = (mypgrp == ctpgrp) ? 0 : 1; /* If they differ, then background. */
  3409.     else x = -1; /* If error, remember. */
  3410.     debug(F101,"conbgt process group test","",x);
  3411. #endif /* PGROUP_T */
  3412. /* Try to see if job control is available */
  3413. #ifdef NOJC /* User override */
  3414.     jc = 0; /* No job control allowed */
  3415.     debug(F111,"NOJC","jc",jc);
  3416. #else
  3417. #ifdef BSD44
  3418.     jc = 1;
  3419. #else
  3420. #ifdef SVR4ORPOSIX /* POSIX actually tells us */
  3421.     debug(F100,"SVR4ORPOSIX jc test...","",0);
  3422. #ifdef _SC_JOB_CONTROL
  3423. #ifdef __bsdi__
  3424.     jc = 1;
  3425. #else
  3426. #ifdef __386BSD__
  3427.     jc = 1;
  3428. #else
  3429.     jc = sysconf(_SC_JOB_CONTROL); /* Whatever system says */
  3430.     if (jc < 0) {
  3431. debug(F101,"sysconf fails, jcshell","",jcshell);
  3432. jc = (jchdlr == SIG_DFL) ? 1 : 0;
  3433.     } else
  3434.       debug(F111,"sysconf(_SC_JOB_CONTROL)","jc",jc);
  3435. #endif /* __386BSD__ */
  3436. #endif /* __bsdi__ */
  3437. #else
  3438. #ifdef _POSIX_JOB_CONTROL
  3439.     jc = 1; /* By definition */
  3440.     debug(F111,"_POSIX_JOB_CONTROL is defined","jc",jc);
  3441. #else
  3442.     jc = 0; /* Assume job control not allowed */
  3443.     debug(F111,"SVR4ORPOSIX _SC/POSIX_JOB_CONTROL not defined","jc",jc);
  3444. #endif /* _POSIX_JOB_CONTROL */
  3445. #endif /* _SC_JOB_CONTROL */
  3446. #else
  3447. #ifdef BSD4
  3448.     jc = 1; /* Job control allowed */
  3449.     debug(F111,"BSD job control","jc",jc);
  3450. #else
  3451. #ifdef SVR3JC
  3452.     jc = 1; /* JC allowed */
  3453.     debug(F111,"SVR3 job control","jc",jc);
  3454. #else
  3455. #ifdef OXOS
  3456.     jc = 1; /* JC allowed */
  3457.     debug(F111,"X/OS job control","jc",jc);
  3458. #else
  3459. #ifdef HPUX9
  3460.     jc = 1; /* JC allowed */
  3461.     debug(F111,"HP-UX 9.0 job control","jc",jc);
  3462. #else
  3463. #ifdef HPUX10
  3464.     jc = 1; /* JC allowed */
  3465.     debug(F111,"HP-UX 10.0 job control","jc",jc);
  3466. #else
  3467.     jc = 0; /* JC not allowed */
  3468.     debug(F111,"job control catch-all","jc",jc);
  3469. #endif /* HPUX10 */
  3470. #endif /* HPUX9 */
  3471. #endif /* OXOS */
  3472. #endif /* SVR3JC */
  3473. #endif /* BSD4 */
  3474. #endif /* SVR4ORPOSIX */
  3475. #endif /* BSD44 */
  3476. #endif /* NOJC */
  3477.     debug(F101,"conbgt jc","",jc);
  3478. #ifndef NOJC
  3479.     debug(F101,"conbgt jcshell","",jcshell);
  3480. /*
  3481.   At this point, if jc == 1 but jcshell == 0, it means that the OS supports
  3482.   job control, but the shell or other process we are running under does not
  3483.   (jcshell is set in sysinit()) and so if we suspend ourselves, nothing good
  3484.   will come of it.  So...
  3485. */
  3486.     if (jc < 0) jc = 0;
  3487.     if (jc > 0 && jcshell == 0) jc = 0;
  3488. #endif /* NOJC */
  3489. /*
  3490.   Another background test.
  3491.   Test if SIGINT (terminal interrupt) is set to SIG_IGN (ignore),
  3492.   which is done by the shell (sh) if the program is started with '&'.
  3493.   Unfortunately, this is NOT done by csh or ksh so watch out!
  3494.   Note, it's safe to set SIGINT to SIG_IGN here, because further down
  3495.   we always set it to something else.
  3496.   Note: as of 16 Jul 1999, we also skip this test if we set SIGINT to
  3497.   SIG_IGN ourselves.
  3498. */
  3499.     if (x < 0 && !flag && !sigint_ign) { /* Didn't get good results above... */
  3500. SIGTYP (*osigint)();
  3501. osigint = signal(SIGINT,SIG_IGN); /* What is SIGINT set to? */
  3502. sigint_ign = 1;
  3503. x = (osigint == SIG_IGN) ? 1 : 0; /* SIG_IGN? */
  3504. debug(F101,"conbgt osigint","",osigint);
  3505. debug(F101,"conbgt signal test","",x);
  3506.     }
  3507. /* Also check to see if we're running with redirected stdio. */
  3508. /* This is not really background operation, but we want to act as though */
  3509. /* it were. */
  3510. #ifdef IKSD
  3511.     if (inserver) { /* Internet Kermit Server */
  3512. backgrd = 0; /* is not in the background */
  3513. return;
  3514.     }
  3515. #endif /* IKSD */
  3516.     y = (isatty(0) && isatty(1)) ? 1 : 0;
  3517.     debug(F101,"conbgt isatty test","",y);
  3518. #ifdef BSD29
  3519. /* The process group and/or signal test doesn't work under these... */
  3520.     backgrd = !y;
  3521. #else
  3522. #ifdef sxaE50
  3523.     backgrd = !y;
  3524. #else
  3525. #ifdef MINIX
  3526.     backgrd = !y;
  3527. #else
  3528. #ifdef MINIX2
  3529.     backgrd = !y;
  3530. #else
  3531.     if (x > -1)
  3532.       backgrd = (x || !y) ? 1 : 0;
  3533.     else backgrd = !y;
  3534. #endif /* BSD29 */
  3535. #endif /* sxaE50 */
  3536. #endif /* MINIX */
  3537. #endif /* MINIX2 */
  3538.     debug(F101,"conbgt backgrd","",backgrd);
  3539. }
  3540. /*  C O N I N T  --  Console Interrupt setter  */
  3541. /*
  3542.   First arg is pointer to function to handle SIGTERM & SIGINT (like Ctrl-C).
  3543.   Second arg is pointer to function to handle SIGTSTP (suspend).
  3544. */
  3545. VOID /* Set terminal interrupt traps. */
  3546. #ifdef CK_ANSIC
  3547. #ifdef apollo
  3548. conint(f,s) SIGTYP (*f)(), (*s)();
  3549. #else
  3550. conint(SIGTYP (*f)(int), SIGTYP (*s)(int))
  3551. #endif /* apollo */
  3552. #else
  3553. conint(f,s) SIGTYP (*f)(), (*s)();
  3554. #endif /* CK_ANSIC */
  3555. /* conint */ {
  3556.     conbgt(0); /* Do background test. */
  3557. /* Set the desired handlers for hangup and software termination. */
  3558. #ifdef SIGTERM
  3559.     signal(SIGTERM,f);                  /* Software termination */
  3560. #endif /* SIGTERM */
  3561. /*
  3562.   Prior to July 1999 we used to call sighup() here but now it's called in
  3563.   sysinit() so SIGHUP can be caught during execution of the init file or
  3564.   a kerbang script.
  3565. */
  3566. /* Now handle keyboard stop, quit, and interrupt signals. */
  3567. /* Check if invoked in background -- if so signals set to be ignored. */
  3568. /* However, if running under a job control shell, don't ignore them. */
  3569. /* We won't be getting any, as we aren't in the terminal's process group. */
  3570.     debug(F101,"conint backgrd","",backgrd);
  3571.     debug(F101,"conint jc","",jc);
  3572.     if (backgrd && !jc) { /* In background, ignore signals */
  3573. debug(F101,"conint background ignoring signals, jc","",jc);
  3574. #ifdef SIGTSTP
  3575.         signal(SIGTSTP,SIG_IGN);        /* Keyboard stop */
  3576. #endif /* SIGTSTP */
  3577.         signal(SIGQUIT,SIG_IGN);        /* Keyboard quit */
  3578.         signal(SIGINT,SIG_IGN);         /* Keyboard interrupt */
  3579. sigint_ign = 1;
  3580.     } else { /* Else in foreground or suspended */
  3581. debug(F101,"conint foreground catching signals, jc","",jc);
  3582.         signal(SIGINT,f);               /* Catch terminal interrupt */
  3583. sigint_ign = (f == SIG_IGN) ? 1 : 0;
  3584. #ifdef SIGTSTP /* Keyboard stop (suspend) */
  3585. /* debug(F101,"conint SIGSTSTP","",s); */
  3586. if (s == NULL) s = SIG_DFL;
  3587. #ifdef NOJC /* No job control allowed. */
  3588. signal(SIGTSTP,SIG_IGN);
  3589. #else /* Job control allowed */
  3590. if (jc) /* if available. */
  3591.   signal(SIGTSTP,s);
  3592. else
  3593.   signal(SIGTSTP,SIG_IGN);
  3594. #endif /* NOJC */
  3595. #endif /* SIGTSTP */
  3596. #ifndef OXOS
  3597. #ifdef SVORPOSIX
  3598. #ifndef FIONREAD /* Watch out, we don't know this... */
  3599. #ifndef SELECT
  3600. #ifndef CK_POLL
  3601. #ifndef RDCHK
  3602.         signal(SIGQUIT,esctrp);         /* Quit signal, Sys III/V. */
  3603. #endif /* RDCHK */
  3604. #endif /* CK_POLL */
  3605. #endif /* SELECT */
  3606. #endif /* FIONREAD */
  3607.         if (conesc) conesc = 0;         /* Clear out pending escapes */
  3608. #else
  3609. #ifdef V7
  3610.         signal(SIGQUIT,esctrp);         /* V7 like Sys III/V */
  3611.         if (conesc) conesc = 0;
  3612. #else
  3613. #ifdef aegis
  3614.         signal(SIGQUIT,f);              /* Apollo, catch it like others. */
  3615. #else
  3616.         signal(SIGQUIT,SIG_IGN);        /* Others, ignore like 4D & earlier. */
  3617. #endif /* aegis */
  3618. #endif /* V7 */
  3619. #endif /* SVORPOSIX */
  3620. #endif /* OXOS */
  3621.     }
  3622. }
  3623. /*  C O N N O I  --  Reset console terminal interrupts */
  3624. VOID
  3625. connoi() {                              /* Console-no-interrupts */
  3626.     debug(F100,"connoi","",0);
  3627. #ifdef SIGTSTP
  3628.     signal(SIGTSTP,SIG_IGN); /* Suspend */
  3629. #endif /* SIGTSTP */
  3630.     conint(SIG_IGN,SIG_IGN); /* Interrupt */
  3631.     sigint_ign = 1; /* Remember we did this ourselves */
  3632. #ifdef SIGQUIT
  3633.     signal(SIGQUIT,SIG_IGN); /* Quit */
  3634. #endif /* SIGQUIT */
  3635. #ifdef SIGTERM
  3636.     signal(SIGTERM,SIG_IGN); /* Term */
  3637. #endif /* SIGTERM */
  3638. }
  3639. /*  I N I T R A W Q  --  Set up to read /dev/kmem for character count.  */
  3640. #ifdef  V7
  3641. /*
  3642.  Used in Version 7 to simulate Berkeley's FIONREAD ioctl call.  This
  3643.  eliminates blocking on a read, because we can read /dev/kmem to get the
  3644.  number of characters available for raw input.  If your system can't
  3645.  or you won't let the world read /dev/kmem then you must figure out a
  3646.  different way to do the counting of characters available, or else replace
  3647.  this by a dummy function that always returns 0.
  3648. */
  3649. /*
  3650.  * Call this routine as: initrawq(tty)
  3651.  * where tty is the file descriptor of a terminal.  It will return
  3652.  * (as a char *) the kernel-mode memory address of the rawq character
  3653.  * count, which may then be read.  It has the side-effect of flushing
  3654.  * input on the terminal.
  3655.  */
  3656. /*
  3657.  * John Mackin, Physiology Dept., University of Sydney (Australia)
  3658.  * ...!decvax!mulga!physiol.su.oz!john
  3659.  *
  3660.  * Permission is hereby granted to do anything with this code, as
  3661.  * long as this comment is retained unmodified and no commercial
  3662.  * advantage is gained.
  3663.  */
  3664. #ifndef MINIX
  3665. #ifndef MINIX2
  3666. #ifndef COHERENT
  3667. #include <a.out.h>
  3668. #include <sys/proc.h>
  3669. #endif /* COHERENT */
  3670. #endif /* MINIX2 */
  3671. #endif /* MINIX */
  3672. #ifdef COHERENT
  3673. #include <l.out.h>
  3674. #include <sys/proc.h>
  3675. #endif /* COHERENT */
  3676. char *
  3677. initrawq(tty) int tty; {
  3678. #ifdef MINIX
  3679.     return(0);
  3680. #else
  3681. #ifdef MINIX2
  3682.     return(0);
  3683. #else
  3684. #ifdef UTS24
  3685.     return(0);
  3686. #else
  3687. #ifdef BSD29
  3688.     return(0);
  3689. #else
  3690.     long lseek();
  3691.     static struct nlist nl[] = {
  3692.         {PROCNAME},
  3693.         {NPROCNAME},
  3694.         {""}
  3695.     };
  3696.     static struct proc *pp;
  3697.     char *qaddr, *p, c;
  3698.     int m;
  3699.     PID_T pid, me;
  3700.     NPTYPE xproc;                       /* Its type is defined in makefile. */
  3701.     int catch();
  3702.     me = getpid();
  3703.     if ((m = open("/dev/kmem", 0)) < 0) err("kmem");
  3704.     nlist(BOOTNAME, nl);
  3705.     if (nl[0].n_type == 0) err("proc array");
  3706.     if (nl[1].n_type == 0) err("nproc");
  3707.     lseek(m, (long)(nl[1].n_value), 0);
  3708.     read (m, &xproc, sizeof(xproc));
  3709.     saval = signal(SIGALRM, catch);
  3710.     if ((pid = fork()) == 0) {
  3711.         while(1)
  3712.             read(tty, &c, 1);
  3713.     }
  3714.     alarm(2);
  3715.     if(setjmp(jjbuf) == 0) {
  3716.         while(1)
  3717.   read(tty, &c, 1);
  3718.     }
  3719.     signal(SIGALRM, SIG_DFL);
  3720. #ifdef DIRECT
  3721.     pp = (struct proc *) nl[0].n_value;
  3722. #else
  3723.     if (lseek(m, (long)(nl[0].n_value), 0) < 0L) err("seek");
  3724.     if (read(m, &pp, sizeof(pp)) != sizeof(pp))  err("no read of proc ptr");
  3725. #endif
  3726.     lseek(m, (long)(nl[1].n_value), 0);
  3727.     read(m, &xproc, sizeof(xproc));
  3728.     if (lseek(m, (long)pp, 0) < 0L) err("Can't seek to proc");
  3729.     if ((p = malloc(xproc * sizeof(struct proc))) == NULL) err("malloc");
  3730.     if (read(m,p,xproc * sizeof(struct proc)) != xproc*sizeof(struct proc))
  3731.         err("read proc table");
  3732.     for (pp = (struct proc *)p; xproc > 0; --xproc, ++pp) {
  3733.         if (pp -> p_pid == (short) pid) goto iout;
  3734.     }
  3735.     err("no such proc");
  3736. iout:
  3737.     close(m);
  3738.     qaddr = (char *)(pp -> p_wchan);
  3739.     free (p);
  3740.     kill(pid, SIGKILL);
  3741.     wait((WAIT_T *)0);
  3742.     return (qaddr);
  3743. #endif
  3744. #endif
  3745. #endif
  3746. #endif
  3747. }
  3748. /*  More V7-support functions...  */
  3749. static VOID
  3750. err(s) char *s; {
  3751.     char buf[200];
  3752.     sprintf(buf, "fatal error in initrawq: %s", s);
  3753.     perror(buf);
  3754.     doexit(1,-1);
  3755. }
  3756. static VOID
  3757. catch(foo) int foo; {
  3758.     longjmp(jjbuf, -1);
  3759. }
  3760. /*  G E N B R K  --  Simulate a modem break.  */
  3761. #ifdef MINIX
  3762. #define BSPEED B110
  3763. #else
  3764. #ifdef MINIX2
  3765. #define BSPEED B110
  3766. #else
  3767. #define BSPEED B150
  3768. #endif /* MINIX2 */
  3769. #endif /* MINIX */
  3770. #ifndef MINIX2
  3771. VOID
  3772. genbrk(fn,msec) int fn, msec; {
  3773.     struct sgttyb ttbuf;
  3774.     int ret, sospeed, x, y;
  3775.     ret = ioctl(fn, TIOCGETP, &ttbuf);
  3776.     sospeed = ttbuf.sg_ospeed;
  3777.     ttbuf.sg_ospeed = BSPEED;
  3778.     ret = ioctl(fn, TIOCSETP, &ttbuf);
  3779.     y = (int)strlen(brnuls);
  3780.     x = ( BSPEED * 100 ) / msec;
  3781.     if (x > y) x = y;
  3782.     ret = write(fn, brnuls, (( BSPEED * 100 ) / msec ));
  3783.     ttbuf.sg_ospeed = sospeed;
  3784.     ret = ioctl(fn, TIOCSETP, &ttbuf);
  3785.     ret = write(fn, "@", 1);
  3786.     return;
  3787. }
  3788. #endif /* MINIX2 */
  3789. #ifdef MINIX2
  3790. int
  3791. genbrk(fn,msec) int fn, msec; {
  3792.     struct termios ttbuf;
  3793.     int ret, x, y;
  3794.     speed_t sospeed;
  3795.     ret = tcgetattr(fn, &ttbuf);
  3796.     sospeed = ttbuf.c_ospeed;
  3797.     ttbuf.c_ospeed = BSPEED;
  3798.     ret = tcsetattr(fn,TCSADRAIN, &ttbuf);
  3799.     y = (int)strlen(brnuls);
  3800.     x = ( BSPEED * 100 ) / msec;
  3801.     if (x > y) x = y;
  3802.     ret = write(fn, brnuls, (( BSPEED * 100 ) / msec ));
  3803.     ttbuf.c_ospeed = sospeed;
  3804.     ret = tcsetattr(fn, TCSADRAIN, &ttbuf);
  3805.     ret = write(fn, "@", 1);
  3806.     return ret;
  3807. }
  3808. #endif /* MINIX2 */
  3809. #endif /* V7 */
  3810. /*
  3811.   I N C H K  --  Check if chars waiting to be read on given file descriptor.
  3812.   This routine is a merger of ttchk() and conchk().
  3813.   Call with:
  3814.     channel == 0 to check console.
  3815.     channel == 1 to check communications connection.
  3816.   and:
  3817.     fd = file descriptor.
  3818.   Returns:
  3819.    >= 0: number of characters waiting, 0 or greater,
  3820.      -1: on any kind of error,
  3821.      -2: if there is (definitely) no connection.
  3822.   Note: In UNIX we don't have to call nettchk() because a socket
  3823.   file descriptor works just like in serial i/o, ioctls and all.
  3824.   (But this will change if we add non-file-descriptor channels,
  3825.   such as IBM X.25 for AIX...)
  3826. */
  3827. static int
  3828. in_chk(channel, fd) int channel, fd; {
  3829.     int x, n = 0; /* Workers, n = return value */
  3830.     extern int clsondisc; /* Close on disconnect */
  3831. /*
  3832.   The first section checks to make sure we have a connection,
  3833.   but only if we're in local mode.
  3834. */
  3835. #ifdef DEBUG
  3836.     if (deblog) {
  3837. char buf[16];
  3838. sprintf(buf,"%d",fd); /* File descriptor */
  3839. debug(F111,"in_chk entry",buf,channel);
  3840. debug(F101,"in_chk ttyfd","",ttyfd);
  3841. debug(F101,"in_chk ttpty","",ttpty);
  3842.     }
  3843. #endif /* DEBUG */
  3844. /*
  3845.   But don't say connection is gone if we have any buffered-stuff.
  3846. */
  3847. #ifdef TTLEBUF
  3848.     debug(F101,"in_chk ttpush","",ttpush);
  3849.     if (channel == 1) {
  3850. if (ttpush >= 0)
  3851.   n++;
  3852. n += le_inbuf();
  3853. if (n > 0)
  3854.   return(n);
  3855.     }
  3856. #endif /* TTLEBUF */
  3857. #ifdef NETPTY
  3858. #ifdef HAVE_PTYTRAP
  3859.     /* Special handling for HP-UX pty i/o */
  3860.     if (ttpty && pty_trap_pending(ttyfd) > 0) {
  3861.         if (pty_trap_handler(ttyfd) > 0) {
  3862.             ttclos(0);
  3863.             return(-2);
  3864.         }
  3865.     }
  3866. #endif /* HAVE_PTYTRAP */
  3867. #endif /* NETPTY */
  3868.     if (channel) { /* Checking communications channel */
  3869. if (ttyfd < 0) { /* No connection */
  3870.   return(-2); /* That's what this means */
  3871. } else if (xlocal && /* In local mode */
  3872.    !netconn && /* Serial connection */
  3873.    ttcarr != CAR_OFF /* with CARRIER WATCH ON (or AUTO) */
  3874. #ifdef COMMENT
  3875. #ifdef MYREAD
  3876. /*
  3877.   Seems like this would be a good idea but it prevents C-Kermit from
  3878.   popping back to the prompt automatically when carrier drops.  However,
  3879.   commenting this out prevents us from seeing the NO CARRIER message.
  3880.   Needs more work...
  3881. */
  3882.    && my_count < 1 /* Nothing in our internal buffer */
  3883. #endif /* MYREAD */
  3884. #endif /* COMMENT */
  3885.    ) {
  3886.     int x;
  3887.     x = ttgmdm(); /* So get modem signals */
  3888.     if (x > -1) { /* Check for carrier */
  3889. if (!(x & BM_DCD)) { /* No carrier */
  3890.     debug(F101,"in_chk carrier lost","",x);
  3891.     if (clsondisc) { /* If "close-on-disconnect" */
  3892. debug(F100,"in_chk close-on-disconnect","",0);
  3893. ttclos(0); /* close device & release lock. */
  3894.     }
  3895.     return(-2); /* This means "disconnected" */
  3896. }
  3897.     }
  3898. }
  3899.     }
  3900. /* We seem to have a connection so now see if any bytes are waiting on it */
  3901. #ifdef CK_SSL
  3902.     if (ssl_active_flag) {
  3903.         n += SSL_pending(ssl_con);
  3904.         debug(F101,"in_chk SSL_pending","",n);
  3905.         if (n < 0) /* Is this right? */
  3906.   return(-1);
  3907.         else
  3908.   return(n);
  3909.     } else if (tls_active_flag) {
  3910.         n += SSL_pending(tls_con);
  3911.         debug(F101,"in_chk TLS_pending","",n);
  3912.         if (n < 0) /* Is this right? */
  3913.   return(-1);
  3914.         else
  3915.   return(n);
  3916.     }
  3917. #endif /* CK_SSL */
  3918. #ifdef RLOGCODE
  3919. #ifdef CK_KERBEROS
  3920.     /* It is not safe to read any data when using encrypted Klogin */
  3921.     if (ttnproto == NP_EK4LOGIN || ttnproto == NP_EK5LOGIN) {
  3922. #ifdef KRB4
  3923.         if (ttnproto == NP_EK4LOGIN) {
  3924.             n += krb4_des_avail(ttyfd);
  3925.             debug(F101,"in_chk krb4_des_avail","",n);
  3926.         }
  3927. #endif /* KRB4 */
  3928. #ifdef KRB5
  3929.         if (ttnproto == NP_EK5LOGIN) {
  3930.             n += krb5_des_avail(ttyfd);
  3931.             debug(F101,"in_chk krb5_des_avail","",n);
  3932.         }
  3933. #endif /* KRB5 */
  3934.         if (n < 0) /* Is this right? */
  3935.   return(-1);
  3936.         else
  3937.   return(n);
  3938.     }
  3939. #endif /* CK_KERBEROS */
  3940. #endif /* RLOGCODE */
  3941.     errno = 0; /* Reset this so we log good info */
  3942. #ifdef FIONREAD
  3943.     x = ioctl(fd, FIONREAD, &n); /* BSD and lots of others */
  3944. #ifdef DEBUG /* (the more the better) */
  3945.     if (deblog) {
  3946. debug(F101,"in_chk FIONREAD return code","",x);
  3947. debug(F101,"in_chk FIONREAD count","",n);
  3948. debug(F101,"in_chk FIONREAD errno","",errno);
  3949.     }
  3950. #endif /* DEBUG */
  3951. #else /* FIONREAD not defined */
  3952. /*
  3953.   Here, if (netconn && ttnet == NET_TCPB), we might try calling recvmsg()
  3954.   with flags MSG_PEEK|MSG_DONTWAIT on the socket (ttyfd), except this is not
  3955.   portable (MSG_DONTWAIT isn't defined in any of the <sys/socket.h> files
  3956.   that I looked at, but it is needed to prevent the call from blocking), and
  3957.   the msghdr struct differs from place to place, so we would need another
  3958.   avalanche of ifdefs.  Still, when FIONREAD is not available, this is the
  3959.   only other known method of asking the OS for the *number* of characters
  3960.   available for reading.
  3961. */
  3962. #ifdef V7 /* UNIX V7: look in kernel memory */
  3963. #ifdef MINIX
  3964.     n = 0; /* But not in MINIX */
  3965. #else
  3966. #ifdef MINIX2
  3967.     n = 0;
  3968. #else
  3969.     lseek(kmem[TTY], (long) qaddr[TTY], 0); /* 7th Edition Unix */
  3970.     x = read(kmem[TTY], &n, sizeof(int));
  3971.     if (x != sizeof(int))
  3972.       n = 0;
  3973. #endif /* MINIX2 */
  3974. #endif /* MINIX */
  3975. #else /* Not V7 */
  3976. #ifdef PROVX1
  3977.     x = ioctl(fd, TIOCQCNT, &ttbuf); /* DEC Pro/3xx Venix V.1 */
  3978.     n = ttbuf.sg_ispeed & 0377; /* Circa 1984 */
  3979.     if (x < 0) n = 0;
  3980. #else
  3981. #ifdef MYREAD
  3982. /*
  3983.   Here we skip all the undependable and expensive calls below if we
  3984.   already have something in our internal buffer.  This tends to work quite
  3985.   nicely, so the only really bad case remaining is the one in which neither
  3986.   FIONREAD or MYREAD are defined, which is increasingly rare these days.
  3987. */
  3988.     if (channel != 0 && my_count > 0) {
  3989. debug(F101,"in_chk buf my_count","",my_count);
  3990. n = my_count; /* n was 0 before we got here */
  3991. return(n);
  3992.     }
  3993. #endif /* MYREAD */
  3994. /*
  3995.   rdchk(), select(), and poll() tell us *if* data is available to be read, but
  3996.   not how much, so these should be used only as a final resort.  Especially
  3997.   since these calls tend to add a lot overhead.
  3998. */
  3999. #ifdef RDCHK /* This mostly SCO-specific */
  4000.     n = rdchk(fd);
  4001.     debug(F101,"in_chk rdchk","",n);
  4002. #else /* No RDCHK */
  4003. #ifdef SELECT
  4004. #ifdef Plan9
  4005.     /* Only allows select on the console ... don't ask */
  4006.     if (channel == 0)
  4007. #endif /* Plan9 */
  4008.       {
  4009. fd_set rfds; /* Read file descriptors */
  4010. #ifdef BELLV10
  4011. FD_ZERO(rfds); /* Initialize them */
  4012. FD_SET(fd,rfds); /* We want to look at this fd */
  4013. #else
  4014. FD_ZERO(&rfds); /* Initialize them */
  4015. FD_SET(fd,&rfds); /* We want to look at this fd */
  4016. tv.tv_sec = tv.tv_usec = 0L; /* A 0-valued timeval structure */
  4017. #endif /* BELLV10 */
  4018. #ifdef Plan9
  4019. n = select( FD_SETSIZE, &rfds, (fd_set *)0, (fd_set *)0, &tv );
  4020. debug(F101,"in_chk Plan 9 select","",n);
  4021. #else
  4022. #ifdef BELLV10
  4023. n = select( 128, rfds, (fd_set *)0, (fd_set *)0, 0 );
  4024. debug(F101,"in_chk BELLV10 select","",n);
  4025. #else
  4026. #ifdef BSD44
  4027. n = select( FD_SETSIZE, &rfds, (fd_set *)0, (fd_set *)0, &tv );
  4028. debug(F101,"in_chk BSD44 select","",n);
  4029. #else
  4030. #ifdef BSD43
  4031. n = select( FD_SETSIZE, &rfds, (fd_set *)0, (fd_set *)0, &tv );
  4032. debug(F101,"in_chk BSD43 select","",n);
  4033. #else
  4034. #ifdef SOLARIS
  4035. n = select( FD_SETSIZE, &rfds, (fd_set *)0, (fd_set *)0, &tv );
  4036. debug(F101,"in_chk SOLARIS select","",n);
  4037. #else
  4038. #ifdef QNX
  4039. n = select( FD_SETSIZE, &rfds, (fd_set *)0, (fd_set *)0, &tv );
  4040. debug(F101,"in_chk QNX select","",n);
  4041. #else
  4042. #ifdef COHERENT
  4043. n = select( FD_SETSIZE, &rfds, (fd_set *)0, (fd_set *)0, &tv );