ckutio.c
资源名称:cku197.tar.Z [点击查看]
上传用户:dufan58
上传日期:2007-01-05
资源大小:3407k
文件大小:361k
源码类别:
通讯/手机编程
开发平台:
Windows_Unix
- printf("UUCP not installed or Kermit misconfiguredn");
- } else {
- if (!quiet)
- perror(lockdir);
- unlink(tmpnam); /* Get rid of the temporary file. */
- }
- priv_off(); /* Turn off privileges!!! */
- return(-1); /* Return failure code. */
- }
- /* Now write the pid into the temp lockfile in the appropriate format */
- #ifdef PIDSTRING /* For Honey DanBer UUCP, */
- sprintf( /* write PID as decimal string */
- pid_str,
- #ifdef LINUXFSSTND /* The "Linux File System Standard" */
- #ifdef FSSTND10 /* Version 1.0 calls for */
- "%010dn", /* leading zeros */
- #else /* while version 1.2 calls for */
- "%10dn", /* leading spaces */
- #endif /* FSSTND10 */
- #else
- #ifdef COHERENT
- "%dn", /* with leading nothing */
- #else
- "%10dn", /* with leading blanks */
- #endif /* COHERENT */
- #endif /* LINUXFSSTND */
- (int) pid
- );
- write(lockfd, pid_str, 11);
- debug(F111,"ttlock hdb pid string",pid_str,(int) pid);
- #else /* Not PIDSTRING, use integer PID */
- write(lockfd, (char *)&pid, sizeof(pid) );
- debug(F101,"ttlock pid","",(int) pid);
- #endif /* PIDSTRING */
- /* Now try to rename the temp file to the real lock file name. */
- /* This will fail if a lock file of that name already exists. */
- close(lockfd); /* Close the temp lockfile. */
- chmod(tmpnam,0444); /* Permission for a valid lock. */
- tries = 0;
- while (!haslock && tries++ < 2) {
- haslock = (link(tmpnam,flfnam) == 0); /* Create a link to it. */
- if (haslock) { /* If we got the lockfile */
- #ifdef RTAIX
- link(flfnam,lkflfn);
- #endif /* RTAIX */
- #ifdef CKSYMLINK
- if (islink && lock2[0])
- link(flfnam,lock2);
- #endif /* CKSYMLINK */
- #ifdef LOCKF
- /*
- Advisory file locking works on SVR4, so we use it. In fact, it is
- necessary in some cases, e.g. when SLIP is involved. But it still doesn't
- seem to prevent multiple users accessing the same device by different names.
- */
- while (lockf(ttyfd, F_TLOCK, 0L) != 0) {
- debug(F111, "ttlock: lockf returns errno", "", errno);
- if ((++tries >= 3) || (errno != EAGAIN)) {
- x = unlink(flfnam); /* remove the lockfile */
- #ifdef RTAIX
- unlink(lkflfn); /* And any links to it... */
- #endif /* RTAIX */
- #ifdef CKSYMLINK
- if (islink && lock2[0])
- unlink(lock2); /* ditto... */
- #endif /* CKSYMLINK */
- debug(F111,"ttlock unlink",flfnam,x);
- haslock = 0;
- break;
- }
- sleep(2);
- }
- if (haslock) /* If we got an advisory lock */
- #endif /* LOCKF */
- break; /* We're done. */
- } else { /* We didn't create a new lockfile. */
- priv_off();
- if (ttchkpid(flfnam)) { /* Check existing lockfile */
- priv_on(); /* cause ttchkpid turns priv_off... */
- unlink(tmpnam); /* Delete the tempfile */
- debug(F100,"ttlock found tty locked","",0);
- priv_off(); /* Turn off privs */
- return(-2); /* Code for device is in use. */
- }
- priv_on();
- }
- }
- unlink(tmpnam); /* Unlink (remove) the temp file. */
- priv_off(); /* Turn off privs */
- return(haslock ? 0 : -1); /* Return link's return code. */
- #else /* HPUX */
- /*
- HP-UX gets its own copy of this routine, modeled after the observed behavior
- of the HP-UX 'cu' program. HP-UX serial device names consist of a base name
- such as "tty", "ttyd", "cua", "cul", "cuad", or "culd", followed by a unit
- designator which is a string of digits, possibly containing an imbedded
- letter "p". Examples (for base name "tty"):
- /dev/tty0, /dev/tty00, dev/ttyd00, /dev/tty0p0
- According to the HP-UX UUCP manual of 1988, the "0p0" notation has been
- used on Series 800 since HP-UX 2.00, and the "non-p" notation was used
- on other models. In HP-UX 10.00, "0p0" notation was adopted for all models.
- However, we make and enforce no such distinctions; either notation is
- accepted on any model or HP-UX version as a valid unit designator.
- If a valid unit is specified (as opposed to a designer name or symlink), we
- check for all aliases of the given unit according to the devprefix[] array.
- If no lockfiles are found for the given unit, we can have the device; we
- create a lockfile LCK..name in the lockfile directory appropriate for the
- HP-UX version (/var/spool/locks for 10.00 and later, /usr/spool/uucp for
- 9.xx and earlier). If it is a "cua" or "cul" device, a second lockfile is
- created with the "ttyd" prefix. This is exactly what cu does.
- If the "set line" device does not have a valid unit designator, then it is
- used literally and no synomyms are searched for and only one lockfile is
- created.
- -fdc, March 1998.
- */
- #define LFNAML 80 /* Max length for lock file name. */
- int lockfd; /* File descriptor for lock file. */
- PID_T pid; /* Process ID of this process. */
- int fpid; /* pid found in existing lockfile. */
- int tries; /* How many times we've tried... */
- int i, k; /* Workers */
- char *device, *devname; /* "/dev/xxx", "xxx" */
- char *unit, *p; /* <instance>p<port> part of xxx */
- char lockfil[LFNAML]; /* Lockfile name (no path) */
- char tmpnam[LFNAML]; /* Temporary lockfile name. */
- #ifdef HPUX10 /* Lockfile directory */
- char *lockdir = "/var/spool/locks"; /* Always this for 10.00 and higher */
- #else /* HP-UX 9.xx and below */
- #ifdef LOCK_DIR
- char *lockdir = LOCK_DIR; /* Defined near top of this file */
- #else
- char *lockdir = "/usr/spool/uucp"; /* or not... */
- #endif /* LOCK_DIR */
- #endif /* HPUX10 */
- haslock = 0; /* Not locked yet. */
- *flfnam = ' '; /* Lockfile name is empty. */
- lock2[0] = ' '; /* Second one too. */
- pid = getpid(); /* Get my process ID */
- /*
- Construct name of lockfile and temporary file...
- device = name of tty device without the path, e.g. "tty0p0"
- lockfil = name of lock file, without path, e.g. "LCK..tty0p0"
- */
- device = ((devname = xxlast(ttdev,'/')) != NULL ? devname+1 : ttdev);
- debug(F110,"TTLOCK device",device,0);
- sprintf(lockfil,"LCK..%s", device);
- k = 0; /* Assume device is not locked */
- n = 0; /* Digit counter */
- unit = device; /* Unit = <instance>p<port> */
- while (*unit && !isdigit(*unit)) /* Search for digit... */
- unit++;
- p = unit; /* Verify <num>p<num> format... */
- debug(F110,"TTLOCK unit 1",unit,0);
- /*
- The unit number is recognized as:
- (a) any sequence of digits that runs to the end of the string.
- (b) any (a) that includes one and only one letter "p", with at least
- one digit before and after it.
- */
- while (isdigit(*p)) p++, n++; /* Get a run of digits */
- if (*p && n > 0) { /* Have a "p"? */
- if (*p == 'p' && isdigit(*(p+1))) {
- p++;
- n = 0;
- while (isdigit(*p)) p++, n++;
- }
- }
- if (n == 0 || *p) unit = "";
- debug(F110,"TTLOCK unit 2",unit,0);
- if (*unit) { /* Device name has unit number. */
- /* The following loop not only searches for the various lockfile */
- /* synonyms, but also removes all -- not just one -- stale lockfile */
- /* for the device, should there be more than one. See ttchkpid(). */
- ttydexists = 0;
- for (i = 0; *devprefix[i]; i++) { /* For each driver... */
- /* Make device name */
- sprintf(lock2,"/dev/%s%s",devprefix[i],unit);
- priv_on(); /* Privs on */
- k = zchki(lock2) != -1; /* See if device exists */
- priv_off(); /* Privs off */
- debug(F111,"TTLOCK exist",lock2,k);
- if (k) {
- if (!strcmp(devprefix[i],"ttyd")) /* ttyd device exists */
- ttydexists = 1;
- /* Make lockfile name */
- sprintf(lock2,"%s/LCK..%s%s",lockdir,devprefix[i],unit);
- debug(F110,"TTLOCK checking",lock2,0);
- priv_on(); /* Privs on */
- k = zchki(lock2) != -1; /* See if lockfile exists */
- priv_off(); /* Privs off */
- debug(F111,"TTLOCK check for lock A",lock2,k);
- if (k) if (ttchkpid(lock2)) { /* If pid still active, fail. */
- ckstrncpy(flfnam,lock2,FLFNAML);
- return(-2);
- }
- }
- }
- } else { /* Some other device-name format */
- /* This takes care of symbolic links, etc... */
- /* But does not chase them down! */
- sprintf(lock2,"%s/LCK..%s",lockdir,device); /* Use the name as-is */
- priv_on();
- k = zchki(lock2) != -1; /* Check for existing lockfile */
- priv_off();
- debug(F111,"TTLOCK check for lock B",lock2,k);
- if (k) if (ttchkpid(lock2)) { /* Check pid from lockfile */
- ckstrncpy(flfnam,lock2,FLFNAML);
- debug(F110,"TTLOCK in use",device,0);
- debug(F101,"TTLOCK returns","",-2);
- return(-2);
- }
- }
- /*
- Get here only if there is no (more) lockfile, so now we make one (or two)...
- flfnam = full lockfile pathname, e.g. "/usr/spool/uucp/LCK..cul0p0".
- tmpnam = unique temporary filname, e.g. "/usr/spool/uucp/LTMP..pid".
- */
- sprintf(flfnam,"%s/%s",lockdir,lockfil); /* Our SET LINE device */
- /* If dialout device, also make one for corresponding dialin device */
- lock2[0] = ' ';
- if (!strncmp(device,"cu",2) && *unit && ttydexists)
- sprintf(lock2, "%s/LCK..ttyd%s", lockdir, unit);
- sprintf(tmpnam,"%s/LTMP.%05d",lockdir,(int) pid); /* Make temporary name */
- #ifdef DEBUG
- if (deblog) {
- debug(F110,"TTLOCK flfnam",flfnam,0);
- debug(F110,"TTLOCK lock2",lock2,0);
- debug(F110,"TTLOCK tmpnam",tmpnam,0);
- }
- #endif /* DEBUG */
- /*
- Lockfile permissions...
- 444 is standard, HP-UX 10.00 uses 664. It doesn't matter.
- Kermit uses 444; the difference lets us tell whether Kermit created
- the lock file.
- */
- priv_on(); /* Turn on privileges. */
- lockfd = creat(tmpnam, 0444); /* Try to create temporary file. */
- if (lockfd < 0) { /* Create failed. */
- debug(F111,"TTLOCK creat failed",tmpnam,errno);
- if (errno == ENOENT) {
- perror(lockdir);
- printf("UUCP not installed or Kermit misconfiguredn");
- } else {
- if (!quiet)
- perror(lockdir);
- unlink(tmpnam); /* Get rid of the temporary file. */
- }
- priv_off(); /* Turn off privileges!!! */
- debug(F101,"TTLOCK returns","",-1);
- return(-1); /* Return failure code. */
- }
- debug(F110,"TTLOCK temp ok",tmpnam,0);
- /* Now write our pid into the temp lockfile in integer format. */
- i = write(lockfd, (char *)&pid, sizeof(pid));
- #ifdef DEBUG
- if (deblog) {
- debug(F101,"TTLOCK pid","",pid);
- debug(F101,"TTLOCK sizeof pid","",sizeof(pid));
- debug(F101,"TTLOCK write pid returns","",i);
- }
- #endif /* DEBUG */
- /*
- Now try to rename the temporary file to the real lockfile name.
- This will fail if a lock file of that name already exists, which
- will catch race conditions with other users.
- */
- close(lockfd); /* Close the temp lockfile. */
- chmod(tmpnam,0444);
- tries = 0;
- while (!haslock && tries++ < 2) {
- haslock = (link(tmpnam,flfnam) == 0); /* Create a link to it. */
- debug(F101,"TTLOCK link","",haslock);
- if (haslock) { /* If we made the lockfile... */
- #ifdef LOCKF /* Can be canceled with -DNOLOCKF */
- /*
- Create an advisory lock on the device through its file descriptor.
- This code actually seems to work. If it is executed, and then another
- process tries to open the same device under a different name to circumvent
- the lockfile, they get a "device busy" error.
- */
- debug(F100,"TTLOCK LOCKF code...","",0);
- while ( lockf(ttyfd, F_TLOCK, 0L) != 0 ) {
- debug(F111, "TTLOCK lockf error", "", errno);
- if ((++tries >= 3) || (errno != EAGAIN)) {
- x = unlink(flfnam); /* Remove the lockfile */
- if (errno == EACCES && !quiet)
- printf("Device already locked by another processn");
- haslock = 0;
- break;
- }
- sleep(2);
- }
- #endif /* LOCKF */
- if (haslock) { /* If we made the lockfile ... */
- if (lock2[0]) { /* if there is to be a 2nd lockfile */
- lockfd = creat(lock2, 0444); /* Create it */
- debug(F111,"TTLOCK lock2 creat", lock2, lockfd);
- if (lockfd > -1) { /* Created OK, write pid. */
- write(lockfd, (char *)&pid, sizeof(pid) );
- close(lockfd); /* Close and */
- chmod(lock2, 0444); /* set permissions. */
- } else { /* Not OK, but don't fail. */
- lock2[0] = ' '; /* Just remember it's not there. */
- }
- }
- break; /* and we're done. */
- }
- }
- }
- unlink(tmpnam); /* Unlink (remove) the temp file. */
- priv_off(); /* Turn off privs */
- i = haslock ? 0 : -1; /* Our return value */
- debug(F101,"TTLOCK returns","",i);
- return(i);
- #endif /* HPUX */
- #endif /* USETTYLOCK */
- #endif /* !NOUUCP */
- }
- /* T T U N L O C K */
- static int
- ttunlck() { /* Remove UUCP lockfile(s). */
- #ifndef NOUUCP
- int x;
- debug(F111,"ttunlck",flfnam,haslock);
- #ifdef USETTYLOCK
- if (haslock && *flfnam) {
- int x;
- priv_on(); /* Turn on privs */
- #ifdef USE_UU_LOCK
- x = uu_unlock(lockname);
- #else /* USE_UU_LOCK */
- x = ttyunlock(lockname); /* Try to unlock */
- #endif /* USE_UU_LOCK */
- priv_off(); /* Turn off privs */
- if (x < 0 && !quiet)
- printf("Warning - Can't remove lockfile: %sn", flfnam);
- *flfnam = ' '; /* Erase the name. */
- haslock = 0;
- return(0);
- }
- #else /* No ttylock()... */
- if (haslock && *flfnam) {
- /* Don't remove lockfile if we didn't make it ourselves */
- if ((x = ttrpid(flfnam)) != (int)getpid()) {
- debug(F111,"ttunlck lockfile seized",flfnam,x);
- printf("Warning - Lockfile %s seized by pid %dn",
- flfnam,
- x
- );
- return(0);
- }
- priv_on(); /* Turn privileges on. */
- errno = 0;
- x = unlink(flfnam); /* Remove the lockfile. */
- debug(F111,"ttunlck unlink",flfnam,x);
- if (x < 0) {
- if (errno && !quiet)
- perror(ttnmsv);
- printf("Warning - Can't remove lockfile: %sn", flfnam);
- }
- haslock = 0;
- *flfnam = ' '; /* Erase the name. */
- #ifdef RTAIX
- errno = 0;
- x = unlink(lkflfn); /* Remove link to lockfile */
- debug(F111,"ttunlck AIX link unlink",lkflfn,x);
- if (x < 0) {
- if (errno && !quiet)
- perror(ttnmsv);
- printf("Warning - Can't remove link to lockfile: %sn", lkflfn);
- }
- *lkflfn = ' ';
- #else
- if (lock2[0]) { /* If there is a second lockfile, */
- errno = 0;
- x = unlink(lock2); /* remove it too. */
- debug(F111,"ttunlck lock2 unlink",lock2,x);
- if (x < 0) {
- if (errno && !quiet)
- perror(ttnmsv);
- printf("Warning - Can't remove secondary lockfile: %sn",
- lock2
- );
- }
- lock2[0] = ' '; /* Forget its name. */
- }
- #endif /* RTAIX */
- #ifdef LOCKF
- (VOID) lockf(ttyfd, F_ULOCK, 0L); /* Remove advisory lock */
- #endif /* LOCKF */
- priv_off(); /* Turn privileges off. */
- }
- #endif /* USETTYLOCK */
- #endif /* !NOUUCP */
- return(0);
- }
- /*
- 4.3BSD-style UUCP line direction control.
- (Stan Barber, Rice U, 1980-something...)
- */
- #ifndef NOUUCP
- #ifdef ACUCNTRL
- VOID
- acucntrl(flag,ttname) char *flag, *ttname; {
- char x[DEVNAMLEN+32], *device, *devname;
- if (strcmp(ttname,CTTNAM) == 0 || xlocal == 0) /* If not local, */
- return; /* just return. */
- device = ((devname = xxlast(ttname,'/')) != NULL ? devname+1 : ttname);
- if (strncmp(device,"LCK..",4) == 0) device += 5;
- sprintf(x,"/usr/lib/uucp/acucntrl %s %s",flag,device);
- debug(F110,"called ",x,0);
- zsyscmd(x);
- }
- #endif /* ACUCNTRL */
- #endif /* NOUUCP */
- /*
- T T H F L O W -- Set or Reset hardware flow control.
- This is an attempt to collect all hardware-flow-control related code
- into a single module. Thanks to Rick Sladkey and John Kohl for lots of
- help here. Overview:
- Hardware flow control is not supported in many UNIX implementions. Even
- when it is supported, there is no (ha ha) "standard" for the programming
- interface. In general, 4.3BSD and earlier (sometimes), 4.4BSD, System V,
- SunOS, AIX, etc, have totally different methods. (And, not strictly
- relevant here, the programming interface often brings one only to a no-op
- in the device driver!)
- Among all these, we have two major types of APIs: those in which hardware
- flow control is determined by bits in the same termio/termios/sgtty mode
- word(s) that are used for controlling such items as CBREAK vs RAW mode, and
- which are also used by the ttvt(), ttpkt(), conbin(), and concb() routines
- for changing terminal modes. And those that use entirely different
- mechanisms.
- In the first category, it is important that any change in the mode bits be
- reflected in the relevant termio(s)/sgtty structure, so that subsequent
- changes to that structure do not wipe out the effects of this routine. That
- is why a pointer, attrs, to the appropriate structure is passed as a
- parameter to this routine.
- The second category should give us no worries, since any changes to hardware
- flow control accomplished by this routine should not affect the termio(s)/
- sgtty structures, and therefore will not be undone by later changes to them.
- The second argument, status, means to turn on hardware flow control if
- nonzero, and to turn it off if zero.
- Returns: 0 on apparent success, -1 on probable failure.
- */
- static int
- tthflow(flow, status, attrs)
- int flow, /* Type of flow control (ckcdeb.h) */
- status; /* Nonzero = turn it on */
- /* Zero = turn it off */
- #ifdef BSD44ORPOSIX /* POSIX or BSD44 */
- struct termios *attrs;
- #else /* System V */
- #ifdef ATTSV
- #ifdef ATT7300
- #ifdef UNIX351M
- /* AT&T UNIX 3.51m can set but not test for hardware flow control */
- #define RTSFLOW CTSCD
- #define CTSFLOW CTSCD
- #endif /* ATT7300 */
- #endif /* UNIX351M */
- struct termio *attrs;
- #else /* BSD, V7, etc */
- struct sgttyb *attrs; /* sgtty info... */
- #endif /* ATTSV */
- #endif /* BSD44ORPOSIX */
- /* tthflow */ {
- int x = 0; /* tthflow() return code */
- #ifdef Plan9
- return p9tthflow(flow, status);
- #else
- #ifndef OXOS /* NOT Olivetti X/OS... */
- /*
- For SunOS 4.0 and later in the BSD environment ...
- The declarations are copied and interpreted from the System V header files,
- so we don't actually have to pull in all the System V junk when building
- C-Kermit for SunOS in the BSD environment, which would be dangerous because
- having those symbols defined would cause us to take the wrong paths through
- the code. The code in this section is used in both the BSD and Sys V SunOS
- versions.
- */
- #ifdef SUNOS41
- /*
- In SunOS 4.1 and later, we use the POSIX calls rather than ioctl calls
- because GNU CC uses different formats for the _IOxxx macros than regular CC;
- the POSIX forms work for both. But the POSIX calls are not available in
- SunOS 4.0.
- */
- #define CRTSCTS 0x80000000 /* RTS/CTS flow control */
- #define TCSANOW 0 /* Do it now */
- struct termios {
- unsigned long c_iflag; /* Input modes */
- unsigned long c_oflag; /* Output modes */
- unsigned long c_cflag; /* Control modes */
- unsigned long c_lflag; /* Line discipline modes */
- char c_line;
- CHAR c_cc[17];
- };
- struct termios temp;
- _PROTOTYP( int tcgetattr, (int, struct termios *) );
- _PROTOTYP( int tcsetattr, (int, int, struct termios *) );
- /*
- When CRTSCTS is set, SunOS won't do output unless both CTS and CD are
- asserted. So we don't set CRTSCTS unless CD is up. This should be OK,
- since we don't need RTS/CTS during dialing, and after dialing is complete,
- we should have CD. If not, we still communicate, but without RTS/CTS.
- */
- int mflags; /* Modem signal flags */
- #ifdef NETCMD
- if (ttpipe) return(0);
- #endif /* NETCMD */
- #ifdef NETPTY
- if (ttpty) return(0);
- #endif /* NETPTY */
- debug(F101,"tthflow SUNOS41 entry status","",status);
- if (!status) { /* Turn hard flow off */
- if (tcgetattr(ttyfd, &temp) > -1 && /* Get device attributes */
- (temp.c_cflag & CRTSCTS)) { /* Check for RTS/CTS */
- temp.c_cflag &= ~CRTSCTS; /* It's there, remove it */
- x = tcsetattr(ttyfd,TCSANOW,&temp);
- }
- } else { /* Turn hard flow on */
- if (ioctl(ttyfd,TIOCMGET,&mflags) > -1 && /* Get modem signals */
- (mflags & TIOCM_CAR)) { /* Check for CD */
- debug(F100,"tthflow SunOS has CD","",0);
- if (tcgetattr(ttyfd, &temp) > -1 && /* Get device attributes */
- !(temp.c_cflag & CRTSCTS)) { /* Check for RTS/CTS */
- temp.c_cflag |= CRTSCTS; /* Not there, add it */
- x = tcsetattr(ttyfd,TCSANOW,&temp);
- }
- } else {
- x = -1;
- debug(F100,"tthflow SunOS no CD","",0);
- }
- }
- #else
- #ifdef QNX
- struct termios temp;
- #ifdef NETCMD
- if (ttpipe) return(0);
- #endif /* NETCMD */
- #ifdef NETPTY
- if (ttpty) return(0);
- #endif /* NETPTY */
- debug(F101,"tthflow QNX entry status","",status);
- if (tcgetattr(ttyfd, &temp) > -1) { /* Get device attributes */
- if (!status) { /* Turn hard flow off */
- if ((temp.c_cflag & (IHFLOW|OHFLOW)) == (IHFLOW|OHFLOW)) {
- temp.c_cflag &= ~(IHFLOW|OHFLOW); /* It's there, remove it */
- attrs->c_cflag &= ~(IHFLOW|OHFLOW);
- x = tcsetattr(ttyfd,TCSANOW,&temp);
- }
- } else { /* Turn hard flow on */
- if ((temp.c_cflag & (IHFLOW|OHFLOW)) != (IHFLOW|OHFLOW)) {
- temp.c_cflag |= (IHFLOW|OHFLOW); /* Not there, add it */
- temp.c_iflag &= ~(IXON|IXOFF); /* Bye to IXON/IXOFF */
- ttraw.c_lflag |= IEXTEN; /* Must be on */
- x = tcsetattr(ttyfd,TCSANOW,&temp);
- attrs->c_cflag |= (IHFLOW|OHFLOW);
- attrs->c_iflag &= ~(IXON|IXOFF);
- }
- }
- } else {
- x = -1;
- debug(F100, "tthflow QNX getattr fails", "", 0);
- }
- #else
- #ifdef POSIX_CRTSCTS
- /*
- POSIX_CRTSCTS is defined in ckcdeb.h or on CC command line.
- Note: Do not assume CRTSCTS is a one-bit field!
- */
- struct termios temp;
- #ifdef NETCMD
- if (ttpipe) return(0);
- #endif /* NETCMD */
- #ifdef NETPTY
- if (ttpty) return(0);
- #endif /* NETPTY */
- debug(F101,"tthflow POSIX_CRTSCTS entry status","",status);
- errno = 0;
- x = tcgetattr(ttyfd, &temp);
- debug(F111,"tthflow POSIX_CRTSCTS tcgetattr",ckitoa(x),errno);
- errno = 0;
- if (x < 0) {
- x = -1;
- } else {
- if (!status) { /* Turn hard flow off */
- if (
- #ifdef COMMENT
- /* This can fail because of sign extension */
- /* e.g. in Linux where it's Bit 31 */
- (temp.c_cflag & CRTSCTS) == CRTSCTS
- #else
- (temp.c_cflag & CRTSCTS) != 0
- #endif /* COMMENT */
- ) {
- temp.c_cflag &= ~CRTSCTS; /* It's there, remove it */
- attrs->c_cflag &= ~CRTSCTS;
- x = tcsetattr(ttyfd,TCSANOW,&temp);
- debug(F111,"tthflow POSIX_CRTSCTS OFF tcsetattr",
- ckitoa(x),errno);
- }
- } else { /* Turn hard flow on */
- if (
- #ifdef COMMENT
- /* This can fail because of sign extension */
- (temp.c_cflag & CRTSCTS) != CRTSCTS
- #else
- (temp.c_cflag & CRTSCTS) == 0
- #endif /* COMMENT */
- ) {
- temp.c_cflag |= CRTSCTS; /* Not there, add it */
- temp.c_iflag &= ~(IXON|IXOFF|IXANY); /* Bye to IXON/IXOFF */
- x = tcsetattr(ttyfd,TCSANOW,&temp);
- debug(F111,"tthflow POSIX_CRTSCTS ON tcsetattr",
- ckitoa(x),errno);
- attrs->c_cflag |= CRTSCTS;
- attrs->c_iflag &= ~(IXON|IXOFF|IXANY);
- }
- }
- }
- #else
- #ifdef SUNOS4
- /*
- SunOS 4.0 (and maybe earlier?). This code is dangerous because it
- prevents compilation with GNU gcc, which uses different formats for the
- _IORxxx macros than regular cc. SunOS 4.1 and later can use the POSIX
- routines above, which work for both cc and gcc.
- */
- #define TCGETS _IOR(T, 8, struct termios) /* Get modes into termios struct */
- #define TCSETS _IOW(T, 9, struct termios) /* Set modes from termios struct */
- #define CRTSCTS 0x80000000 /* RTS/CTS flow control */
- struct termios {
- unsigned long c_iflag; /* Input modes */
- unsigned long c_oflag; /* Output modes */
- unsigned long c_cflag; /* Control modes */
- unsigned long c_lflag; /* Line discipline modes */
- char c_line;
- CHAR c_cc[17];
- };
- struct termios temp;
- #ifdef NETCMD
- if (ttpipe) return(0);
- #endif /* NETCMD */
- #ifdef NETPTY
- if (ttpty) return(0);
- #endif /* NETPTY */
- debug(F101,"tthflow entry status","",status);
- if (ioctl(ttyfd,TCGETS,&temp) > -1) { /* Get terminal modes. */
- if (status) { /* Turn hard flow on */
- temp.c_cflag |= CRTSCTS; /* Add RTS/CTS to them. */
- x = ioctl(ttyfd,TCSETS,&temp); /* Set them again. */
- attrs->c_cflag |= CRTSCTS; /* Add to global info. */
- } else { /* Turn hard flow off */
- temp.c_cflag &= ~CRTSCTS;
- x = ioctl(ttyfd,TCSETS,&temp);
- attrs->c_cflag &= ~CRTSCTS;
- }
- }
- #else /* Not SunOS 4.0 or later */
- #ifdef AIXRS /* IBM AIX RS/6000 */
- #ifndef AIX41 /* But only pre-4.x == SVR4 */
- #ifdef NETCMD
- if (ttpipe) return(0);
- #endif /* NETCMD */
- #ifdef NETPTY
- if (ttpty) return(0);
- #endif /* NETPTY */
- if (status) {
- if ((x = ioctl(ttyfd, TXADDCD, "rts")) < 0 && errno != EBUSY)
- debug(F100,"hardflow TXADDCD (rts) error", "", 0);
- } else {
- if ((x = ioctl(ttyfd, TXDELCD, "rts")) < 0 && errno != EINVAL)
- debug(F100,"hardflow TXDELCD (rts) error", "", 0);
- }
- #endif /* AIX41 */
- #else /* Not AIX RS/6000 */
- #ifdef ATTSV /* System V... */
- #ifdef CK_SCOV5 /* SCO Open Server 5.0 */
- #define CK_SCOUNIX
- #else
- #ifdef M_UNIX /* SCO UNIX 3.2v4.x or earlier */
- #define CK_SCOUNIX
- #endif /* M_UNIX */
- #endif /* CK_SCOV5 */
- #ifdef SCO_FORCE_RTSXOFF
- #ifdef CK_SCOUNIX /* But not SCO OpenServer 5.0.4 */
- #ifdef SCO_OSR504 /* or later... */
- #undef CK_SCOUNIX
- #endif /* SCO_OSR504 */
- #endif /* CK_SCOUNIX */
- #endif /* SCO_FORCE_RTSXOFF */
- #ifdef CK_SCOUNIX
- #ifdef POSIX
- struct termios temp;
- #ifdef NETCMD
- if (ttpipe) return(0);
- #endif /* NETCMD */
- #ifdef NETPTY
- if (ttpty) return(0);
- #endif /* NETPTY */
- debug(F101,"tthflow SCOUNIX POSIX entry status","",status);
- errno = 0;
- x = tcgetattr(ttyfd, &temp);
- debug(F111,"tthflow SCO UNIX POSIX tcgetattr",ckitoa(x),errno);
- #else /* POSIX */
- struct termio temp;
- #ifdef NETCMD
- if (ttpipe) return(0);
- #endif /* NETCMD */
- #ifdef NETPTY
- if (ttpty) return(0);
- #endif /* NETPTY */
- debug(F101,"tthflow SCOUNIX non-POSIX entry status","",status);
- x = ioctl(ttyfd, TCGETA, &temp);
- debug(F111,"tthflow SCO UNIX non-POSIX TCGETA",ckitoa(x),errno);
- #endif /* POSIX */
- /*
- This is not really POSIX, since POSIX does not deal with hardware flow
- control, but we are using the POSIX APIs. In fact, RTSFLOW and CTSFLOW
- are defined in termio.h, but within #ifndef _POSIX_SOURCE..#endif. So
- let's try forcing their definitions here.
- */
- #ifndef CTSFLOW
- #define CTSFLOW 0020000
- debug(F101,"tthflow SCO defining CTSFLOW","",CTSFLOW);
- #else
- debug(F101,"tthflow SCO CTSFLOW","",CTSFLOW);
- #endif /* CTSFLOW */
- #ifndef RTSFLOW
- #define RTSFLOW 0040000
- debug(F101,"tthflow SCO defining RTSFLOW","",RTSFLOW);
- #else
- debug(F101,"tthflow SCO RTSFLOW","",RTSFLOW);
- #endif /* RTSFLOW */
- #ifndef ORTSFL
- #define ORTSFL 0100000
- debug(F101,"tthflow SCO defining ORTSFL","",ORTSFL);
- #else
- debug(F101,"tthflow SCO ORTSFL","",ORTSFL);
- #endif /* ORTSFL */
- if (x != -1) {
- if (status) { /* Turn it ON */
- temp.c_cflag |= RTSFLOW|CTSFLOW;
- attrs->c_cflag |= RTSFLOW|CTSFLOW;
- #ifdef ORTSFL
- temp.c_cflag &= ~ORTSFL;
- attrs->c_cflag &= ~ORTSFL;
- #endif /* ORTSFL */
- temp.c_iflag &= ~(IXON|IXOFF|IXANY);
- attrs->c_iflag &= ~(IXON|IXOFF|IXANY);
- } else { /* Turn it OFF */
- #ifdef ORTSFL
- temp.c_cflag &= ~(RTSFLOW|CTSFLOW|ORTSFL);
- attrs->c_cflag &= ~(RTSFLOW|CTSFLOW|ORTSFL);
- #else /* ORTSFL */
- temp.c_cflag &= ~(RTSFLOW|CTSFLOW);
- attrs->c_cflag &= ~(RTSFLOW|CTSFLOW);
- #endif /* ORTSFL */
- }
- #ifdef POSIX
- x = tcsetattr(ttyfd, TCSADRAIN, &temp);
- #else
- x = ioctl(ttyfd, TCSETA, &temp);
- #endif /* POSIX */
- debug(F101,"tthflow SCO set modes","",x);
- }
- #else /* Not SCO UNIX */
- #ifdef NETCMD
- if (ttpipe) return(0);
- #endif /* NETCMD */
- #ifdef NETPTY
- if (ttpty) return(0);
- #endif /* NETPTY */
- if (!status) { /* Turn it OFF */
- #ifdef RTSXOFF
- debug(F100,"tthflow ATTSV RTS/CTS OFF","",0);
- rctsx.x_hflag &= ~(RTSXOFF|CTSXON);
- #ifdef TCSETX
- x = ioctl(ttyfd,TCSETX,&rctsx);
- debug(F101,"tthflow ATTSV TCSETX OFF","",x);
- #else
- x = -1
- debug(F100,"tthflow TCSETX not defined","",0);
- #endif /* TCSETX */
- #else
- debug(F100,"tthflow ATTSV RTSXOFF not defined","",0);
- #endif /* RTSXOFF */
- #ifdef DTRXOFF
- debug(F100,"tthflow ATTSV DTR/CD OFF","",0);
- rctsx.x_hflag &= ~(DTRXOFF|CDXON);
- x = ioctl(ttyfd,TCSETX,&rctsx);
- debug(F101,"tthflow ATTSV DTRXOFF OFF","",x);
- #else
- debug(F100,"tthflow ATTSV DTRXOFF not defined","",0);
- #endif /* DTRXOFF */
- } else { /* Turn it ON. */
- if (flow == FLO_RTSC) { /* RTS/CTS Flow control... */
- debug(F100,"tthflow ATTSV RTS/CTS ON","",0);
- #ifdef RTSXOFF
- /* This is the preferred way, according to SVID3 */
- #ifdef TCGETX
- x = ioctl(ttyfd,TCGETX,&rctsx);
- debug(F101,"tthflow TCGETX","",x);
- if (x > -1) {
- rctsx.x_hflag |= RTSXOFF | CTSXON;
- x = ioctl(ttyfd,TCSETX,&rctsx);
- debug(F100,"tthflow ATTSV ioctl","",x);
- }
- #else
- debug(F100,"tthflow TCGETX not defined","",0);
- x = -1
- #endif /* TCGETX */
- #else
- debug(F100,"tthflow RTSXOFF not defined","",0);
- x = -1;
- #endif /* RTSXOFF */
- } else if (flow == FLO_DTRC) { /* DTR/CD Flow control... */
- debug(F100,"tthflow ATTSV DTR/CD ON","",0);
- #ifdef DTRXOFF
- /* This is straight out of SVID R4 */
- if (ioctl(ttyfd,TCGETX,&rctsx) > -1) {
- rctsx.x_hflag &= ~(DTRXOFF|CDXON);
- x = ioctl(ttyfd,TCSETX,&rctsx);
- }
- #else
- debug(F100,"tthflow ATTSV DTRXOFF not defined","",0);
- x = -1;
- #endif /* DTRXOFF */
- }
- }
- #endif /* CK_SCOUNIX */
- #else /* not System V... */
- #ifdef CK_DTRCTS
- #ifdef LDODTR
- #ifdef LDOCTS
- #ifdef NETCMD
- if (ttpipe) return(0);
- #endif /* NETCMD */
- #ifdef NETPTY
- if (ttpty) return(0);
- #endif /* NETPTY */
- x = LDODTR | LDOCTS; /* Found only on UTEK? */
- if (flow == FLO_DTRT && status) { /* Use hardware flow control */
- if (lmodef) {
- x = ioctl(ttyfd,TIOCLBIS,&x);
- if (x < 0) {
- debug(F100,"hardflow TIOCLBIS error","",0);
- } else {
- lmodef++;
- debug(F100,"hardflow TIOCLBIS ok","",0);
- }
- }
- } else {
- if (lmodef) {
- x = ioctl(ttyfd,TIOCLBIC,&x);
- if (x < 0) {
- debug(F100,"hardflow TIOCLBIC error","",0);
- } else {
- lmodef++;
- debug(F100,"hardflow TIOCLBIC ok","",0);
- }
- }
- }
- #endif /* LDODTR */
- #endif /* LDOCTS */
- #endif /* CK_DTRCTS */
- #endif /* ATTSV */
- #endif /* AIXRS */
- #endif /* SUNOS4 */
- #endif /* QNX */
- #endif /* POSIX_CRTSCTS */
- #endif /* SUNOS41 */
- #else /* OXOS */
- struct termios temp; /* Olivetti X/OS ... */
- #ifdef NETCMD
- if (ttpipe) return(0);
- #endif /* NETCMD */
- #ifdef NETPTY
- if (ttpty) return(0);
- #endif /* NETPTY */
- x = ioctl(ttyfd,TCGETS,&temp);
- if (x == 0) {
- temp.c_cflag &= ~(CRTSCTS|CDTRCTS|CBRKFLOW|CDTRDSR|CRTSDSR);
- if (status) {
- switch (flow) {
- case FLO_RTSC: temp.c_cflag |= CRTSCTS; /* RTS/CTS (hard) */
- break;
- case FLO_DTRT: temp.c_cflag |= CDTRCTS; /* DTR/CTS (hard) */
- break;
- }
- }
- x = ioctl(ttyfd,TCSETS,&temp);
- }
- #endif /* OXOS */
- return(x);
- #endif /* Plan9 */
- }
- /* T T P K T -- Condition the communication line for packets */
- /* or for modem dialing */
- /*
- If called with speed > -1, also set the speed.
- Returns 0 on success, -1 on failure.
- NOTE: the "xflow" parameter is supposed to be the currently selected
- type of flow control, but for historical reasons, this parameter is also
- used to indicate that we are dialing. Therefore, when the true flow
- control setting is needed, we access the external variable "flow", rather
- than trusting our "xflow" argument.
- */
- int
- #ifdef CK_ANSIC
- ttpkt(long speed, int xflow, int parity)
- #else
- ttpkt(speed,xflow,parity) long speed; int xflow, parity;
- #endif /* CK_ANSIC */
- /* ttpkt */ {
- #ifndef NOLOCAL
- int s2;
- int s = -1;
- #endif /* NOLOCAL */
- #ifndef SVORPOSIX
- int x;
- #endif /* SVORPOSIX */
- extern int flow; /* REAL flow-control setting */
- if (ttyfd < 0) return(-1); /* Not open. */
- debug(F101,"ttpkt parity","",parity);
- debug(F101,"ttpkt xflow","",xflow);
- debug(F101,"ttpkt speed","",(int) speed);
- ttprty = parity; /* Let other tt functions see these. */
- ttspeed = speed; /* Make global copy for this module */
- ttpmsk = ttprty ? 0177 : 0377; /* Parity stripping mask */
- #ifdef PARSENSE
- needpchk = ttprty ? 0 : 1; /* Parity check needed? */
- #else
- needpchk = 0;
- #endif /* PARSENSE */
- debug(F101,"ttpkt ttpmsk","",ttpmsk);
- debug(F101,"ttpkt netconn","",netconn);
- #ifdef NETCONN /* No mode-changing for telnet */
- if (netconn) {
- #ifdef TCPSOCKET
- #ifdef TCP_NODELAY
- if (ttnet == NET_TCPB) { /* But turn off Nagle */
- extern int tcp_nodelay;
- nodelay_sav = tcp_nodelay;
- no_delay(1);
- }
- #endif /* TCP_NODELAY */
- #endif /* TCPSOCKET */
- return(0);
- }
- #endif /* NETCONN */
- #ifdef NETCMD
- if (ttpipe) return(0);
- #endif /* NETCMD */
- #ifdef NETPTY
- if (ttpty) return(0);
- #endif /* NETPTY */
- #ifndef Plan9
- if (ttfdflg && !isatty(ttyfd)) return(0);
- #endif /* Plan9 */
- #ifdef COHERENT
- #define SVORPOSIX
- #endif /* COHERENT */
- #ifndef SVORPOSIX /* Berkeley, V7, etc. */
- #ifdef LPASS8
- /*
- For some reason, with BSD terminal drivers, you can't set FLOW to XON/XOFF
- after having previously set it to NONE without closing and reopening the
- device. Unless there's something I overlooked below...
- */
- if (ttflow == FLO_NONE && flow == FLO_XONX && xlocal == 0) {
- debug(F101,"ttpkt executing horrible flow kludge","",0);
- ttclos(0); /* Close it */
- x = 0;
- ttopen(ttnmsv,&x,ttmdm,0); /* Open it again */
- }
- #endif /* LPASS8 */
- #endif /* SVORPOSIX */
- #ifdef COHERENT /* This must be vestigial since we */
- #undef SVORPOSIX /* reverse it a few lines below... */
- #endif /* COHERENT */
- if (xflow != FLO_DIAL && xflow != FLO_DIAX)
- ttflow = xflow; /* Now make this available too. */
- #ifndef NOLOCAL
- if (xlocal) {
- s2 = (int) (speed / 10L); /* Convert bps to cps */
- debug(F101,"ttpkt calling ttsspd","",s2);
- s = ttsspd(s2); /* Check and set the speed */
- debug(F101,"ttpkt ttsspd result","",s);
- carrctl(&ttraw, xflow != FLO_DIAL /* Carrier control */
- && (ttcarr == CAR_ON || (ttcarr == CAR_AUT && ttmdm != 0)));
- tvtflg = 0; /* So ttvt() will work next time */
- }
- #endif /* NOLOCAL */
- #ifdef COHERENT
- #define SVORPOSIX
- #endif /* COHERENT */
- #ifndef SVORPOSIX /* BSD section */
- if (flow == FLO_RTSC || /* Hardware flow control */
- flow == FLO_DTRC ||
- flow == FLO_DTRT) {
- tthflow(flow, 1, &ttraw);
- debug(F100,"ttpkt hard flow, TANDEM off, RAW on","",0);
- ttraw.sg_flags &= ~TANDEM; /* Turn off software flow control */
- ttraw.sg_flags |= RAW; /* Enter raw mode */
- } else if (flow == FLO_NONE) { /* No flow control */
- debug(F100,"ttpkt no flow, TANDEM off, RAW on","",0);
- ttraw.sg_flags &= ~TANDEM; /* Turn off software flow control */
- tthflow(flow, 0, &ttraw); /* Turn off any hardware f/c too */
- ttraw.sg_flags |= RAW; /* Enter raw mode */
- } else if (flow == FLO_KEEP) { /* Keep device's original setting */
- debug(F100,"ttpkt keeping original TANDEM","",0);
- ttraw.sg_flags &= ~TANDEM;
- ttraw.sg_flags |= (ttold.sg_flags & TANDEM);
- /* NOTE: We should also handle hardware flow control here! */
- }
- /* SET FLOW XON/XOFF is in effect, or SET FLOW KEEP resulted in Xon/Xoff */
- if ((flow == FLO_XONX) || (ttraw.sg_flags & TANDEM)) {
- debug(F100,"ttpkt turning on TANDEM","",0);
- ttraw.sg_flags |= TANDEM; /* So ask for it. */
- #ifdef LPASS8 /* Can pass 8-bit data through? */
- /* If the LPASS8 local mode is available, then flow control can always */
- /* be used, even if parity is none and we are transferring 8-bit data. */
- /* But we only need to do all this if Xon/Xoff is requested. */
- /* BUT... this tends not to work through IP or LAT connections, terminal */
- /* servers, telnet, rlogin, etc, so it is currently disabled. */
- x = LPASS8; /* If LPASS8 defined, then */
- debug(F100,"ttpkt executing LPASS8 code","",0);
- if (lmodef) { /* TIOCLBIS must be too. */
- x = ioctl(ttyfd,TIOCLBIS,&x); /* Try to set LPASS8. */
- if (x < 0) {
- debug(F100,"ttpkt TIOCLBIS error","",0);
- } else {
- lmodef++;
- debug(F100,"ttpkt TIOCLBIS ok","",0);
- }
- }
- /*
- But if we use LPASS8 mode, we must explicitly turn off
- terminal interrupts of all kinds.
- */
- #ifdef TIOCGETC /* Not rawmode, */
- if (tcharf && (xlocal == 0)) { /* must turn off */
- tchnoi.t_intrc = -1; /* interrupt character */
- tchnoi.t_quitc = -1; /* and quit character. */
- tchnoi.t_startc = 17; /* Make sure xon */
- tchnoi.t_stopc = 19; /* and xoff not ignored. */
- #ifndef NOBRKC
- tchnoi.t_eofc = -1; /* eof character. */
- tchnoi.t_brkc = -1; /* brk character. */
- #endif /* NOBRKC */
- if (ioctl(ttyfd,TIOCSETC,&tchnoi) < 0) {
- debug(F100,"ttpkt TIOCSETC failed","",0);
- } else {
- tcharf = 1;
- debug(F100,"ttpkt TIOCSETC ok","",0);
- }
- #ifdef COMMENT
- /* only for paranoid debugging */
- if (tcharf) {
- struct tchars foo;
- char tchbuf[100];
- ioctl(0,TIOCGETC,&foo);
- sprintf(tchbuf,
- "intr=%d,quit=%d, start=%d, stop=%d, eof=%d, brk=%d",
- foo.t_intrc, foo.t_quitc, foo.t_startc,
- foo.t_stopc, foo.t_eofc, foo.t_brkc);
- debug(F110,"ttpkt chars",tchbuf,0);
- }
- #endif /* COMMENT */
- }
- ttraw.sg_flags |= CBREAK; /* Needed for unknown reason */
- #endif /* TIOCGETC */
- /* Prevent suspend during packet mode */
- #ifdef TIOCGLTC /* Not rawmode, */
- if (ltcharf && (xlocal == 0)) { /* must turn off */
- ltchnoi.t_suspc = -1; /* suspend character */
- ltchnoi.t_dsuspc = -1; /* and delayed suspend character */
- if (ioctl(ttyfd,TIOCSLTC,&tchnoi) < 0) {
- debug(F100,"ttpkt TIOCSLTC failed","",0);
- } else {
- ltcharf = 1;
- debug(F100,"ttpkt TIOCSLTC ok","",0);
- }
- }
- #endif /* TIOCGLTC */
- #else /* LPASS8 not defined */
- /* Previously, BSD-based implementations always */
- /* used rawmode for packets. Now, we use rawmode only if parity is NONE. */
- /* This allows the flow control requested above to actually work, but only */
- /* if the user asks for parity (which also means they get 8th-bit quoting). */
- if (parity) { /* If parity, */
- ttraw.sg_flags &= ~RAW; /* use cooked mode */
- #ifdef COMMENT
- /* WHY??? */
- if (xlocal)
- #endif /* COMMENT */
- ttraw.sg_flags |= CBREAK;
- debug(F101,"ttpkt cooked, cbreak, parity","",parity);
- #ifdef TIOCGETC /* Not rawmode, */
- if (tcharf && (xlocal == 0)) { /* must turn off */
- tchnoi.t_intrc = -1; /* interrupt character */
- tchnoi.t_quitc = -1; /* and quit character. */
- tchnoi.t_startc = 17; /* Make sure xon */
- tchnoi.t_stopc = 19; /* and xoff not ignored. */
- #ifndef NOBRKC
- tchnoi.t_eofc = -1; /* eof character. */
- tchnoi.t_brkc = -1; /* brk character. */
- #endif /* NOBRKC */
- if (ioctl(ttyfd,TIOCSETC,&tchnoi) < 0) {
- debug(F100,"ttpkt TIOCSETC failed","",0);
- } else {
- tcharf = 1;
- debug(F100,"ttpkt TIOCSETC ok","",0);
- }
- }
- #endif /* TIOCGETC */
- #ifdef TIOCGLTC /* Not rawmode, */
- /* Prevent suspend during packet mode */
- if (ltcharf && (xlocal == 0)) { /* must turn off */
- ltchnoi.t_suspc = -1; /* suspend character */
- ltchnoi.t_dsuspc = -1; /* and delayed suspend character */
- if (ioctl(ttyfd,TIOCSLTC,&tchnoi) < 0) {
- debug(F100,"ttpkt TIOCSLTC failed","",0);
- } else {
- ltcharf = 1;
- debug(F100,"ttpkt TIOCSLTC ok","",0);
- }
- }
- #endif /* TIOCGLTC */
- } else { /* If no parity, */
- ttraw.sg_flags |= RAW; /* must use 8-bit raw mode. */
- debug(F101,"ttpkt setting rawmode, parity","",parity);
- }
- #endif /* LPASS8 */
- } /* End of Xon/Xoff section */
- /* Don't echo, don't map CR to CRLF on output, don't fool with case */
- #ifdef LCASE
- ttraw.sg_flags &= ~(ECHO|CRMOD|LCASE);
- #else
- ttraw.sg_flags &= ~(ECHO|CRMOD);
- #endif /* LCASE */
- #ifdef TOWER1
- ttraw.sg_flags &= ~ANYP; /* Must set this on old Towers */
- #endif /* TOWER1 */
- #ifdef BELLV10
- if (ioctl(ttyfd,TIOCSETP,&ttraw) < 0) /* Set the new modes. */
- return(-1);
- #else
- errno = 0;
- if (stty(ttyfd,&ttraw) < 0) { /* Set the new modes. */
- debug(F101,"ttpkt stty failed","",errno);
- return(-1);
- }
- #endif /* BELLV10 */
- debug(F100,"ttpkt stty ok","",0);
- #ifdef sony_news
- x = xlocal ? km_ext : km_con; /* Put line in ASCII mode. */
- if (x != -1) { /* Make sure we know original modes. */
- x &= ~KM_TTYPE;
- x |= KM_ASCII;
- if (ioctl(ttyfd,TIOCKSET, &x) < 0) {
- perror("ttpkt can't set ASCII mode");
- debug(F101,"ttpkt error setting ASCII mode","",x);
- return(-1);
- }
- }
- debug(F100,"ttpkt set ASCII mode ok","",0);
- #endif /* sony_news */
- if (xlocal == 0) { /* Turn this off so we can read */
- signal(SIGINT,SIG_IGN); /* Ctrl-C chars typed at console */
- sigint_ign = 1;
- }
- tvtflg = 0; /* So ttvt() will work next time */
- debug(F100,"ttpkt success","",0);
- return(0);
- #endif /* Not ATTSV or POSIX */
- /* AT&T UNIX and POSIX */
- #ifdef COHERENT
- #define SVORPOSIX
- #endif /* COHERENT */
- #ifdef SVORPOSIX
- if (flow == FLO_XONX) { /* Xon/Xoff */
- ttraw.c_iflag |= (IXON|IXOFF);
- tthflow(flow, 0, &ttraw);
- } else if (flow == FLO_NONE) { /* None */
- /* NOTE: We should also turn off hardware flow control here! */
- ttraw.c_iflag &= ~(IXON|IXOFF);
- tthflow(flow, 0, &ttraw);
- } else if (flow == FLO_KEEP) { /* Keep */
- ttraw.c_iflag &= ~(IXON|IXOFF); /* Turn off Xon/Xoff flags */
- ttraw.c_iflag |= (ttold.c_iflag & (IXON|IXOFF)); /* OR in old ones */
- /* NOTE: We should also handle hardware flow control here! */
- #ifdef POSIX_CRTSCTS
- /* In Linux case, we do this, which is unlikely to be portable */
- ttraw.c_cflag &= ~CRTSCTS; /* Turn off RTS/CTS flag */
- ttraw.c_cflag |= (ttold.c_cflag & CRTSCTS); /* OR in old one */
- #endif /* POSIX_CRTSCTS */
- } else if (flow == FLO_RTSC || /* Hardware */
- flow == FLO_DTRC ||
- flow == FLO_DTRT) {
- ttraw.c_iflag &= ~(IXON|IXOFF); /* (190) */
- tthflow(flow, 1, &ttraw);
- }
- ttraw.c_lflag &= ~(ICANON|ECHO);
- ttraw.c_lflag &= ~ISIG; /* Do NOT check for interrupt chars */
- #ifndef OXOS
- #ifdef QNX
- if (flow != FLO_RTSC && flow != FLO_DTRC && flow != FLO_DTRT)
- #endif /* QNX */
- #ifndef COHERENT
- ttraw.c_lflag &= ~IEXTEN; /* Turn off ^O/^V processing */
- #endif /* COHERENT */
- #else /* OXOS */
- ttraw.c_cc[VDISCARD] = ttraw.c_cc[VLNEXT] = CDISABLE;
- #endif /* OXOS */
- ttraw.c_lflag |= NOFLSH; /* Don't flush */
- ttraw.c_iflag |= IGNPAR; /* Ignore parity errors */
- #ifdef ATTSV
- #ifdef BSD44
- ttraw.c_iflag &= ~(IGNBRK|INLCR|IGNCR|ICRNL|INPCK|ISTRIP|IXANY);
- #else
- ttraw.c_iflag &= ~(IGNBRK|INLCR|IGNCR|ICRNL|IUCLC|INPCK|ISTRIP|IXANY);
- #endif /* BSD44 */
- #else /* POSIX */
- ttraw.c_iflag &= ~(IGNBRK|INLCR|IGNCR|ICRNL|INPCK|ISTRIP);
- #endif /* ATTSV */
- ttraw.c_oflag &= ~OPOST;
- ttraw.c_cflag &= ~(CSIZE);
- ttraw.c_cflag |= (CS8|CREAD|HUPCL);
- #ifdef HWPARITY
- if (hwparity && xlocal) { /* Hardware parity & stop bits */
- #ifdef CSTOPB
- if (stopbits == 2) {
- ttraw.c_cflag |= CSTOPB; /* 2 stop bits */
- debug(F100,"ttpkt 2 stopbits","",0);
- } else if (stopbits == 1) {
- ttraw.c_cflag &= ~(CSTOPB); /* 1 stop bit */
- debug(F100,"ttpkt 1 stopbit","",0);
- }
- #else
- debug(F101,"ttpkt CSTOPB not def","",stopbits);
- #endif /* CSTOPB */
- ttraw.c_cflag |= PARENB; /* Enable parity */
- switch (hwparity) {
- case 'e': /* Even */
- ttraw.c_cflag &= ~(PARODD);
- debug(F100,"ttpkt 8 bits + even parity","",0);
- break;
- case 'o': /* Odd */
- ttraw.c_cflag |= PARODD;
- debug(F100,"ttpkt 8 bits + odd parity","",0);
- break;
- case 'm': /* Mark */
- case 's': /* Space */
- debug(F100,"ttpkt 8 bits + invalid parity","",0);
- break;
- }
- } else { /* We handle parity ourselves */
- #endif /* HWPARITY */
- ttraw.c_cflag &= ~(PARENB); /* Don't enable parity */
- #ifdef HWPARITY
- }
- #endif /* HWPARITY */
- #ifdef IX370
- ttraw.c_cc[4] = 48; /* So Series/1 doesn't interrupt on every char */
- ttraw.c_cc[5] = 1;
- #else
- #ifndef VEOF /* for DGUX this is VEOF, not VMIN */
- ttraw.c_cc[4] = 1; /* [VMIN] return max of this many characters or */
- #else
- #ifndef OXOS
- #ifdef VMIN
- ttraw.c_cc[VMIN] = 1;
- #endif /* VMIN */
- #else /* OXOS */
- ttraw.c_min = 1;
- #endif /* OXOS */
- #endif /* VEOF */
- #ifndef VEOL /* for DGUX this is VEOL, not VTIME */
- ttraw.c_cc[5] = 0; /* [VTIME] when this many secs/10 expire w/no input */
- #else
- #ifndef OXOS
- #ifdef VTIME
- ttraw.c_cc[VTIME] = 0;
- #endif /* VTIME */
- #else /* OXOS */
- ttraw.c_time = 0;
- #endif /* OXOS */
- #endif /* VEOL */
- #endif /* IX370 */
- #ifdef VINTR /* Turn off interrupt character */
- if (xlocal == 0) /* so ^C^C can break us out of */
- ttraw.c_cc[VINTR] = 0; /* packet mode. */
- #endif /* VINTR */
- #ifdef Plan9
- if (p9ttyparity('n') < 0)
- return -1;
- #else
- #ifdef BSD44ORPOSIX
- #ifdef BEOSORBEBOX
- ttraw.c_cc[VMIN] = 0; /* DR7 can only poll. */
- #endif /* BEOSORBEBOX */
- debug(F100,"ttpkt calling tcsetattr(TCSETAW)","",0);
- errno = 0;
- if (tcsetattr(ttyfd,TCSADRAIN,&ttraw) < 0) {
- debug(F101,"ttpkt BSD44ORPOSIX tcsetattr(TCSADRAIN) fail","",errno);
- return(-1);
- }
- #else /* BSD44ORPOSIX */
- errno = 0;
- debug(F100,"ttpkt calling ioctl(TCSETAW)","",0);
- if (ioctl(ttyfd,TCSETAW,&ttraw) < 0) { /* set new modes . */
- debug(F100,"ttpkt ATTSV ioctl(TCSETAW) fail","",errno);
- return(-1);
- }
- #endif /* BSD44ORPOSIX */
- #endif /* Plan9 */
- tvtflg = 0;
- debug(F100,"ttpkt success","",0);
- return(0);
- #endif /* ATTSV */
- #ifdef COHERENT
- #undef SVORPOSIX
- #endif /* COHERENT */
- }
- /* T T S E T F L O W -- Set flow control immediately. */
- #ifdef COHERENT
- #define SVORPOSIX
- #endif /* COHERENT */
- int
- ttsetflow(flow) int flow; {
- if (ttyfd < 0) /* Communications channel must open */
- return(-1);
- debug(F101,"ttsetflow","",flow);
- #ifdef NETCMD
- if (ttpipe) return(0);
- #endif /* NETCMD */
- #ifdef NETPTY
- if (ttpty) return(0);
- #endif /* NETPTY */
- #ifdef COMMENT
- /* This seems to hurt... */
- if (flow == FLO_KEEP)
- return(0);
- #endif /* COMMENT */
- if (flow == FLO_RTSC || /* Hardware flow control... */
- flow == FLO_DTRC ||
- flow == FLO_DTRT) {
- tthflow(flow, 1, &ttraw);
- #ifndef SVORPOSIX
- ttraw.sg_flags &= ~TANDEM; /* Turn off software flow control */
- #else
- ttraw.c_iflag &= ~(IXON|IXOFF);
- #endif /* SVORPOSIX */
- } else if (flow == FLO_XONX) { /* Xon/Xoff... */
- #ifndef SVORPOSIX
- ttraw.sg_flags |= TANDEM;
- #else
- ttraw.c_iflag |= (IXON|IXOFF);
- #endif /* SVORPOSIX */
- tthflow(FLO_RTSC, 0, &ttraw); /* Turn off hardware flow control */
- } else if (flow == FLO_NONE) { /* No flow control */
- #ifndef SVORPOSIX
- ttraw.sg_flags &= ~TANDEM; /* Turn off software flow control */
- #else
- ttraw.c_iflag &= ~(IXON|IXOFF);
- #endif /* SVORPOSIX */
- tthflow(FLO_RTSC, 0, &ttraw); /* Turn off any hardware f/c too */
- }
- /* Set the new modes... */
- #ifndef SVORPOSIX /* BSD and friends */
- #ifdef BELLV10
- if (ioctl(ttyfd,TIOCSETP,&ttraw) < 0)
- return(-1);
- #else
- #ifndef MINIX2
- if (stty(ttyfd,&ttraw) < 0)
- return(-1);
- #endif /* MINIX2 */
- #endif /* BELLV10 */
- #else
- #ifdef BSD44ORPOSIX /* POSIX */
- if (tcsetattr(ttyfd,TCSADRAIN,&ttraw) < 0)
- return(-1);
- #else /* System V */
- if (ioctl(ttyfd,TCSETAW,&ttraw) < 0)
- return(-1);
- #endif /* BSD44ORPOSIX */
- #endif /* SVORPOSIX */
- return(0);
- }
- #ifdef COHERENT
- #undef SVORPOSIX
- #endif /* COHERENT */
- /* T T V T -- Condition communication device for use as virtual terminal. */
- int
- #ifdef CK_ANSIC
- ttvt(long speed, int flow)
- #else
- ttvt(speed,flow) long speed; int flow;
- #endif /* CK_ANSIC */
- /* ttvt */ {
- int s, s2;
- debug(F101,"ttvt ttyfd","",ttyfd);
- debug(F101,"ttvt tvtflg","",tvtflg);
- debug(F101,"ttvt speed","",speed);
- debug(F101,"ttvt flow","",flow);
- ttpmsk = 0xff;
- #ifdef NOLOCAL
- return(conbin((char)escchr));
- #else
- if (ttyfd < 0) { /* Not open. */
- if (ttchk() < 0)
- return(-1);
- else /* But maybe something buffered. */
- return(0);
- }
- #ifdef NETCMD
- if (ttpipe) return(0);
- #endif /* NETCMD */
- #ifdef NETPTY
- if (ttpty) return(0);
- #endif /* NETPTY */
- #ifdef NETCONN
- if (netconn) {
- tvtflg = 1; /* Network connections... */
- debug(F100,"ttvt network connection, skipping...","",0);
- #ifdef TCPSOCKET
- #ifdef TCP_NODELAY
- {
- extern int tcp_nodelay;
- if (ttnet == NET_TCPB) {
- if (nodelay_sav > -1) {
- no_delay(nodelay_sav);
- nodelay_sav = -1;
- }
- }
- }
- #endif /* TCP_NODELAY */
- #endif /* TCPSOCKET */
- return(0); /* ... require no special setup */
- }
- #endif /* NETCONN */
- if (tvtflg != 0 && speed == ttspeed && flow == ttflow && ttcarr == curcarr)
- {
- debug(F100,"ttvt modes already set, skipping...","",0);
- return(0); /* Already been called. */
- }
- if (ttfdflg
- #ifndef Plan9
- && !isatty(ttyfd)
- #endif /* Plan9 */
- ) {
- debug(F100,"ttvt using external fd, skipping...","",0);
- return(0);
- }
- debug(F100,"ttvt setting modes...","",0);
- if (xlocal) { /* For external lines... */
- s2 = (int) (speed / 10L);
- s = ttsspd(s2); /* Check/set the speed */
- carrctl(&tttvt, flow != FLO_DIAL /* Do carrier control */
- && (ttcarr == CAR_ON || (ttcarr == CAR_AUT && ttmdm != 0)));
- } else
- s = s2 = -1;
- #ifdef COHERENT
- #define SVORPOSIX
- #endif /* COHERENT */
- #ifndef SVORPOSIX
- /* Berkeley, V7, etc */
- if (flow == FLO_RTSC || /* Hardware flow control */
- flow == FLO_DTRC ||
- flow == FLO_DTRT) {
- tthflow(flow, 1, &tttvt);
- debug(F100,"ttvt hard flow, TANDEM off","",0);
- tttvt.sg_flags &= ~TANDEM; /* Turn off software flow control */
- } else if (flow == FLO_XONX) { /* Xon/Xoff flow control */
- debug(F100,"ttvt TANDEM on","",0);
- tttvt.sg_flags |= TANDEM; /* Ask for it. */
- tthflow(flow, 0, &tttvt); /* Turn off hardware f/c */
- } else if (flow == FLO_NONE) {
- debug(F100,"ttvt no flow, TANDEM off, RAW on","",0);
- tttvt.sg_flags &= ~TANDEM; /* Turn off software flow control */
- tthflow(flow, 0, &tttvt); /* Turn off any hardware f/c too */
- tttvt.sg_flags |= RAW; /* Enter raw mode */
- } else if (flow == FLO_KEEP) { /* Keep device's original setting */
- debug(F100,"ttvt keeping original TANDEM","",0);
- tttvt.sg_flags &= ~TANDEM;
- tttvt.sg_flags |= (ttold.sg_flags & TANDEM);
- /* NOTE: We should also handle hardware flow control here! */
- }
- tttvt.sg_flags |= RAW; /* Raw mode in all cases */
- #ifdef TOWER1
- tttvt.sg_flags &= ~(ECHO|ANYP); /* No echo or parity */
- #else
- tttvt.sg_flags &= ~ECHO; /* No echo */
- #endif /* TOWER1 */
- #ifdef BELLV10
- if (ioctl(ttyfd,TIOCSETP,&tttvt) < 0) /* Set the new modes */
- return(-1);
- #else
- if (stty(ttyfd,&tttvt) < 0) /* Set the new modes */
- return(-1);
- #endif /* BELLV10 */
- #else /* It is ATTSV or POSIX */
- if (flow == FLO_XONX) { /* Software flow control */
- tttvt.c_iflag |= (IXON|IXOFF); /* On if requested. */
- tthflow(flow, 0, &tttvt); /* Turn off hardware f/c */
- debug(F100,"ttvt SVORPOSIX flow XON/XOFF","",0);
- } else if (flow == FLO_NONE) { /* NONE */
- tttvt.c_iflag &= ~(IXON|IXOFF); /* Turn off Xon/Xoff */
- tthflow(flow, 0, &tttvt); /* Turn off hardware f/c */
- debug(F100,"ttvt SVORPOSIX flow NONE","",0);
- } else if (flow == FLO_KEEP) {
- tttvt.c_iflag &= ~(IXON|IXOFF); /* Turn off Xon/Xoff flags */
- tttvt.c_iflag |= (ttold.c_iflag & (IXON|IXOFF)); /* OR in old ones */
- #ifdef POSIX_CRTSCTS
- tttvt.c_cflag &= ~CRTSCTS; /* Turn off RTS/CTS flag */
- tttvt.c_cflag |= (ttold.c_cflag & CRTSCTS); /* OR in old one */
- #endif /* POSIX_CRTSCTS */
- debug(F100,"ttvt SVORPOSIX flow KEEP","",0);
- } else if (flow == FLO_RTSC || /* Hardware flow control */
- flow == FLO_DTRC ||
- flow == FLO_DTRT) {
- tttvt.c_iflag &= ~(IXON|IXOFF); /* (196) */
- tthflow(flow, 1, &tttvt);
- debug(F100,"ttvt SVORPOSIX flow HARD","",0);
- }
- #ifndef OXOS
- #ifdef COHERENT
- tttvt.c_lflag &= ~(ISIG|ICANON|ECHO);
- #else
- tttvt.c_lflag &= ~(ISIG|ICANON|ECHO|IEXTEN);
- #endif /* COHERENT */
- #ifdef QNX
- /* Needed for hwfc */
- if (flow == FLO_RTSC || flow == FLO_DTRC || flow == FLO_DTRT)
- tttvt.c_lflag |= IEXTEN;
- #endif /* QNX */
- #else /* OXOS */
- tttvt.c_lflag &= ~(ISIG|ICANON|ECHO);
- tttvt.c_cc[VDISCARD] = tttvt.c_cc[VLNEXT] = CDISABLE;
- #endif /* OXOS */
- tttvt.c_iflag |= (IGNBRK|IGNPAR);
- /* Parity */
- #ifdef HWPARITY
- if (hwparity && xlocal) { /* Hardware parity */
- #ifdef CSTOPB
- if (stopbits == 2) {
- ttraw.c_cflag |= CSTOPB; /* 2 stop bits */
- debug(F100,"ttpkt 2 stopbits","",0);
- } else if (stopbits == 1) {
- ttraw.c_cflag &= ~(CSTOPB); /* 1 stop bit */
- debug(F100,"ttpkt 1 stopbit","",0);
- }
- #endif /* CSTOPB */
- tttvt.c_cflag |= PARENB; /* Enable parity */
- switch (hwparity) {
- case 'e': /* Even */
- tttvt.c_cflag &= ~(PARODD);
- debug(F100,"ttvt 8 bits + even parity","",0);
- break;
- case 'o': /* Odd */
- tttvt.c_cflag |= PARODD;
- debug(F100,"ttvt 8 bits + odd parity","",0);
- break;
- case 'm': /* Mark */
- case 's': /* Space */
- debug(F100,"ttvt 8 bits + invalid parity","",0);
- break;
- }
- } else { /* We handle parity ourselves */
- #endif /* HWPARITY */
- tttvt.c_cflag &= ~(PARENB); /* Don't enable parity */
- #ifdef HWPARITY
- }
- #endif /* HWPARITY */
- #ifdef ATTSV
- #ifdef BSD44
- /* Things not to do... */
- tttvt.c_iflag &= ~(INLCR|IGNCR|ICRNL|INPCK|ISTRIP|IXANY);
- #else
- tttvt.c_iflag &= ~(INLCR|IGNCR|ICRNL|IUCLC|INPCK|ISTRIP|IXANY);
- #endif /* BSD44 */
- #else /* POSIX */
- tttvt.c_iflag &= ~(INLCR|IGNCR|ICRNL|INPCK|ISTRIP);
- #endif /* ATTSV */
- tttvt.c_cflag &= ~(CSIZE); /* Zero out the char size field */
- tttvt.c_cflag |= (CS8|CREAD|HUPCL); /* Char size 8, enable receiver, hup */
- tttvt.c_oflag &= ~OPOST; /* Don't postprocess output */
- #ifndef VEOF /* DGUX termio has VEOF at entry 4, see comment above */
- tttvt.c_cc[4] = 1;
- #else
- #ifndef OXOS
- #ifdef VMIN
- tttvt.c_cc[VMIN] = 1;
- #endif /* VMIN */
- #else /* OXOS */
- tttvt.c_min = 1;
- #endif /* OXOS */
- #endif /* VEOF */
- #ifndef VEOL /* DGUX termio has VEOL at entry 5, see comment above */
- tttvt.c_cc[5] = 0;
- #else
- #ifndef OXOS
- #ifdef VTIME
- tttvt.c_cc[VTIME] = 0;
- #endif /* VTIME */
- #else /* OXOS */
- tttvt.c_time = 0;
- #endif /* OXOS */
- #endif /* VEOL */
- #ifdef Plan9
- if (p9ttyparity('n') < 0)
- return -1;
- #else
- #ifdef BSD44ORPOSIX
- #ifdef BEOSORBEBOX
- tttvt.c_cc[VMIN] = 0; /* DR7 can only poll. */
- #endif /* BEOSORBEBOX */
- if (tcsetattr(ttyfd,TCSADRAIN,&tttvt) < 0) return(-1);
- #else /* ATTSV */
- if (ioctl(ttyfd,TCSETAW,&tttvt) < 0) return(-1); /* set new modes . */
- #endif /* BSD44ORPOSIX */
- #endif /* Plan9 */
- #endif /* ATTSV */
- ttspeed = speed; /* Done, remember how we were */
- ttflow = flow; /* called, so we can decide how to */
- tvtflg = 1; /* respond next time. */
- debug(F101,"ttvt done","",tvtflg);
- return(0);
- #ifdef COHERENT
- #undef SVORPOSIX
- #endif /* COHERENT */
- #endif /* NOLOCAL */
- }
- #ifndef NOLOCAL
- /* Serial speed department . . . */
- /*
- Plan 9's native speed setting interface lets you set anything you like,
- but will fail if the hardware doesn't like it, so we allow all the common
- speeds.
- */
- #ifdef Plan9
- #ifndef B50
- #define B50 50
- #endif /* B50 */
- #ifndef B75
- #define B75 75
- #endif /* B75 */
- #ifndef B110
- #define B110 110
- #endif /* B110 */
- #ifndef B134
- #define B134 134
- #endif /* B134 */
- #ifndef B200
- #define B200 200
- #endif /* B200 */
- #ifndef B300
- #define B300 300
- #endif /* B300 */
- #ifndef B1200
- #define B1200 1200
- #endif /* B1200 */
- #ifndef B1800
- #define B1800 1800
- #endif /* B1800 */
- #ifndef B2400
- #define B2400 2400
- #endif /* B2400 */
- #ifndef B4800
- #define B4800 4800
- #endif /* B4800 */
- #ifndef B9600
- #define B9600 9600
- #endif /* B9600 */
- #ifndef B14400
- #define B14400 14400
- #endif /* B14400 */
- #ifndef B19200
- #define B19200 19200
- #endif /* B19200 */
- #ifndef B28800
- #define B28800 28800
- #endif /* B28800 */
- #ifndef B38400
- #define B38400 38400
- #endif /* B38400 */
- #ifndef B57600
- #define B57600 57600
- #endif /* B57600 */
- #ifndef B76800
- #define B76800 76800
- #endif /* B76800 */
- #ifndef B115200
- #define B115200 115200
- #endif /* B115200 */
- #ifndef B230400
- #define B230400 230400
- #endif /* B230400 */
- #ifndef B460800
- #define B460800 460800
- #endif /* B460800 */
- #ifndef B921600
- #define B921600 921600
- #endif /* B921600 */
- #endif /* Plan9 */
- /* T T S S P D -- Checks and sets transmission rate. */
- /* Call with speed in characters (not bits!) per second. */
- /* Returns -1 on failure, 0 if it did nothing, 1 if it changed the speed. */
- #ifdef USETCSETSPEED
- /*
- The tcsetspeed() / tcgetspeed() interface lets you pass any number at all
- to be used as a speed to be set, rather than forcing a choice from a
- predefined list. It seems to be peculiar to UnixWare 7.
- These are the function codes to be passed to tc[gs]etspeed(),
- but for some reason they don't seem to be picked up from termios.h.
- */
- #ifndef TCS_ALL
- #define TCS_ALL 0
- #endif /* TCS_ALL */
- #ifndef TCS_IN
- #define TCS_IN 1
- #endif /* TCS_IN */
- #ifndef TCS_OUT
- #define TCS_OUT 2
- #endif /* TCS_OUT */
- #endif /* USETCSETSPEED */
- int
- ttsspd(cps) int cps; {
- int x;
- #ifdef POSIX
- /* Watch out, speed_t should be unsigned, so don't compare with -1, etc... */
- speed_t
- #else
- int
- #endif /* POSIX */
- s, s2;
- int ok = 1; /* Speed check result, assume ok */
- #ifdef OLINUXHISPEED
- unsigned int spd_flags = 0;
- struct serial_struct serinfo;
- #endif /* OLINUXHISPEED */
- debug(F101,"ttsspd cps","",cps);
- debug(F101,"ttsspd ttyfd","",ttyfd);
- debug(F101,"ttsspd xlocal","",xlocal);
- if (ttyfd < 0 || xlocal == 0 ) /* Don't set speed on console */
- return(0);
- #ifdef NETCONN
- if (netconn)
- return(0);
- #endif /* NETCONN */
- #ifdef NETCMD
- if (ttpipe) return(0);
- #endif /* NETCMD */
- #ifdef NETPTY
- if (ttpty) return(0);
- #endif /* NETPTY */
- if (cps < 0) return(-1);
- s = s2 = 0; /* NB: s and s2 might be unsigned */
- #ifdef USETCSETSPEED
- s = cps * 10L;
- x = tcgetattr(ttyfd,&ttcur); /* Get current speed */
- debug(F101,"ttsspd tcgetattr","",x);
- if (x < 0)
- return(-1);
- debug(F101,"ttsspd TCSETSPEED speed","",s);
- errno = 0;
- if (s == 8880L) { /* 75/1200 split speed requested */
- tcsetspeed(TCS_IN, &ttcur, 1200L);
- tcsetspeed(TCS_OUT, &ttcur, 75L);
- } else
- tcsetspeed(TCS_ALL, &ttcur, s); /* Put new speed in structs */
- #ifdef DEBUG
- if (errno & deblog) {
- debug(F101,"ttsspd TCSETSPEED errno","",errno);
- }
- #endif /* DEBUG */
- #ifdef COMMENT
- tcsetspeed(TCS_ALL, &ttraw, s);
- tcsetspeed(TCS_ALL, &tttvt, s);
- tcsetspeed(TCS_ALL, &ttold, s);
- #else
- if (s == 8880L) { /* 75/1200 split speed requested */
- tcsetspeed(TCS_IN, &ttraw, 1200L);
- tcsetspeed(TCS_OUT, &ttraw, 75L);
- tcsetspeed(TCS_IN, &tttvt, 1200L);
- tcsetspeed(TCS_OUT, &tttvt, 75L);
- tcsetspeed(TCS_IN, &ttold, 1200L);
- tcsetspeed(TCS_OUT, &ttold, 75L);
- } else {
- tcsetspeed(TCS_ALL, &ttraw, s);
- tcsetspeed(TCS_ALL, &tttvt, s);
- tcsetspeed(TCS_ALL, &ttold, s);
- }
- #endif /* COMMENT */
- x = tcsetattr(ttyfd,TCSADRAIN,&ttcur); /* Set the speed */
- debug(F101,"ttsspd tcsetattr","",x);
- if (x < 0)
- return(-1);
- #else /* Not USETCSETSPEED */
- #ifdef MINIX2 /* Hack alert */
- #define MINIX /* Use pre-2.0 speed selection for Minix 2.0 as well */
- #endif /* MINIX2 */
- /* First check that the given speed is valid. */
- switch (cps) {
- #ifndef MINIX
- case 0: s = B0; break;
- case 5: s = B50; break;
- case 7: s = B75; break;
- #endif /* MINIX */
- case 11: s = B110; break;
- #ifndef MINIX
- case 13: s = B134; break;
- case 15: s = B150; break;
- case 20: s = B200; break;
- #endif /* MINIX */
- case 30: s = B300; break;
- #ifndef MINIX
- case 60: s = B600; break;
- #endif /* MINIX */
- case 120: s = B1200; break;
- #ifndef MINIX
- case 180: s = B1800; break;
- #endif /* MINIX */
- case 240: s = B2400; break;
- case 480: s = B4800; break;
- #ifndef MINIX
- case 888: s = B75; s2 = B1200; break; /* 888 = 75/1200 split speed */
- #endif /* MINIX */
- #ifdef B7200
- case 720: s = B7200; break;
- #endif /* B7200 */
- case 960: s = B9600; break;
- #ifdef B14400
- case 1440: s = B14400; break;
- #endif /* B14400 */
- #ifdef B19200
- case 1920: s = B19200; break;
- #else
- #ifdef EXTA
- case 1920: s = EXTA; break;
- #endif /* EXTA */
- #endif /* B19200 */
- #ifdef B28800
- case 2880: s = B28800; break;
- #endif /* B28800 */
- #ifdef B38400
- case 3840: s = B38400;
- #ifdef OLINUXHISPEED
- spd_flags = ~ASYNC_SPD_MASK; /* Nonzero, but zero flags */
- #endif /* OLINUXHISPEED */
- break;
- #else /* B38400 not defined... */
- #ifdef EXTB
- case 3840: s = EXTB; break;
- #endif /* EXTB */
- #endif /* B38400 */
- #ifdef HPUX
- #ifdef _B57600
- case 5760: s = _B57600; break;
- #endif /* _B57600 */
- #ifdef _B115200
- case 11520: s = _B115200; break;
- #endif /* _B115200 */
- #else
- #ifdef OLINUXHISPEED
- /*
- This bit from <carlo@sg.tn.tudelft.nl>:
- "Only note to make is maybe this: When the ASYNC_SPD_CUST flags are set then
- setting the speed to 38400 will set the custom speed (and ttgspd returns
- 38400), but speeds 57600 and 115200 won't work any more because I didn't
- want to mess up the speed flags when someone is doing sophisticated stuff
- like custom speeds..."
- */
- case 5760: s = B38400; spd_flags = ASYNC_SPD_HI; break;
- case 11520: s = B38400; spd_flags = ASYNC_SPD_VHI; break;
- #else
- #ifdef B57600
- case 5760: s = B57600; break;
- #endif /* B57600 */
- #ifdef B76800
- case 7680: s = B76800; break;
- #endif /* B76800 */
- #ifdef B115200
- case 11520: s = B115200; break;
- #endif /* B115200 */
- #endif /* OLINUXHISPEED */
- #ifdef B153600
- case 15360: s = B153600; break;
- #endif /* B153600 */
- #ifdef B230400
- case 23040: s = B230400; break;
- #endif /* B230400 */
- #ifdef B307200
- case 30720: s = B307200; break;
- #endif /* B307200 */
- #ifdef B460800
- case 46080: s = B460800; break;
- #endif /* 460800 */
- #ifdef B921600
- case 92160: s = B921600; break;
- #endif /* B921600 */
- #endif /* HPUX */
- default:
- ok = 0; /* Good speed not found, so not ok */
- break;
- }
- debug(F101,"ttsspd ok","",ok);
- debug(F101,"ttsspd s","",s);
- if (!ok) {
- debug(F100,"ttsspd fails","",0);
- return(-1);
- } else {
- if (!s2) s2 = s; /* Set input speed */
- #ifdef Plan9
- if (p9ttsspd(cps) < 0)
- return(-1);
- #else
- #ifdef BSD44ORPOSIX
- x = tcgetattr(ttyfd,&ttcur); /* Get current speed */
- debug(F101,"ttsspd tcgetattr","",x);
- if (x < 0)
- return(-1);
- #ifdef OLINUXHISPEED
- debug(F101,"ttsspd spd_flags","",spd_flags);
- if (spd_flags && spd_flags != ASYNC_SPD_CUST) {
- if (ioctl(ttyfd, TIOCGSERIAL, &serinfo) < 0) {
- debug(F100,"ttsspd: TIOCGSERIAL failed","",0);
- return(-1);
- } else debug(F100,"ttsspd: TIOCGSERIAL ok","",0);
- serinfo.flags &= ~ASYNC_SPD_MASK;
- serinfo.flags |= (spd_flags & ASYNC_SPD_MASK);
- if (ioctl(ttyfd, TIOCSSERIAL, &serinfo) < 0)
- return(-1);
- }
- #endif /* OLINUXHISPEED */
- cfsetospeed(&ttcur,s);
- cfsetispeed(&ttcur,s2);
- cfsetospeed(&ttraw,s);
- cfsetispeed(&ttraw,s2);
- cfsetospeed(&tttvt,s);
- cfsetispeed(&tttvt,s2);
- cfsetospeed(&ttold,s);
- cfsetispeed(&ttold,s2);
- x = tcsetattr(ttyfd,TCSADRAIN,&ttcur);
- debug(F101,"ttsspd tcsetattr","",x);
- if (x < 0) return(-1);
- #else
- #ifdef ATTSV
- if (cps == 888) return(-1); /* No split speeds, sorry. */
- x = ioctl(ttyfd,TCGETA,&ttcur);
- debug(F101,"ttsspd TCGETA ioctl","",x);
- if (x < 0) return(-1);
- ttcur.c_cflag &= ~CBAUD;
- ttcur.c_cflag |= s;
- tttvt.c_cflag &= ~CBAUD;
- tttvt.c_cflag |= s;
- ttraw.c_cflag &= ~CBAUD;
- ttraw.c_cflag |= s;
- ttold.c_cflag &= ~CBAUD;
- ttold.c_cflag |= s;
- x = ioctl(ttyfd,TCSETAW,&ttcur);
- debug(F101,"ttsspd TCSETAW ioctl","",x);
- if (x < 0) return(-1);
- #else
- #ifdef BELLV10
- x = ioctl(ttyfd,TIOCGDEV,&tdcur);
- debug(F101,"ttsspd TIOCGDEV ioctl","",x);
- if (x < 0) return(-1);
- tdcur.ispeed = s2;
- tdcur.ospeed = s;
- errno = 0;
- ok = ioctl(ttyfd,TIOCSDEV,&tdcur);
- debug(F101,"ttsspd BELLV10 ioctl","",ok);
- if (ok < 0) {
- perror(ttnmsv);
- debug(F101,"ttsspd BELLV10 errno","",ok);
- return(-1);
- }
- #else
- x = gtty(ttyfd,&ttcur);
- debug(F101,"ttsspd gtty","",x);
- if (x < 0) return(-1);
- ttcur.sg_ospeed = s; ttcur.sg_ispeed = s2;
- tttvt.sg_ospeed = s; tttvt.sg_ispeed = s2;
- ttraw.sg_ospeed = s; ttraw.sg_ispeed = s2;
- ttold.sg_ospeed = s; ttold.sg_ispeed = s2;
- x = stty(ttyfd,&ttcur);
- debug(F101,"ttsspd stty","",x);
- if (x < 0) return(-1);
- #endif /* BELLV10 */
- #endif /* ATTSV */
- #endif /* BSD44ORPOSIX */
- #endif /* Plan9 */
- }
- return(1); /* Return 1 = success. */
- #endif /* USETCSETSPEED */
- }
- #endif /* NOLOCAL */
- /* C O N G S P D - Get speed of console terminal */
- long
- congspd() {
- /*
- This is a disgusting hack. The right way to do this would be to pass an
- argument to ttgspd(), but then we'd need to change the Kermit API and
- all of the ck?tio.c modules. (Currently used only for rlogin.)
- */
- int t1, t2;
- long spd;
- #ifdef NETCONN
- t2 = netconn;
- netconn = 0;
- #endif /* NETCONN */
- t1 = ttyfd;
- ttyfd = -1;
- spd = ttgspd();
- debug(F101,"congspd","",spd);
- #ifdef NETCONN
- netconn = t2;
- #endif /* NETCONN */
- ttyfd = t1;
- return(spd);
- }
- /* T T S P D L I S T -- Get list of serial speeds allowed on this platform */
- #define NSPDLIST 64
- static long spdlist[NSPDLIST];
- /*
- As written, this picks up the speeds known at compile time, and thus
- apply to the system where C-Kermit was built, rather than to the one where
- it is running. Suggestions for improvement are always welcome.
- */
- long *
- ttspdlist() {
- int i;
- for (i = 0; i < NSPDLIST; i++) /* Initialize the list */
- spdlist[i] = -1L;
- i = 1;
- #ifdef USETCSETSPEED /* No way to find out what's legal */
- spdlist[i++] = 50L;
- #ifndef UW7
- spdlist[i++] = 75L;
- #endif /* UW7 */
- spdlist[i++] = 110L;
- #ifndef UW7
- spdlist[i++] = 134L;
- #endif /* UW7 */
- spdlist[i++] = 150L;
- spdlist[i++] = 200L;
- spdlist[i++] = 300L;
- spdlist[i++] = 600L;
- spdlist[i++] = 1200L;
- spdlist[i++] = 1800L;
- spdlist[i++] = 2400L;
- spdlist[i++] = 4800L;
- spdlist[i++] = 8880L;
- spdlist[i++] = 9600L;
- spdlist[i++] = 14400L;
- spdlist[i++] = 19200L;
- spdlist[i++] = 28800L;
- #ifndef UW7
- spdlist[i++] = 33600L;
- #endif /* UW7 */
- spdlist[i++] = 38400L;
- spdlist[i++] = 57600L;
- spdlist[i++] = 76800L;
- spdlist[i++] = 115200L;
- #ifndef UW7
- spdlist[i++] = 153600L;
- spdlist[i++] = 230400L;
- spdlist[i++] = 307200L;
- spdlist[i++] = 460800L;
- spdlist[i++] = 921600L;
- #endif /* UW7 */
- #else /* USETCSETSPEED */
- #ifdef B50
- spdlist[i++] = 50L;
- #endif /* B50 */
- #ifdef B75
- spdlist[i++] = 75L;
- #endif /* B75 */
- #ifdef B110
- spdlist[i++] = 110L;
- #endif /* B110 */
- #ifdef B134
- spdlist[i++] = 134L;
- #endif /* B134 */
- #ifdef B150
- spdlist[i++] = 150L;
- #endif /* B150 */
- #ifdef B200
- spdlist[i++] = 200L;
- #endif /* B200 */
- #ifdef B300
- spdlist[i++] = 300L;
- #endif /* B300 */
- #ifdef B600
- spdlist[i++] = 600L;
- #endif /* B600 */
- #ifdef B1200
- spdlist[i++] = 1200L;
- #endif /* B1200 */
- #ifdef B1800
- spdlist[i++] = 1800L;
- #endif /* B1800 */
- #ifdef B2400
- spdlist[i++] = 2400L;
- #endif /* B2400 */
- #ifdef B4800
- spdlist[i++] = 4800L;
- #endif /* B4800 */
- #ifdef B9600
- spdlist[i++] = 9600L;
- #endif /* B9600 */
- #ifdef B14400
- spdlist[i++] = 14400L;
- #endif /* B14400 */
- #ifdef B19200
- spdlist[i++] = 19200L;
- #else
- #ifdef EXTA
- spdlist[i++] = 19200L;
- #endif /* EXTA */
- #endif /* B19200 */
- #ifdef B28800
- spdlist[i++] = 28800L;
- #endif /* B28800 */
- #ifdef B33600
- spdlist[i++] = 33600L;
- #endif /* B33600 */
- #ifdef B38400
- spdlist[i++] = 38400L;
- #else
- #ifdef EXTB
- spdlist[i++] = 38400L;
- #endif /* EXTB */
- #endif /* B38400 */
- #ifdef _B57600
- spdlist[i++] = 57600L;
- #else
- #ifdef B57600
- spdlist[i++] = 57600L;
- #endif /* B57600 */
- #endif /* _B57600 */
- #ifdef B76800
- spdlist[i++] = 76800L;
- #endif /* B76800 */
- #ifdef _B115200
- spdlist[i++] = 115200L;
- #else
- #ifdef B115200
- spdlist[i++] = 115200L;
- #endif /* B115200 */
- #endif /* _B115200 */
- #ifdef B153600
- spdlist[i++] = 153600L;
- #endif /* B153600 */
- #ifdef B230400
- spdlist[i++] = 230400L;
- #endif /* B230400 */
- #ifdef B307200
- spdlist[i++] = 307200L;
- #endif /* B307200 */
- #ifdef B460800
- spdlist[i++] = 460800L;
- #endif /* B460800 */
- #ifdef B921600
- spdlist[i++] = 921600L;
- #endif /* B921600 */
- #endif /* USETCSETSPEED */
- spdlist[0] = i - 1; /* Return count in 0th element */
- return((long *)spdlist);
- }
- /* T T G S P D - Get speed of currently selected tty line */
- /*
- Unreliable. After SET LINE, it returns an actual speed, but not necessarily
- the real speed. On some systems, it returns the line's nominal speed, from
- /etc/ttytab. Even if you SET SPEED to something else, this function might
- not notice.
- */
- long
- ttgspd() { /* Get current serial device speed */
- #ifdef NOLOCAL
- return(-1L);
- #else
- #ifdef POSIX
- speed_t /* Should be unsigned */
- #else
- int /* Isn't unsigned */
- #endif /* POSIX */
- s;
- int x;
- long ss;
- #ifdef OLINUXHISPEED
- unsigned int spd_flags = 0;
- struct serial_struct serinfo;
- #endif /* OLINUXHISPEED */
- #ifdef NETCONN
- if (netconn) return(-1); /* -1 if network connection */
- #endif /* NETCONN */
- #ifdef NETCMD
- if (ttpipe) return(-1);
- #endif /* NETCMD */
- #ifdef NETPTY
- if (ttpty) return(-1);
- #endif /* NETPTY */
- debug(F101,"ttgspd ttyfd","",ttyfd);
- #ifdef USETCSETSPEED
- x = tcgetattr(ttyfd,&ttcur); /* Get current speed */
- debug(F101,"ttgspd tcgetattr","",x);
- if (x < 0)
- return(-1);
- errno = 0;
- s = tcgetspeed(TCS_ALL, &ttcur);
- debug(F101,"ttsspd TCGETSPEED speed","",s);
- if (s == 0) {
- long s1, s2;
- s1 = tcgetspeed(TCS_IN, &ttcur);
- s2 = tcgetspeed(TCS_OUT, &ttcur);
- if (s1 == 1200L && s2 == 75L)
- return(8880L);
- }
- #ifdef DEBUG
- if (errno & deblog) {
- debug(F101,"ttsspd TCGETSPEED errno","",errno);
- }
- #endif /* DEBUG */
- return(s);
- #else /* Not USETCSETSPEED */
- #ifdef Plan9
- if (ttyfd < 0)
- ss = -1;
- else
- ss = ttylastspeed;
- #else
- #ifdef OLINUXHISPEED
- debug(F100,"ttgspd Linux OLINUXHISPEED","",0);
- #endif /* OLINUXHISPEED */
- if (ttyfd < 0) {
- #ifdef BSD44ORPOSIX
- s = cfgetospeed(&ccold);
- debug(F101,"ttgspd cfgetospeed 1 POSIX","",s);
- #else
- #ifdef ATTSV
- s = ccold.c_cflag & CBAUD;
- debug(F101,"ttgspd c_cflag CBAUD 1 ATTSV","",s);
- #else
- s = ccold.sg_ospeed; /* (obtained by congm()) */
- debug(F101,"ttgspd sg_ospeed 1","",s);
- #endif /* ATTSV */
- #endif /* BSD44POSIX */
- } else {
- #ifdef BSD44ORPOSIX
- if (tcgetattr(ttyfd,&ttcur) < 0) return(-1);
- s = cfgetospeed(&ttcur);
- debug(F101,"ttgspd cfgetospeed 2 BSDORPOSIX","",s);
- #ifdef OLINUXHISPEED
- if (ioctl(ttyfd,TIOCGSERIAL,&serinfo) > -1)
- spd_flags = serinfo.flags & ASYNC_SPD_MASK;
- debug(F101,"ttgspd spd_flags","",spd_flags);
- #endif /* OLINUXHISPEED */
- #else
- #ifdef ATTSV
- x = ioctl(ttyfd,TCGETA,&ttcur);
- debug(F101,"ttgspd ioctl 2 ATTSV x","",x);
- debug(F101,"ttgspd ioctl 2 ATTSV errno","",errno);
- if (x < 0) return(-1);
- s = ttcur.c_cflag & CBAUD;
- debug(F101,"ttgspd ioctl 2 ATTSV speed","",s);
- #else
- #ifdef BELLV10
- x = ioctl(ttyfd,TIOCGDEV,&tdcur);
- debug(F101,"ttgspd ioctl 2 BELLV10 x","",x);
- if (x < 0) return(-1);
- s = tdcur.ospeed;
- debug(F101,"ttgspd ioctl 2 BELLV10 speed","",s);
- #else
- x = gtty(ttyfd,&ttcur);
- debug(F101,"ttgspd gtty 2 x","",x);
- debug(F101,"ttgspd gtty 2 errno","",errno);
- if (x < 0) return(-1);
- s = ttcur.sg_ospeed;
- debug(F101,"ttgspd gtty 2 speed","",s);
- #endif /* BELLV10 */
- #endif /* ATTSV */
- #endif /* BSD44ORPOSIX */
- }
- debug(F101,"ttgspd code","",s);
- #ifdef OLINUXHISPEED
- debug(F101,"ttgspd spd_flags","",spd_flags);
- #endif /* OLINUXHISPEED */
- switch (s) {
- #ifdef B0
- case B0: ss = 0L; break;
- #endif /* B0 */
- #ifndef MINIX
- /*
- MINIX defines the Bxx symbols to be bps/100, so B50==B75, B110==B134==B150,
- etc, making for many "duplicate case in switch" errors, which are fatal.
- */
- #ifdef B50
- case B50: ss = 50L; break;
- #endif /* B50 */
- #ifdef B75
- case B75: ss = 75L; break;
- #endif /* B75 */
- #endif /* MINIX */
- #ifdef B110
- case B110: ss = 110L; break;
- #endif /* B110 */
- #ifndef MINIX
- #ifdef B134
- case B134: ss = 134L; break;
- #endif /* B134 */
- #ifdef B150
- case B150: ss = 150L; break;
- #endif /* B150 */
- #endif /* MINIX */
- #ifdef B200
- case B200: ss = 200L; break;
- #endif /* B200 */
- #ifdef B300
- case B300: ss = 300L; break;
- #endif /* B300 */
- #ifdef B600
- case B600: ss = 600L; break;
- #endif /* B600 */
- #ifdef B1200
- case B1200: ss = 1200L; break;
- #endif /* B1200 */
- #ifdef B1800
- case B1800: ss = 1800L; break;
- #endif /* B1800 */
- #ifdef B2400
- case B2400: ss = 2400L; break;
- #endif /* B2400 */
- #ifdef B4800
- case B4800: ss = 4800L; break;
- #endif /* B4800 */
- #ifdef B7200
- case B7200: ss = 7200L; break;
- #endif /* B7200 */
- #ifdef B9600
- case B9600: ss = 9600L; break;
- #endif /* B9600 */
- #ifdef B19200
- case B19200: ss = 19200L; break;
- #else
- #ifdef EXTA
- case EXTA: ss = 19200L; break;
- #endif /* EXTA */
- #endif /* B19200 */
- #ifdef MINIX2
- /* End of hack to make MINIX2 use MINIX1 speed setting */
- #undef MINIX
- #endif /* MINIX2 */
- #ifndef MINIX
- #ifdef B38400
- case B38400:
- ss = 38400L;
- #ifdef OLINUXHISPEED
- switch(spd_flags) {
- case ASYNC_SPD_HI: ss = 57600L; break;
- case ASYNC_SPD_VHI: ss = 115200L; break;
- }
- #endif /* OLINUXHISPEED */
- break;
- #else
- #ifdef EXTB
- case EXTB: ss = 38400L; break;
- #endif /* EXTB */
- #endif /* B38400 */
- #endif /* MINIX */
- #ifdef HPUX
- #ifdef _B57600
- case _B57600: ss = 57600L; break;
- #endif /* _B57600 */
- #ifdef _B115200
- case _B115200: ss = 115200L; break;
- #endif /* _B115200 */
- #else
- #ifdef B57600
- case B57600: ss = 57600L; break;
- #endif /* B57600 */
- #ifdef B76800
- case B76800: ss = 76800L; break;
- #endif /* B76800 */
- #ifdef B115200
- case B115200: ss = 115200L; break;
- #endif /* B115200 */
- #ifdef B153600
- case B153600: ss = 153600L; break;
- #endif /* B153600 */
- #ifdef B230400
- case B230400: ss = 230400L; break;
- #endif /* B230400 */
- #ifdef B307200
- case B307200: ss = 307200L; break;
- #endif /* B307200 */
- #ifdef B460800
- case B460800: ss = 460800L; break;
- #endif /* B460800 */
- #endif /* HPUX */
- #ifdef B921600
- case 92160: ss = 921600L; break;
- #endif /* B921600 */
- default:
- ss = -1; break;
- }
- #endif /* Plan9 */
- debug(F101,"ttgspd speed","",ss);
- return(ss);
- #endif /* USETCSETSPEED */
- #endif /* NOLOCAL */
- }
- #ifdef MINIX2 /* Another hack alert */
- #define MINIX
- #endif /* MINIX2 */
- /*
- FIONREAD data type... This has been defined as "long" for many, many
- years, and it worked OK until 64-bit platforms appeared. Thus we use
- int for 64-bit platforms, but keep long for the others. If we changed
- the default PEEKTYPE to int, this would probably break 16-bit builds
- (note that sizeof(long) == sizeof(int) on most 32-bit platforms), many
- of which we have no way of testing any more. Therefore, do not change
- the default definition of PEEKTYPE -- only add exceptions to it as needed.
- */
- #ifdef COHERENT
- #ifdef FIONREAD
- #undef FIONREAD
- #endif /* FIONREAD */
- /* #define FIONREAD TIOCQUERY */
- /* #define PEEKTYPE int */
- #else /* Not COHERENT... */
- #ifdef OSF32 /* Digital UNIX 3.2 or higher */
- #define PEEKTYPE int
- #else
- #define PEEKTYPE long /* Elsewhere (see notes above) */
- #endif /* OSF32 */
- #endif /* COHERENT */
- /* ckumyr.c by Kristoffer Eriksson, ske@pkmab.se, 15 Mar 1990. */
- #ifdef MYREAD
- /* Private buffer for myread() and its companions. Not for use by anything
- * else. ttflui() is allowed to reset them to initial values. ttchk() is
- * allowed to read my_count.
- *
- * my_item is an index into mybuf[]. Increment it *before* reading mybuf[].
- *
- * A global parity mask variable could be useful too. We could use it to
- * let myread() strip the parity on its own, instead of stripping sign
- * bits as it does now.
- */
- #ifdef BIGBUFOK
- #define MYBUFLEN 32768
- #else
- #ifdef pdp11
- #define MYBUFLEN 256
- #else
- #define MYBUFLEN 1024
- #endif /* pdp11 */
- #endif /* BIGBUFOK */
- #ifdef ANYX25
- #undef MYBUFLEN
- #define MYBUFLEN 256
- /*
- On X.25 connections, there is an extra control byte at the beginning.
- */
- static CHAR x25buf[MYBUFLEN+1]; /* Communication device input buffer */
- static CHAR *mybuf = x25buf+1;
- #else
- static CHAR mybuf[MYBUFLEN];
- #endif /* ANYX25 */
- static int my_count = 0; /* Number of chars still in mybuf */
- static int my_item = -1; /* Last index read from mybuf[] */
- /* T T P E E K -- Peek into our internal communications input buffers. */
- /*
- NOTE: This routine is peculiar to UNIX, and is used only by the
- select()-based CONNECT module, ckucns.c. It need not be replicated in
- the ck?tio.c of other platforms.
- */
- int
- ttpeek() {
- int rc = 0;
- #ifdef TTLEBUF
- if (ttpush >= 0)
- rc++;
- rc += le_inbuf();
- if (rc > 0)
- return(rc);
- else
- #endif /* TTLEBUF */
- #ifdef MYREAD
- return(my_count);
- #else
- return(0);
- #endif /* MYREAD */
- }
- /* myread() -- Efficient read of one character from communications line.
- *
- * Uses a private buffer to minimize the number of expensive read() system
- * calls. Essentially performs the equivalent of read() of 1 character, which
- * is then returned. By reading all available input from the system buffers
- * to the private buffer in one chunk, and then working from this buffer, the
- * number of system calls is reduced in any case where more than one character
- * arrives during the processing of the previous chunk, for instance high
- * baud rates or network type connections where input arrives in packets.
- * If the time needed for a read() system call approaches the time for more
- * than one character to arrive, then this mechanism automatically compensates
- * for that by performing bigger read()s less frequently. If the system load
- * is high, the same mechanism compensates for that too.
- *
- * myread() is a macro that returns the next character from the buffer. If the
- * buffer is empty, mygetbuf() is called. See mygetbuf() for possible error
- * returns.
- *
- * This should be efficient enough for any one-character-at-a-time loops.
- * For even better efficiency you might use memcpy()/bcopy() or such between
- * buffers (since they are often better optimized for copying), but it may not
- * be worth it if you have to take an extra pass over the buffer to strip
- * parity and check for CTRL-C anyway.
- *
- * Note that if you have been using myread() from another program module, you
- * may have some trouble accessing this macro version and the private variables
- * it uses. In that case, just add a function in this module, that invokes the
- * macro.
- */
- #define myread() (--my_count < 0 ? mygetbuf() : 255 & (int)mybuf[++my_item])
- /* Specification: Push back up to one character onto myread()'s queue.
- *
- * This implementation: Push back characters into mybuf. At least one character
- * must have been read through myread() before myunrd() may be used. After
- * EOF or read error, again, myunrd() can not be used. Sometimes more than
- * one character can be pushed back, but only one character is guaranteed.
- * Since a previous myread() must have read its character out of mybuf[],
- * that guarantees that there is space for at least one character. If push
- * back was really needed after EOF, a small addition could provide that.
- *
- * myunrd() is currently not called from anywhere inside kermit...
- */
- #ifdef COMMENT /* not used */
- myunrd(ch) CHAR ch; {
- if (my_item >= 0) {
- mybuf[my_item--] = ch;
- ++my_count;
- }
- }
- #endif /* COMMENT */
- /* T T P U S H B A C K -- Put n bytes back into the myread buffer */
- static CHAR * pushbuf = NULL;
- static int pushed = 0;
- int
- ttpushback(s,n) CHAR * s; int n; {
- debug(F101,"ttpushback n","",n);
- if (pushbuf || n > MYBUFLEN || n < 1)
- return(-1);
- debug(F101,"ttpushback my_count","",my_count);
- if (my_count > 0) {
- if (!(pushbuf = (CHAR *)malloc(n+1)))
- return(-1);
- memcpy(pushbuf,mybuf,my_count);
- pushed = my_count;
- }
- memcpy(mybuf,s,n);
- my_count = n;
- my_item = -1;
- return(0);
- }
- /* mygetbuf() -- Fill buffer for myread() and return first character.
- *
- * This function is what myread() uses when it can't get the next character
- * directly from its buffer. First, it calls a system dependent myfillbuf()
- * to read at least one new character into the buffer, and then it returns
- * the first character just as myread() would have done. This function also
- * is responsible for all error conditions that myread() can indicate.
- *
- * Returns: When OK => a positive character, 0 or greater.
- * When EOF => -2.
- * When error => -3, error code in errno.
- *
- * Older myread()s additionally returned -1 to indicate that there was nothing
- * to read, upon which the caller would call myread() again until it got
- * something. The new myread()/mygetbuf() always gets something. If it
- * doesn't, then make it do so! Any program that actually depends on the old
- * behaviour will break.
- *
- * The older version also used to return -2 both for EOF and other errors,
- * and used to set errno to 9999 on EOF. The errno stuff is gone, EOF and
- * other errors now return different results, although Kermit currently never
- * checks to see which it was. It just disconnects in both cases.
- *
- * Kermit lets the user use the quit key to perform some special commands
- * during file transfer. This causes read(), and thus also mygetbuf(), to
- * finish without reading anything and return the EINTR error. This should
- * be checked by the caller. Mygetbuf() could retry the read() on EINTR,
- * but if there is nothing to read, this could delay Kermit's reaction to
- * the command, and make Kermit appear unresponsive.
- *
- * The debug() call should be removed for optimum performance.
- */
- int
- mygetbuf() {
- int x;
- errno = 0;
- #ifdef DEBUG
- if (deblog && my_count > 0)
- debug(F101,"mygetbuf IMPROPERLY CALLED with my_count","",my_count);
- #endif /* DEBUG */
- if (my_count <= 0)
- my_count = myfillbuf();
- #ifdef DEBUG
- if (deblog) debug(F101, "mygetbuf read", "", my_count);
- #endif /* DEBUG */
- x = my_count;
- if (my_count <= 0) {
- my_count = 0;
- my_item = -1;
- debug(F101,"mygetbuf errno","",errno);
- #ifdef TCPSOCKET
- if (netconn && ttnet == NET_TCPB && errno != 0) {
- if (errno != EINTR) {
- debug(F101,"mygetbuf TCP error","",errno);
- ttclos(0); /* Close the connection. */
- }
- return(-3);
- }
- #endif /* TCPSOCKET */
- if (!netconn && xlocal && errno) {
- if (errno != EINTR) {
- debug(F101,"mygetbuf SERIAL error","",errno);
- x = -3;
- ttclos(0); /* Close the connection. */
- }
- }
- return((x < 0) ? -3 : -2);
- }
- --my_count;
- return((unsigned)(0xff & mybuf[my_item = 0]));
- }
- /* myfillbuf():
- * System-dependent read() into mybuf[], as many characters as possible.
- *
- * Returns: OK => number of characters read, always more than zero.
- * EOF => 0
- * Error => -1, error code in errno.
- *
- * If there is input available in the system's buffers, all of it should be
- * read into mybuf[] and the function return immediately. If no input is
- * available, it should wait for a character to arrive, and return with that
- * one in mybuf[] as soon as possible. It may wait somewhat past the first
- * character, but be aware that any such delay lengthens the packet turnaround
- * time during kermit file transfers. Should never return with zero characters
- * unless EOF or irrecoverable read error.
- *
- * Correct functioning depends on the correct tty parameters being used.
- * Better control of current parameters is required than may have been the
- * case in older Kermit releases. For instance, O_NDELAY (or equivalent) can
- * no longer be sometimes off and sometimes on like it used to, unless a
- * special myfillbuf() is written to handle that. Otherwise the ordinary
- * myfillbuf()s may think they have come to EOF.
- *
- * If your system has a facility to directly perform the functioning of
- * myfillbuf(), then use it. If the system can tell you how many characters
- * are available in its buffers, then read that amount (but not less than 1).
- * If the system can return a special indication when you try to read without
- * anything to read, while allowing you to read all there is when there is
- * something, you may loop until there is something to read, but probably that
- * is not good for the system load.
- */
- #ifdef SVORPOSIX
- /* This is for System III/V with VMIN>0, VTIME=0 and O_NDELAY off,
- * and CLOCAL set any way you like. This way, read() will do exactly
- * what is required by myfillbuf(): If there is data in the buffers
- * of the O.S., all available data is read into mybuf, up to the size
- * of mybuf. If there is none, the first character to arrive is
- * awaited and returned.
- */
- int
- myfillbuf() {
- int fd, n;
- #ifdef NETCMD
- if (ttpipe)
- fd = fdin;
- else
- #endif /* NETCMD */
- fd = ttyfd;
- #ifdef sxaE50
- /* From S. Dezawa at Fujifilm in Japan. I don't know why this is */
- /* necessary for the sxa E50, but it is. */
- return read(fd, mybuf, 255);
- #else
- #ifdef BEOSORBEBOX
- while (1) {
- #ifdef NETCONN
- if (netconn) {
- n = netxin(sizeof(mybuf), (char *)mybuf);
- debug(F101,"BEBOX SVORPOSIX network myfillbuf","",n);
- }
- else
- #endif /* NETCONN */
- n = read(fd, mybuf, sizeof(mybuf));
- debug(F101,"BEBOX SVORPOSIX notnet myfillbuf","",n);
- if (n > 0)
- return(n);
- snooze(1000.0);
- }
- #else /* BEOSORBEBOX */
- errno = 0;
- debug(F100,"SVORPOSIX myfillbuf calling read()","",0);
- #ifdef IBMX25
- if (netconn && (nettype == NET_IX25)) {
- /* can't use sizeof because mybuf is a pointer, and not an array! */
- n = x25xin( MYBUFLEN, mybuf );
- } else
- #endif /* IBMX25 */
- #ifdef CK_SSL
- if (ssl_active_flag || tls_active_flag) {
- int error, n = 0;
- while (n == 0) {
- if (ssl_active_flag)
- n = SSL_read(ssl_con, (char *)mybuf, sizeof(mybuf));
- else if (tls_active_flag)
- n = SSL_read(tls_con, (char *)mybuf, sizeof(mybuf));
- else
- break;
- switch (SSL_get_error(ssl_active_flag?ssl_con:tls_con,n)) {
- case SSL_ERROR_NONE:
- if (n > 0)
- return(n);
- if (n < 0)
- return(-2);
- msleep(50);
- break;
- case SSL_ERROR_WANT_WRITE:
- case SSL_ERROR_WANT_READ:
- return(-1);
- case SSL_ERROR_SYSCALL:
- case SSL_ERROR_WANT_X509_LOOKUP:
- case SSL_ERROR_SSL:
- case SSL_ERROR_ZERO_RETURN:
- default:
- ttclos(0);
- return(-3);
- }
- }
- }
- #endif /* CK_SSL */
- #ifdef RLOGCODE
- #ifdef CK_KERBEROS
- #ifdef KRB4
- if (ttnproto == NP_EK4LOGIN) {
- if ((n = krb4_des_read(ttyfd,mybuf,sizeof(mybuf))) < 0)
- return(-3);
- else
- return(n);
- }
- #endif /* KRB4 */
- #ifdef KRB5
- if (ttnproto == NP_EK5LOGIN) {
- if ((n = krb5_des_read(ttyfd,mybuf,sizeof(mybuf))) < 0)
- return(-3);
- else
- return(n);
- }
- #endif /* KRB5 */
- #endif /* CK_KERBEROS */
- #endif /* RLOGCODE */
- #ifdef NETPTY
- #ifdef HAVE_PTYTRAP
- /* Special handling for HP-UX pty i/o */
- ptyread:
- if (ttpty && pty_trap_pending(ttyfd) > 0) {
- if (pty_trap_handler(ttyfd) > 0) {
- ttclos(0);
- return(-3);
- }
- }
- #endif /* HAVE_PTYTRAP */
- #endif /* NETPTY */
- n = read(fd, mybuf, sizeof(mybuf));
- debug(F101,"SVORPOSIX myfillbuf","",n);
- debug(F101,"SVORPOSIX myfillbuf ttcarr","",ttcarr);
- debug(F101,"SVORPOSIX myfillbuf errno","",errno);
- if (n < 1) {
- #ifdef NETPTY
- #ifdef HAVE_PTYTRAP
- /* When we have a PTY trap in place the connection cannot */
- /* be closed until the trap receives a close indication. */
- if (n == 0 && ttpty)
- goto ptyread;
- #endif /* HAVE_PTYTRAP */
- #endif /* NETPTY */
- return(-3);
- }
- return(n);
- #endif /* BEOSORBEBOX */
- #endif /* sxaE50 */
- }
- #else /* not AT&T or POSIX */
- #ifdef aegis
- /* This is quoted from the old myread(). The semantics seem to be
- * alright, but maybe errno would not need to be set even when
- * there is no error? I don't know aegis.
- */
- int
- myfillbuf() {
- int count;
- #ifdef NETCMD
- if (ttpipe)
- fd = fdin;
- else
- #endif /* NETCMD */
- fd = ttyfd;
- count = ios_$get((short)fd, ios_$cond_opt, mybuf, 256L, st);
- errno = EIO;
- if (st.all == ios_$get_conditional_failed) /* get at least one */
- count = ios_$get((short)fd, 0, mybuf, 1L, st);
- if (st.all == ios_$end_of_file)
- return(-3);
- else if (st.all != status_$ok) {
- errno = EIO;
- return(-1);
- }
- return(count > 0 ? count : -3);
- }
- #else /* !aegis */
- #ifdef FIONREAD
- /* This is for systems with FIONREAD. FIONREAD returns the number
- * of characters available for reading. If none are available, wait
- * until something arrives, otherwise return all there is.
- */
- int
- myfillbuf() {
- PEEKTYPE avail = 0;
- int x, fd;
- #ifdef NETCMD
- if (ttpipe)
- fd = fdin;
- else
- #endif /* NETCMD */
- fd = ttyfd;
- #ifdef SUNX25
- /*
- SunLink X.25 support in this routine from Stefaan A. Eeckels, Eurostat (CEC).
- Depends on SunOS having FIONREAD, not because we use it, but just so this
- code is grouped correctly within the #ifdefs. Let's hope Solaris keeps it.
- We call x25xin() instead of read() so that Q-Bit packets, which contain
- X.25 service-level information (e.g. PAD parameter changes), can be processed
- transparently to the upper-level code. This is a blocking read, and so
- we depend on higher-level code (such as ttinc()) to set any necessary alarms.
- */
- extern int nettype;
- if (netconn && nettype == NET_SX25) {
- while ((x = x25xin(sizeof(x25buf), x25buf)) < 1) ;
- return(x - 1); /* "-1" compensates for extra status byte */
- }
- #endif /* SUNX25 */
- #ifdef CK_SSL
- if (ssl_active_flag || tls_active_flag) {
- int error, n = 0;
- while (n == 0) {
- if (ssl_active_flag)
- n = SSL_read(ssl_con, (char *)mybuf, sizeof(mybuf));
- else
- n = SSL_read(tls_con, (char *)mybuf, sizeof(mybuf));
- switch (SSL_get_error(ssl_active_flag?ssl_con:tls_con,n)) {
- case SSL_ERROR_NONE:
- if (n > 0)
- return(n);
- if (n < 0)
- return(-2);
- msleep(50);
- break;
- case SSL_ERROR_WANT_WRITE:
- case SSL_ERROR_WANT_READ:
- return(-1);
- case SSL_ERROR_SYSCALL:
- case SSL_ERROR_WANT_X509_LOOKUP:
- case SSL_ERROR_SSL:
- case SSL_ERROR_ZERO_RETURN:
- default:
- ttclos(0);
- return(-2);
- }
- }
- }
- #endif /* CK_SSL */
- #ifdef RLOGCODE
- #ifdef CK_KERBEROS
- #ifdef KRB4
- if (ttnproto == NP_EK4LOGIN) {
- if ((x = krb4_des_read(ttyfd,mybuf,sizeof(mybuf))) < 0)
- return(-1);
- else
- return(x);
- }
- #endif /* KRB4 */
- #ifdef KRB5
- if (ttnproto == NP_EK5LOGIN) {
- if ((x = krb5_des_read(ttyfd,mybuf,sizeof(mybuf))) < 0)
- return(-1);
- else
- return(x);
- }
- #endif /* KRB5 */
- #endif /* CK_KERBEROS */
- #endif /* RLOGCODE */
- errno = 0;
- debug(F101,"myfillbuf calling FIONREAD ioctl","",xlocal);
- x = ioctl(fd, FIONREAD, &avail);
- #ifdef DEBUG
- if (deblog) {
- debug(F101,"myfillbuf FIONREAD","",x);
- debug(F101,"myfillbuf FIONREAD avail","",avail);
- debug(F101,"myfillbuf FIONREAD errno","",errno);
- }
- #endif /* DEBUG */
- if (x < 0 || avail == 0)
- avail = 1;
- if (avail > MYBUFLEN)
- avail = MYBUFLEN;
- errno = 0;
- x = read(fd, mybuf, (int) avail);
- #ifdef DEBUG
- if (deblog) {
- debug(F101,"myfillbuf avail","",avail);
- debug(F101,"myfillbuf read","",x);
- debug(F101,"myfillbuf read errno","",errno);
- if (x > 0)
- hexdump("myfillbuf mybuf",mybuf,x);
- }
- #endif /* DEBUG */
- if (x < 1) x = -3; /* read 0 == connection loss */
- return(x);
- }
- #else /* !FIONREAD */
- /* Add other systems here, between #ifdef and #else, e.g. NETCONN. */
- /* When there is no other possibility, read 1 character at a time. */
- int
- myfillbuf() {
- int x;
- #ifdef CK_SSL
- if (ssl_active_flag || tls_active_flag) {
- int error, n = 0;
- while (n == 0) {
- if (ssl_active_flag)
- n = SSL_read(ssl_con, (char *)mybuf, sizeof(mybuf));
- else
- count = SSL_read(tls_con, (char *)mybuf, sizeof(mybuf));
- switch (SSL_get_error(ssl_active_flag?ssl_con:tls_con,n)) {
- case SSL_ERROR_NONE:
- if (n > 0)
- return(n);
- if (n < 0)
- return(-2);
- msleep(50);
- break;
- case SSL_ERROR_WANT_WRITE:
- case SSL_ERROR_WANT_READ:
- return(-1);
- case SSL_ERROR_SYSCALL:
- case SSL_ERROR_WANT_X509_LOOKUP:
- case SSL_ERROR_SSL:
- case SSL_ERROR_ZERO_RETURN:
- default:
- ttclos(0);
- return(-2);
- }
- }
- }
- #endif /* CK_SSL */
- #ifdef RLOGCODE
- #ifdef CK_KERBEROS
- #ifdef KRB4
- if (ttnproto == NP_EK4LOGIN) {
- if ((len = krb4_des_read(ttyfd,mybuf,sizeof(mybuf))) < 0)
- return(-1);
- else
- return(len);
- }
- #endif /* KRB4 */
- #ifdef KRB5
- if (ttnproto == NP_EK5LOGIN) {
- if ((len = krb5_des_read(ttyfd,mybuf,sizeof(mybuf))) < 0)
- return(-1);
- else
- return(len);
- }
- #endif /* KRB5 */
- #endif /* CK_KERBEROS */
- #endif /* RLOGCODE */
- #ifdef NETCMD
- if (ttpipe)
- fd = fdin;
- else
- #endif /* NETCMD */
- fd = ttyfd;
- x = read(fd, mybuf, 1);
- return(x > 0 ? x : -3);
- }
- #endif /* !FIONREAD */
- #endif /* !aegis */
- #endif /* !ATTSV */
- #endif /* MYREAD */
- #ifdef MINIX2
- #undef MINIX
- #endif /* MINIX2 */
- /* T T _ T N O P T -- Handle Telnet negotions in incoming data */
- /*
- Call with the IAC that was encountered.
- Returns:
- -3: If connection has dropped or gone bad.
- -2: On Telnet protocol error resulting in inconsistent states.
- 0: If negotiation OK and caller has nothing to do.
- 1: If packet start character has changed (new value is in global stchr).
- 255: If there was a quoted IAC as data.
- or: Not at all if we got a legitimate Telnet Logout request.
- */
- #ifdef TCPSOCKET
- static int
- tt_tnopt(n) int n; { /* Handle Telnet options */
- /* In case caller did not already check these conditions... */
- if (n == IAC &&
- ((xlocal && netconn && (ttnproto == NP_TELNET)) ||
- (!xlocal && sstelnet))) {
- extern int duplex;
- extern int server;
- int tx = 0;
- debug(F100,"ttinl calling tn_doop()","",0);
- tx = tn_doop((CHAR)(n & 0xff),duplex,ttinc);
- debug(F111,"ttinl tn_doop() returned","tx",tx);
- switch (tx) {
- case 0:
- return(0);
- case -1: /* I/O error */
- ttimoff(); /* Turn off timer */
- return(-3);
- case -2: /* Connection failed. */
- case -3:
- ttimoff(); /* Turn off timer */
- ttclos(0);
- return(-3);
- case 1: /* ECHO change */
- duplex = 1;
- return(0);
- case 2: /* ECHO change */
- duplex = 0;
- return(0);
- case 3: /* Quoted IAC */
- n = 255;
- return((unsigned)255);
- #ifdef IKS_OPTION
- case 4: {
- if (TELOPT_SB(TELOPT_KERMIT).kermit.u_start && server
- #ifdef IKSD
- && !inserver
- #endif /* IKSD */
- ) { /* Remote in Server mode */
- ttimoff(); /* Turn off timer */
- debug(F100,"u_start and !inserver","",0);
- return(-2); /* End server mode */
- } else if (!TELOPT_SB(TELOPT_KERMIT).kermit.me_start &&
- server
- ) { /* I'm no longer in Server Mode */
- debug(F100,"me_start and server","",0);
- ttimoff();
- return(-2);
- }
- return(0);
- }
- case 5: { /* Start character change */
- /* extern CHAR stchr; */
- /* start = stchr; */
- return(1);
- }
- #endif /* IKS_OPTION */
- case 6: /* Remote Logout */
- ttimoff();
- ttclos(0);
- #ifdef IKSD
- if (inserver && !local)
- doexit(GOOD_EXIT,0);
- else
- #endif /* IKSD */
- return(-2);
- default:
- return(0);
- }
- } else
- return(0);
- }
- #endif /* TCPSOCKET */
- /* T T F L U I -- Flush tty input buffer */
- void
- ttflux() { /* But first... */
- #ifdef MYREAD
- /*
- Flush internal MYREAD buffer.
- */
- #ifdef TCPSOCKET
- int dotnopts, x;
- dotnopts = (((xlocal && netconn && (ttnproto == NP_TELNET)) ||
- (!xlocal && sstelnet)));
- #endif /* TCPSOCKET */
- debug(F101,"ttflux my_count","",my_count);
- #ifdef TCPSOCKET
- if (dotnopts) {
- CHAR ch = ' ';
- while (my_count > 0) {
- ch = myread();
- #ifdef CK_ENCRYPTION
- if (TELOPT_U(TELOPT_ENCRYPTION))
- ck_tn_decrypt(&ch,1);
- #endif /* CK_ENCRYPTION */
- if (ch == IAC)
- x = tt_tnopt(ch);
- }
- } else
- #endif /* TCPSOCKET */
- #ifdef COMMENT
- #ifdef CK_ENCRYPTION
- if (TELOPT_U(TELOPT_ENCRYPTION) && my_count > 0)
- ck_tn_decrypt(&mybuf[my_item+1],my_count);
- #endif /* CK_ENCRYPTION */
- #endif /* COMMENT */
- my_count = 0; /* Reset count to zero */
- my_item = -1; /* And buffer index to -1 */
- #endif /* MYREAD */
- }
- int
- ttflui() {
- int n, fd;
- #ifdef TCPSOCKET
- int dotnopts;
- dotnopts = (((xlocal && netconn && (ttnproto == NP_TELNET)) ||
- (!xlocal && sstelnet)));
- #endif /* TCPSOCKET */
- #ifdef NETCMD
- if (ttpipe)
- fd = fdin;
- else
- #endif /* NETCMD */
- fd = ttyfd;
- #ifdef TTLEBUF
- ttpush = -1; /* Clear the peek-ahead char */
- while (le_data && (le_inbuf() > 0)) {
- CHAR ch = ' ';
- if (le_getchar(&ch) > 0) { /* Clear any more... */
- debug(F101,"ttflui le_inbuf ch","",ch);
- }
- }
- #endif /* TTLEBUF */
- debug(F101,"ttflui ttpipe","",ttpipe);
- #ifdef MYREAD
- /*
- Flush internal MYREAD buffer *NEXT*, in all cases.
- */
- ttflux();
- #endif /* MYREAD */
- #ifdef NETCONN
- /* Network flush is done specially, in the network support module. */
- if ((netconn || sstelnet) && !ttpipe && !ttpty) {
- debug(F100,"ttflui netflui","",0);
- return(netflui());
- }
- #endif /* NETCONN */
- debug(F101,"ttflui ttyfd","",ttyfd); /* Not network */
- if (ttyfd < 0)
- return(-1);
- #ifdef aegis
- sio_$control((short)yfd, sio_$flush_in, true, st);
- if (st.all != status_$ok) {
- fprintf(stderr, "flush failed: "); error_$print(st);
- } else { /* sometimes the flush doesn't work */
- for (;;) {
- char buf[256];
- /* eat all the characters that shouldn't be available */
- ios_$get((short)fd, ios_$cond_opt, buf, 256L, st); /* (void) */
- if (st.all == ios_$get_conditional_failed) break;
- fprintf(stderr, "flush failed(2): "); error_$print(st);
- }
- }
- #else
- #ifdef BSD44 /* 4.4 BSD */
- n = FREAD; /* Specify read queue */
- debug(F100,"ttflui BSD44","",0);
- ioctl(fd,TIOCFLUSH,&n);
- #else
- #ifdef Plan9
- #undef POSIX /* Uh oh... */
- #endif /* Plan9 */
- #ifdef POSIX /* POSIX */
- debug(F100,"ttflui POSIX","",0);
- tcflush(fd,TCIFLUSH);
- #else
- #ifdef ATTSV /* System V */
- #ifndef VXVE
- debug(F100,"ttflui ATTSV","",0);
- ioctl(fd,TCFLSH,0);
- #endif /* VXVE */
- #else /* Not BSD44, POSIX, or Sys V */
- #ifdef TIOCFLUSH /* Those with TIOCFLUSH defined */
- #ifdef ANYBSD /* Berkeley */
- n = FREAD; /* Specify read queue */
- debug(F100,"ttflui TIOCFLUSH ANYBSD","",0);
- ioctl(fd,TIOCFLUSH,&n);
- #else /* Others (V7, etc) */
- debug(F100,"ttflui TIOCFLUSH","",0);
- ioctl(fd,TIOCFLUSH,0);
- #endif /* ANYBSD */
- #else /* All others... */
- /*
- No system call (that we know about) for input buffer flushing.
- So see how many there are and read them in a loop, using ttinc().
- ttinc() is buffered, so we're not getting charged with a system call
- per character, just a function call.
- */
- if ((n = ttchk()) > 0) {
- debug(F101,"ttflui read loop","",n);
- while ((n--) && ttinc(0) > 0) ;
- }
- #endif /* TIOCFLUSH */
- #endif /* ATTSV */
- #endif /* POSIX */
- #ifdef Plan9
- #define POSIX
- #endif /* Plan9 */
- #endif /* BSD44 */
- #endif /* aegis */
- return(0);
- }
- int
- ttfluo() { /* Flush output buffer */
- int fd;
- #ifdef NETCMD
- if (ttpipe)
- fd = fdout;
- else
- #endif /* NETCMD */
- fd = ttyfd;
- #ifdef Plan9
- return 0;
- #else
- #ifdef POSIX
- return(tcflush(fd,TCOFLUSH));
- #else
- #ifdef OXOS
- return(ioctl(fd,TCFLSH,1));
- #else
- return(0); /* All others, nothing */
- #endif /* OXOS */
- #endif /* POSIX */
- #endif /* Plan9 */
- }
- /* Interrupt Functions */
- /* Set up terminal interrupts on console terminal */
- #ifndef FIONREAD /* We don't need esctrp() */
- #ifndef SELECT /* if we have any of these... */
- #ifndef CK_POLL
- #ifndef RDCHK
- #ifndef OXOS
- #ifdef SVORPOSIX
- SIGTYP
- esctrp(foo) int foo; { /* trap console escapes (^) */
- signal(SIGQUIT,SIG_IGN); /* ignore until trapped */
- conesc = 1;
- debug(F101,"esctrp caught SIGQUIT","",conesc);
- }
- #endif /* SVORPOSIX */
- #endif /* OXOS */
- #ifdef V7
- #ifndef MINIX2
- SIGTYP
- esctrp(foo) int foo; { /* trap console escapes (^) */
- signal(SIGQUIT,SIG_IGN); /* ignore until trapped */
- conesc = 1;
- debug(F101,"esctrp caught SIGQUIT","",conesc);
- }
- #endif /* MINIX2 */
- #endif /* V7 */
- #ifdef C70
- SIGTYP
- esctrp(foo) int foo; { /* trap console escapes (^) */
- conesc = 1;
- signal(SIGQUIT,SIG_IGN); /* ignore until trapped */
- }
- #endif /* C70 */
- #endif /* RDCHK */
- #endif /* CK_POLL */
- #endif /* SELECT */
- #endif /* FIONREAD */
- /* C O N B G T -- Background Test */
- static int jc = 0; /* 0 = no job control */
- /*
- Call with flag == 1 to prevent signal test, which can not be expected
- to work during file transfer, when SIGINT probably *is* set to SIG_IGN.
- Call with flag == 0 to use the signal test, but only if the process-group
- test fails, as it does on some UNIX systems, where getpgrp() is buggy,
- requires an argument when the man page says it doesn't, or vice versa.
- If flag == 0 and the process-group test fails, then we determine background
- status simply (but not necessarily reliably) from isatty().
- conbgt() sets the global backgrd = 1 if we appear to be in the background,
- and to 0 if we seem to be in the foreground. conbgt() is highly prone to
- misbehavior.
- */
- VOID
- conbgt(flag) int flag; {
- int x = -1, /* process group or SIGINT test */
- y = 0; /* isatty() test */
- /*
- Check for background operation, even if not running on real tty, so that
- background flag can be set correctly. If background status is detected,
- then Kermit will not issue its interactive prompt or most messages.
- If your prompt goes away, you can blame (and fix?) this function.
- */
- /* Use process-group test if possible. */
- #ifdef POSIX /* We can do it in POSIX */
- #define PGROUP_T
- #else
- #ifdef BSD4 /* and in BSD 4.x. */
- #define PGROUP_T
- #else
- #ifdef HPUXJOBCTL /* and in most HP-UX's */
- #define PGROUP_T
- #else
- #ifdef TIOCGPGRP /* and anyplace that has this ioctl. */
- #define PGROUP_T
- #endif /* TIOCGPGRP */
- #endif /* HPUXJOBCTL */
- #endif /* BSD4 */
- #endif /* POSIX */
- #ifdef MIPS /* Except if it doesn't work... */
- #undef PGROUP_T
- #endif /* MIPS */
- #ifdef PGROUP_T
- /*
- Semi-reliable process-group test. Check whether this process's group is
- the same as the controlling terminal's process group. This works if the
- getpgrp() call doesn't lie (as it does in the SUNOS System V environment).
- */
- PID_T mypgrp = (PID_T)0; /* Kermit's process group */
- PID_T ctpgrp = (PID_T)0; /* The terminal's process group */
- #ifndef _POSIX_SOURCE
- /*
- The getpgrp() prototype is obtained from system header files for POSIX
- and Sys V R4 compilations. Other systems, who knows. Some complain about
- a duplicate declaration here, others don't, so it's safer to leave it in
- if we don't know for certain.
- */
- #ifndef SVR4
- #ifndef PS2AIX10
- #ifndef HPUX9
- extern PID_T getpgrp();
- #endif /* HPUX9 */
- #endif /* PS2AIX10 */
- #endif /* SVR4 */
- #endif /* _POSIX_SOURCE */
- /* Get my process group. */
- #ifdef SVR3 /* Maybe this should be ATTSV? */
- /* This function is not described in SVID R2 */
- mypgrp = getpgrp();
- /* debug(F101,"ATTSV conbgt process group","",(int) mypgrp); */
- #else
- #ifdef POSIX
- mypgrp = getpgrp();
- /* debug(F101,"POSIX conbgt process group","",(int) mypgrp); */
- #else
- #ifdef OSFPC
- mypgrp = getpgrp();
- /* debug(F101,"OSF conbgt process group","",(int) mypgrp); */
- #else
- #ifdef QNX
- mypgrp = getpgrp();
- /* debug(F101,"QNX conbgt process group","",(int) mypgrp); */
- #else
- #ifdef OSF32 /* (was OSF40) */
- mypgrp = getpgrp();
- /* debug(F101,"Digital UNIX conbgt process group","",(int) mypgrp); */
- #else /* BSD, V7, etc */
- #ifdef MINIX2
- mypgrp = getpgrp();
- #else
- mypgrp = getpgrp(0);
- #endif /* MINIX2 */
- /* debug(F101,"BSD conbgt process group","",(int) mypgrp); */
- #endif /* OSF32 */
- #endif /* QNX */
- #endif /* OSFPC */
- #endif /* POSIX */
- #endif /* SVR3 */
- #ifdef MINIX2
- #undef BSD44ORPOSIX
- #endif /* MINIX2 */
- /* Now get controlling tty's process group */
- #ifdef BSD44ORPOSIX
- ctpgrp = tcgetpgrp(1); /* The POSIX way */
- /* debug(F101,"POSIX conbgt terminal process group","",(int) ctpgrp); */
- #else
- ioctl(1, TIOCGPGRP, &ctpgrp); /* Or the BSD way */
- /* debug(F101,"non-POSIX conbgt terminal process group","",(int) ctpgrp); */
- #endif /* BSD44ORPOSIX */
- #ifdef MINIX2
- #define BSD44ORPOSIX
- #endif /* MINIX2 */
- if ((mypgrp > (PID_T) 0) && (ctpgrp > (PID_T) 0))
- x = (mypgrp == ctpgrp) ? 0 : 1; /* If they differ, then background. */
- else x = -1; /* If error, remember. */
- debug(F101,"conbgt process group test","",x);
- #endif /* PGROUP_T */
- /* Try to see if job control is available */
- #ifdef NOJC /* User override */
- jc = 0; /* No job control allowed */
- debug(F111,"NOJC","jc",jc);
- #else
- #ifdef BSD44
- jc = 1;
- #else
- #ifdef SVR4ORPOSIX /* POSIX actually tells us */
- debug(F100,"SVR4ORPOSIX jc test...","",0);
- #ifdef _SC_JOB_CONTROL
- #ifdef __bsdi__
- jc = 1;
- #else
- #ifdef __386BSD__
- jc = 1;
- #else
- jc = sysconf(_SC_JOB_CONTROL); /* Whatever system says */
- if (jc < 0) {
- debug(F101,"sysconf fails, jcshell","",jcshell);
- jc = (jchdlr == SIG_DFL) ? 1 : 0;
- } else
- debug(F111,"sysconf(_SC_JOB_CONTROL)","jc",jc);
- #endif /* __386BSD__ */
- #endif /* __bsdi__ */
- #else
- #ifdef _POSIX_JOB_CONTROL
- jc = 1; /* By definition */
- debug(F111,"_POSIX_JOB_CONTROL is defined","jc",jc);
- #else
- jc = 0; /* Assume job control not allowed */
- debug(F111,"SVR4ORPOSIX _SC/POSIX_JOB_CONTROL not defined","jc",jc);
- #endif /* _POSIX_JOB_CONTROL */
- #endif /* _SC_JOB_CONTROL */
- #else
- #ifdef BSD4
- jc = 1; /* Job control allowed */
- debug(F111,"BSD job control","jc",jc);
- #else
- #ifdef SVR3JC
- jc = 1; /* JC allowed */
- debug(F111,"SVR3 job control","jc",jc);
- #else
- #ifdef OXOS
- jc = 1; /* JC allowed */
- debug(F111,"X/OS job control","jc",jc);
- #else
- #ifdef HPUX9
- jc = 1; /* JC allowed */
- debug(F111,"HP-UX 9.0 job control","jc",jc);
- #else
- #ifdef HPUX10
- jc = 1; /* JC allowed */
- debug(F111,"HP-UX 10.0 job control","jc",jc);
- #else
- jc = 0; /* JC not allowed */
- debug(F111,"job control catch-all","jc",jc);
- #endif /* HPUX10 */
- #endif /* HPUX9 */
- #endif /* OXOS */
- #endif /* SVR3JC */
- #endif /* BSD4 */
- #endif /* SVR4ORPOSIX */
- #endif /* BSD44 */
- #endif /* NOJC */
- debug(F101,"conbgt jc","",jc);
- #ifndef NOJC
- debug(F101,"conbgt jcshell","",jcshell);
- /*
- At this point, if jc == 1 but jcshell == 0, it means that the OS supports
- job control, but the shell or other process we are running under does not
- (jcshell is set in sysinit()) and so if we suspend ourselves, nothing good
- will come of it. So...
- */
- if (jc < 0) jc = 0;
- if (jc > 0 && jcshell == 0) jc = 0;
- #endif /* NOJC */
- /*
- Another background test.
- Test if SIGINT (terminal interrupt) is set to SIG_IGN (ignore),
- which is done by the shell (sh) if the program is started with '&'.
- Unfortunately, this is NOT done by csh or ksh so watch out!
- Note, it's safe to set SIGINT to SIG_IGN here, because further down
- we always set it to something else.
- Note: as of 16 Jul 1999, we also skip this test if we set SIGINT to
- SIG_IGN ourselves.
- */
- if (x < 0 && !flag && !sigint_ign) { /* Didn't get good results above... */
- SIGTYP (*osigint)();
- osigint = signal(SIGINT,SIG_IGN); /* What is SIGINT set to? */
- sigint_ign = 1;
- x = (osigint == SIG_IGN) ? 1 : 0; /* SIG_IGN? */
- debug(F101,"conbgt osigint","",osigint);
- debug(F101,"conbgt signal test","",x);
- }
- /* Also check to see if we're running with redirected stdio. */
- /* This is not really background operation, but we want to act as though */
- /* it were. */
- #ifdef IKSD
- if (inserver) { /* Internet Kermit Server */
- backgrd = 0; /* is not in the background */
- return;
- }
- #endif /* IKSD */
- y = (isatty(0) && isatty(1)) ? 1 : 0;
- debug(F101,"conbgt isatty test","",y);
- #ifdef BSD29
- /* The process group and/or signal test doesn't work under these... */
- backgrd = !y;
- #else
- #ifdef sxaE50
- backgrd = !y;
- #else
- #ifdef MINIX
- backgrd = !y;
- #else
- #ifdef MINIX2
- backgrd = !y;
- #else
- if (x > -1)
- backgrd = (x || !y) ? 1 : 0;
- else backgrd = !y;
- #endif /* BSD29 */
- #endif /* sxaE50 */
- #endif /* MINIX */
- #endif /* MINIX2 */
- debug(F101,"conbgt backgrd","",backgrd);
- }
- /* C O N I N T -- Console Interrupt setter */
- /*
- First arg is pointer to function to handle SIGTERM & SIGINT (like Ctrl-C).
- Second arg is pointer to function to handle SIGTSTP (suspend).
- */
- VOID /* Set terminal interrupt traps. */
- #ifdef CK_ANSIC
- #ifdef apollo
- conint(f,s) SIGTYP (*f)(), (*s)();
- #else
- conint(SIGTYP (*f)(int), SIGTYP (*s)(int))
- #endif /* apollo */
- #else
- conint(f,s) SIGTYP (*f)(), (*s)();
- #endif /* CK_ANSIC */
- /* conint */ {
- conbgt(0); /* Do background test. */
- /* Set the desired handlers for hangup and software termination. */
- #ifdef SIGTERM
- signal(SIGTERM,f); /* Software termination */
- #endif /* SIGTERM */
- /*
- Prior to July 1999 we used to call sighup() here but now it's called in
- sysinit() so SIGHUP can be caught during execution of the init file or
- a kerbang script.
- */
- /* Now handle keyboard stop, quit, and interrupt signals. */
- /* Check if invoked in background -- if so signals set to be ignored. */
- /* However, if running under a job control shell, don't ignore them. */
- /* We won't be getting any, as we aren't in the terminal's process group. */
- debug(F101,"conint backgrd","",backgrd);
- debug(F101,"conint jc","",jc);
- if (backgrd && !jc) { /* In background, ignore signals */
- debug(F101,"conint background ignoring signals, jc","",jc);
- #ifdef SIGTSTP
- signal(SIGTSTP,SIG_IGN); /* Keyboard stop */
- #endif /* SIGTSTP */
- signal(SIGQUIT,SIG_IGN); /* Keyboard quit */
- signal(SIGINT,SIG_IGN); /* Keyboard interrupt */
- sigint_ign = 1;
- } else { /* Else in foreground or suspended */
- debug(F101,"conint foreground catching signals, jc","",jc);
- signal(SIGINT,f); /* Catch terminal interrupt */
- sigint_ign = (f == SIG_IGN) ? 1 : 0;
- #ifdef SIGTSTP /* Keyboard stop (suspend) */
- /* debug(F101,"conint SIGSTSTP","",s); */
- if (s == NULL) s = SIG_DFL;
- #ifdef NOJC /* No job control allowed. */
- signal(SIGTSTP,SIG_IGN);
- #else /* Job control allowed */
- if (jc) /* if available. */
- signal(SIGTSTP,s);
- else
- signal(SIGTSTP,SIG_IGN);
- #endif /* NOJC */
- #endif /* SIGTSTP */
- #ifndef OXOS
- #ifdef SVORPOSIX
- #ifndef FIONREAD /* Watch out, we don't know this... */
- #ifndef SELECT
- #ifndef CK_POLL
- #ifndef RDCHK
- signal(SIGQUIT,esctrp); /* Quit signal, Sys III/V. */
- #endif /* RDCHK */
- #endif /* CK_POLL */
- #endif /* SELECT */
- #endif /* FIONREAD */
- if (conesc) conesc = 0; /* Clear out pending escapes */
- #else
- #ifdef V7
- signal(SIGQUIT,esctrp); /* V7 like Sys III/V */
- if (conesc) conesc = 0;
- #else
- #ifdef aegis
- signal(SIGQUIT,f); /* Apollo, catch it like others. */
- #else
- signal(SIGQUIT,SIG_IGN); /* Others, ignore like 4D & earlier. */
- #endif /* aegis */
- #endif /* V7 */
- #endif /* SVORPOSIX */
- #endif /* OXOS */
- }
- }
- /* C O N N O I -- Reset console terminal interrupts */
- VOID
- connoi() { /* Console-no-interrupts */
- debug(F100,"connoi","",0);
- #ifdef SIGTSTP
- signal(SIGTSTP,SIG_IGN); /* Suspend */
- #endif /* SIGTSTP */
- conint(SIG_IGN,SIG_IGN); /* Interrupt */
- sigint_ign = 1; /* Remember we did this ourselves */
- #ifdef SIGQUIT
- signal(SIGQUIT,SIG_IGN); /* Quit */
- #endif /* SIGQUIT */
- #ifdef SIGTERM
- signal(SIGTERM,SIG_IGN); /* Term */
- #endif /* SIGTERM */
- }
- /* I N I T R A W Q -- Set up to read /dev/kmem for character count. */
- #ifdef V7
- /*
- Used in Version 7 to simulate Berkeley's FIONREAD ioctl call. This
- eliminates blocking on a read, because we can read /dev/kmem to get the
- number of characters available for raw input. If your system can't
- or you won't let the world read /dev/kmem then you must figure out a
- different way to do the counting of characters available, or else replace
- this by a dummy function that always returns 0.
- */
- /*
- * Call this routine as: initrawq(tty)
- * where tty is the file descriptor of a terminal. It will return
- * (as a char *) the kernel-mode memory address of the rawq character
- * count, which may then be read. It has the side-effect of flushing
- * input on the terminal.
- */
- /*
- * John Mackin, Physiology Dept., University of Sydney (Australia)
- * ...!decvax!mulga!physiol.su.oz!john
- *
- * Permission is hereby granted to do anything with this code, as
- * long as this comment is retained unmodified and no commercial
- * advantage is gained.
- */
- #ifndef MINIX
- #ifndef MINIX2
- #ifndef COHERENT
- #include <a.out.h>
- #include <sys/proc.h>
- #endif /* COHERENT */
- #endif /* MINIX2 */
- #endif /* MINIX */
- #ifdef COHERENT
- #include <l.out.h>
- #include <sys/proc.h>
- #endif /* COHERENT */
- char *
- initrawq(tty) int tty; {
- #ifdef MINIX
- return(0);
- #else
- #ifdef MINIX2
- return(0);
- #else
- #ifdef UTS24
- return(0);
- #else
- #ifdef BSD29
- return(0);
- #else
- long lseek();
- static struct nlist nl[] = {
- {PROCNAME},
- {NPROCNAME},
- {""}
- };
- static struct proc *pp;
- char *qaddr, *p, c;
- int m;
- PID_T pid, me;
- NPTYPE xproc; /* Its type is defined in makefile. */
- int catch();
- me = getpid();
- if ((m = open("/dev/kmem", 0)) < 0) err("kmem");
- nlist(BOOTNAME, nl);
- if (nl[0].n_type == 0) err("proc array");
- if (nl[1].n_type == 0) err("nproc");
- lseek(m, (long)(nl[1].n_value), 0);
- read (m, &xproc, sizeof(xproc));
- saval = signal(SIGALRM, catch);
- if ((pid = fork()) == 0) {
- while(1)
- read(tty, &c, 1);
- }
- alarm(2);
- if(setjmp(jjbuf) == 0) {
- while(1)
- read(tty, &c, 1);
- }
- signal(SIGALRM, SIG_DFL);
- #ifdef DIRECT
- pp = (struct proc *) nl[0].n_value;
- #else
- if (lseek(m, (long)(nl[0].n_value), 0) < 0L) err("seek");
- if (read(m, &pp, sizeof(pp)) != sizeof(pp)) err("no read of proc ptr");
- #endif
- lseek(m, (long)(nl[1].n_value), 0);
- read(m, &xproc, sizeof(xproc));
- if (lseek(m, (long)pp, 0) < 0L) err("Can't seek to proc");
- if ((p = malloc(xproc * sizeof(struct proc))) == NULL) err("malloc");
- if (read(m,p,xproc * sizeof(struct proc)) != xproc*sizeof(struct proc))
- err("read proc table");
- for (pp = (struct proc *)p; xproc > 0; --xproc, ++pp) {
- if (pp -> p_pid == (short) pid) goto iout;
- }
- err("no such proc");
- iout:
- close(m);
- qaddr = (char *)(pp -> p_wchan);
- free (p);
- kill(pid, SIGKILL);
- wait((WAIT_T *)0);
- return (qaddr);
- #endif
- #endif
- #endif
- #endif
- }
- /* More V7-support functions... */
- static VOID
- err(s) char *s; {
- char buf[200];
- sprintf(buf, "fatal error in initrawq: %s", s);
- perror(buf);
- doexit(1,-1);
- }
- static VOID
- catch(foo) int foo; {
- longjmp(jjbuf, -1);
- }
- /* G E N B R K -- Simulate a modem break. */
- #ifdef MINIX
- #define BSPEED B110
- #else
- #ifdef MINIX2
- #define BSPEED B110
- #else
- #define BSPEED B150
- #endif /* MINIX2 */
- #endif /* MINIX */
- #ifndef MINIX2
- VOID
- genbrk(fn,msec) int fn, msec; {
- struct sgttyb ttbuf;
- int ret, sospeed, x, y;
- ret = ioctl(fn, TIOCGETP, &ttbuf);
- sospeed = ttbuf.sg_ospeed;
- ttbuf.sg_ospeed = BSPEED;
- ret = ioctl(fn, TIOCSETP, &ttbuf);
- y = (int)strlen(brnuls);
- x = ( BSPEED * 100 ) / msec;
- if (x > y) x = y;
- ret = write(fn, brnuls, (( BSPEED * 100 ) / msec ));
- ttbuf.sg_ospeed = sospeed;
- ret = ioctl(fn, TIOCSETP, &ttbuf);
- ret = write(fn, "@", 1);
- return;
- }
- #endif /* MINIX2 */
- #ifdef MINIX2
- int
- genbrk(fn,msec) int fn, msec; {
- struct termios ttbuf;
- int ret, x, y;
- speed_t sospeed;
- ret = tcgetattr(fn, &ttbuf);
- sospeed = ttbuf.c_ospeed;
- ttbuf.c_ospeed = BSPEED;
- ret = tcsetattr(fn,TCSADRAIN, &ttbuf);
- y = (int)strlen(brnuls);
- x = ( BSPEED * 100 ) / msec;
- if (x > y) x = y;
- ret = write(fn, brnuls, (( BSPEED * 100 ) / msec ));
- ttbuf.c_ospeed = sospeed;
- ret = tcsetattr(fn, TCSADRAIN, &ttbuf);
- ret = write(fn, "@", 1);
- return ret;
- }
- #endif /* MINIX2 */
- #endif /* V7 */
- /*
- I N C H K -- Check if chars waiting to be read on given file descriptor.
- This routine is a merger of ttchk() and conchk().
- Call with:
- channel == 0 to check console.
- channel == 1 to check communications connection.
- and:
- fd = file descriptor.
- Returns:
- >= 0: number of characters waiting, 0 or greater,
- -1: on any kind of error,
- -2: if there is (definitely) no connection.
- Note: In UNIX we don't have to call nettchk() because a socket
- file descriptor works just like in serial i/o, ioctls and all.
- (But this will change if we add non-file-descriptor channels,
- such as IBM X.25 for AIX...)
- */
- static int
- in_chk(channel, fd) int channel, fd; {
- int x, n = 0; /* Workers, n = return value */
- extern int clsondisc; /* Close on disconnect */
- /*
- The first section checks to make sure we have a connection,
- but only if we're in local mode.
- */
- #ifdef DEBUG
- if (deblog) {
- char buf[16];
- sprintf(buf,"%d",fd); /* File descriptor */
- debug(F111,"in_chk entry",buf,channel);
- debug(F101,"in_chk ttyfd","",ttyfd);
- debug(F101,"in_chk ttpty","",ttpty);
- }
- #endif /* DEBUG */
- /*
- But don't say connection is gone if we have any buffered-stuff.
- */
- #ifdef TTLEBUF
- debug(F101,"in_chk ttpush","",ttpush);
- if (channel == 1) {
- if (ttpush >= 0)
- n++;
- n += le_inbuf();
- if (n > 0)
- return(n);
- }
- #endif /* TTLEBUF */
- #ifdef NETPTY
- #ifdef HAVE_PTYTRAP
- /* Special handling for HP-UX pty i/o */
- if (ttpty && pty_trap_pending(ttyfd) > 0) {
- if (pty_trap_handler(ttyfd) > 0) {
- ttclos(0);
- return(-2);
- }
- }
- #endif /* HAVE_PTYTRAP */
- #endif /* NETPTY */
- if (channel) { /* Checking communications channel */
- if (ttyfd < 0) { /* No connection */
- return(-2); /* That's what this means */
- } else if (xlocal && /* In local mode */
- !netconn && /* Serial connection */
- ttcarr != CAR_OFF /* with CARRIER WATCH ON (or AUTO) */
- #ifdef COMMENT
- #ifdef MYREAD
- /*
- Seems like this would be a good idea but it prevents C-Kermit from
- popping back to the prompt automatically when carrier drops. However,
- commenting this out prevents us from seeing the NO CARRIER message.
- Needs more work...
- */
- && my_count < 1 /* Nothing in our internal buffer */
- #endif /* MYREAD */
- #endif /* COMMENT */
- ) {
- int x;
- x = ttgmdm(); /* So get modem signals */
- if (x > -1) { /* Check for carrier */
- if (!(x & BM_DCD)) { /* No carrier */
- debug(F101,"in_chk carrier lost","",x);
- if (clsondisc) { /* If "close-on-disconnect" */
- debug(F100,"in_chk close-on-disconnect","",0);
- ttclos(0); /* close device & release lock. */
- }
- return(-2); /* This means "disconnected" */
- }
- }
- }
- }
- /* We seem to have a connection so now see if any bytes are waiting on it */
- #ifdef CK_SSL
- if (ssl_active_flag) {
- n += SSL_pending(ssl_con);
- debug(F101,"in_chk SSL_pending","",n);
- if (n < 0) /* Is this right? */
- return(-1);
- else
- return(n);
- } else if (tls_active_flag) {
- n += SSL_pending(tls_con);
- debug(F101,"in_chk TLS_pending","",n);
- if (n < 0) /* Is this right? */
- return(-1);
- else
- return(n);
- }
- #endif /* CK_SSL */
- #ifdef RLOGCODE
- #ifdef CK_KERBEROS
- /* It is not safe to read any data when using encrypted Klogin */
- if (ttnproto == NP_EK4LOGIN || ttnproto == NP_EK5LOGIN) {
- #ifdef KRB4
- if (ttnproto == NP_EK4LOGIN) {
- n += krb4_des_avail(ttyfd);
- debug(F101,"in_chk krb4_des_avail","",n);
- }
- #endif /* KRB4 */
- #ifdef KRB5
- if (ttnproto == NP_EK5LOGIN) {
- n += krb5_des_avail(ttyfd);
- debug(F101,"in_chk krb5_des_avail","",n);
- }
- #endif /* KRB5 */
- if (n < 0) /* Is this right? */
- return(-1);
- else
- return(n);
- }
- #endif /* CK_KERBEROS */
- #endif /* RLOGCODE */
- errno = 0; /* Reset this so we log good info */
- #ifdef FIONREAD
- x = ioctl(fd, FIONREAD, &n); /* BSD and lots of others */
- #ifdef DEBUG /* (the more the better) */
- if (deblog) {
- debug(F101,"in_chk FIONREAD return code","",x);
- debug(F101,"in_chk FIONREAD count","",n);
- debug(F101,"in_chk FIONREAD errno","",errno);
- }
- #endif /* DEBUG */
- #else /* FIONREAD not defined */
- /*
- Here, if (netconn && ttnet == NET_TCPB), we might try calling recvmsg()
- with flags MSG_PEEK|MSG_DONTWAIT on the socket (ttyfd), except this is not
- portable (MSG_DONTWAIT isn't defined in any of the <sys/socket.h> files
- that I looked at, but it is needed to prevent the call from blocking), and
- the msghdr struct differs from place to place, so we would need another
- avalanche of ifdefs. Still, when FIONREAD is not available, this is the
- only other known method of asking the OS for the *number* of characters
- available for reading.
- */
- #ifdef V7 /* UNIX V7: look in kernel memory */
- #ifdef MINIX
- n = 0; /* But not in MINIX */
- #else
- #ifdef MINIX2
- n = 0;
- #else
- lseek(kmem[TTY], (long) qaddr[TTY], 0); /* 7th Edition Unix */
- x = read(kmem[TTY], &n, sizeof(int));
- if (x != sizeof(int))
- n = 0;
- #endif /* MINIX2 */
- #endif /* MINIX */
- #else /* Not V7 */
- #ifdef PROVX1
- x = ioctl(fd, TIOCQCNT, &ttbuf); /* DEC Pro/3xx Venix V.1 */
- n = ttbuf.sg_ispeed & 0377; /* Circa 1984 */
- if (x < 0) n = 0;
- #else
- #ifdef MYREAD
- /*
- Here we skip all the undependable and expensive calls below if we
- already have something in our internal buffer. This tends to work quite
- nicely, so the only really bad case remaining is the one in which neither
- FIONREAD or MYREAD are defined, which is increasingly rare these days.
- */
- if (channel != 0 && my_count > 0) {
- debug(F101,"in_chk buf my_count","",my_count);
- n = my_count; /* n was 0 before we got here */
- return(n);
- }
- #endif /* MYREAD */
- /*
- rdchk(), select(), and poll() tell us *if* data is available to be read, but
- not how much, so these should be used only as a final resort. Especially
- since these calls tend to add a lot overhead.
- */
- #ifdef RDCHK /* This mostly SCO-specific */
- n = rdchk(fd);
- debug(F101,"in_chk rdchk","",n);
- #else /* No RDCHK */
- #ifdef SELECT
- #ifdef Plan9
- /* Only allows select on the console ... don't ask */
- if (channel == 0)
- #endif /* Plan9 */
- {
- fd_set rfds; /* Read file descriptors */
- #ifdef BELLV10
- FD_ZERO(rfds); /* Initialize them */
- FD_SET(fd,rfds); /* We want to look at this fd */
- #else
- FD_ZERO(&rfds); /* Initialize them */
- FD_SET(fd,&rfds); /* We want to look at this fd */
- tv.tv_sec = tv.tv_usec = 0L; /* A 0-valued timeval structure */
- #endif /* BELLV10 */
- #ifdef Plan9
- n = select( FD_SETSIZE, &rfds, (fd_set *)0, (fd_set *)0, &tv );
- debug(F101,"in_chk Plan 9 select","",n);
- #else
- #ifdef BELLV10
- n = select( 128, rfds, (fd_set *)0, (fd_set *)0, 0 );
- debug(F101,"in_chk BELLV10 select","",n);
- #else
- #ifdef BSD44
- n = select( FD_SETSIZE, &rfds, (fd_set *)0, (fd_set *)0, &tv );
- debug(F101,"in_chk BSD44 select","",n);
- #else
- #ifdef BSD43
- n = select( FD_SETSIZE, &rfds, (fd_set *)0, (fd_set *)0, &tv );
- debug(F101,"in_chk BSD43 select","",n);
- #else
- #ifdef SOLARIS
- n = select( FD_SETSIZE, &rfds, (fd_set *)0, (fd_set *)0, &tv );
- debug(F101,"in_chk SOLARIS select","",n);
- #else
- #ifdef QNX
- n = select( FD_SETSIZE, &rfds, (fd_set *)0, (fd_set *)0, &tv );
- debug(F101,"in_chk QNX select","",n);
- #else
- #ifdef COHERENT
- n = select( FD_SETSIZE, &rfds, (fd_set *)0, (fd_set *)0, &tv );