char *ckxv = "Atari ST tty I/O, 5A(086), 20 Jul 92"; /* C K S T I O */ /* C-Kermit interrupt, terminal control & i/o functions for Atari ST */ /* Author: Frank da Cruz (fdc@cunixc.cc.columbia.edu, FDCCU@CUVMA.BITNET), Columbia University Center for Computing Activities. Many other contributors. First released January 1985. Copyright (C) 1985, 1992, Trustees of Columbia University in the City of New York. Permission is granted to any individual or institution to use, copy, or redistribute this software so long as it is not sold for profit, provided this copyright notice is retained. Extensive modifications for Atari ST by: Bruce Moore (mooreb@iccgcc.decnet.ab.com). */ /* Includes for all Unixes (conditional includes come later) */ #include "ckcdeb.h" /* This moved to here. */ #include "ckcnet.h" /* Symbols for network types. */ #include /* System error numbers */ #include /* OS bindings */ #include /* Xtended BIOS */ #include /* time_t typedef, etc. */ #include /* Signals for cc trap */ #define _auxis() (!! Bconstat(1)) #define _auxos() (!! Bcostat(1)) #define _auxin() Bconin(1) #define _auxout(x) Bconout(1,x) #define _conis() (!! Bconstat(2)) #define _conos() (!! Bcostat(2)) #define _necin() (Bconin(2) & 0x7f) #define _conout(x) Bconout(2,x) /* Maximum length for the name of a tty device */ #ifndef DEVNAMLEN #define DEVNAMLEN 25 #endif #include "ckuver.h" /* Version herald */ char *ckxsys = HERALD; /* Variables available to outside world: dftty -- Pointer to default tty name string, like "/dev/tty". dfloc -- 0 if dftty is console, 1 if external line. dfprty -- Default parity dfflow -- Default flow control ckxech -- Flag for who echoes console typein: 1 - The program (system echo is turned off) 0 - The system (or front end, or terminal). functions that want to do their own echoing should check this flag before doing so. *flfnam -- Name of lock file, including its path, e.g., "/usr/spool/uucp/LCK..cul0" or "/etc/locks/tty77" *lkflfn -- Name of link to lock file, including its paths *haslock -- Flag set if this kermit established a uucp lock. backgrd -- Flag indicating program executing in background ( & on end of shell command). Used to ignore INT and QUIT signals. *rtu_bug -- Set by stptrap(). RTU treats ^Z as EOF (but only when we handle SIGTSTP) Functions for assigned communication line (either external or console tty): sysinit() -- System dependent program initialization *syscleanup() -- System dependent program shutdown ttopen(ttname,local,mdmtyp,timo) -- Open the named tty for exclusive access. ttclos() -- Close & reset the tty, releasing any access lock. *ttsspd(cps) -- Set the transmission speed of the tty. *ttgspd() -- Get (read) the the transmission speed of the tty. ttpkt(speed,flow,parity) -- Put the tty in packet mode and set the speed. ttvt(speed,flow) -- Put the tty in virtual terminal mode. or in DIALING or CONNECTED modem control state. ttres() -- Restore original tty modes. *ttscarr(carrier) -- Set carrier control mode, on/off/auto. ttinl(dest,max,timo) -- Timed read line from the tty. ttinc(timo) -- Timed read character from tty. ttchk() -- See how many characters in tty input buffer. *ttxin(n,buf) -- Read n characters from tty (untimed). ttol(string,length) -- Write a string to the tty. ttoc(c) -- Write a character to the tty. ttflui() -- Flush tty input buffer. ttsndb() -- Send BREAK signal. ttsndlb() -- Send Long BREAK signal. ttlock(ttname) -- "Lock" tty device against uucp collisions. ttunlck() -- Unlock tty device. */ /* Functions for console terminal: congm() -- Get console terminal modes. concb(esc) -- Put the console in single-character wakeup mode with no echo. conbin(esc) -- Put the console in binary (raw) mode. conres() -- Restore the console to mode obtained by congm(). conoc(c) -- Unbuffered output, one character to console. conol(s) -- Unbuffered output, null-terminated string to the console. conola(s) -- Unbuffered output, array of strings to the console. conxo(n,s) -- Unbuffered output, n characters to the console. conchk() -- Check if characters available at console (bsd 4.2). Check if escape char (^\) typed at console (System III/V). coninc(timo) -- Timed get a character from the console. congks(timo) -- Timed get keyboard scan code. conint() -- Enable terminal interrupts on the console if not background. connoi() -- Disable terminal interrupts on the console if not background. Time functions msleep(m) -- Millisecond sleep (already defined by MWC!!!) ztime(&s) -- Return pointer to date/time string rtimer() -- Reset timer gtimer() -- Get elapsed time since last call to rtimer() */ /* Declarations */ time_t time(); /* All Unixes should have this... */ extern char *malloc(), *getenv(); /* and these. */ extern int errno; /* System call error code. */ long ttgspd(); /* Declared below. */ /* dftty is the device name of the default device for file transfer */ /* dfloc is 0 if dftty is the user's console terminal, 1 if an external line */ int dfloc = 1; /* Default local(0) or remote(1) */ char *dftty = CTTNAM; /* Remote by default, use normal */ char *dfmdm = "con:"; /* controlling terminal name. */ int dfprty = 0; /* Default parity (0 = none) */ int ttprty = 0; /* Parity in use. */ static int ttpmsk = 0377; /* Parity stripping mask. */ int ttmdm = 0; /* Modem in use. */ int ttcarr = CAR_AUT; /* Carrier handling mode. */ int dfflow = 1; /* Xon/Xoff flow control */ int backgrd = 0; /* Assume in foreground (no '&' ) */ int fdflag = 0; /* Flag for redirected stdio */ int tvtflg = 0; /* Flag that ttvt has been called */ long ttspeed = -1; /* For saving speed */ int ttflow = -9; /* For saving flow */ int ttld = -1; /* Line discipline */ extern int ttnproto; extern int ttnet; int ckxech = 0; /* 0 if system normally echoes console characters, else 1 */ /* Declarations of variables global within this module */ static time_t tcount; /* Elapsed time counter */ static char /* A string of nulls */ *brnuls = "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"; /* static */ /* (Not static any more) */ int ttyfd = -1; /* TTY file descriptor */ static SIGTYP (*cc_handler) (); /* Our Ctrl-C handler */ static SIGTYP (*oldint) (); /* And the old one */ static int lkf = 0, /* Line lock flag */ cgmf = 0, /* Flag that console modes saved */ xlocal = 0, /* Flag for tty local or remote */ curcarr = 0; /* Carrier mode: require/ignore. */ static int netconn = 0; /* 1 if network socket */ static char escchr; /* Escape or attn character */ static char pushchar = 0; /* Push character */ int haslock = 0; /* =1 if this kermit locked uucp */ static int conesc = 0; /* set to 1 if esc char (^\) typed */ _PROTOTYP( static int ttlock, (char *) ); _PROTOTYP( static int ttunlck, (void) ); #ifdef CK_ANSIC static char * xxlast(char *s, char c) #else static char * xxlast(s,c) char *s; char c; #endif /* CK_ANSIC */ /* xxlast */ { /* Last occurrence of character c in string s. */ int i; for (i = strlen(s); i > 0; i--) if ( s[i-1] == c ) return( s + (i - 1) ); return(NULL); } static char ttnmsv[DEVNAMLEN]; /* copy of open path for tthang */ /* S Y S I N I T -- System-dependent program initialization. */ int sysinit() { return(0); } /* S Y S C L E A N U P -- System-dependent program cleanup. */ int syscleanup() { return(0); } /* T T O P E N -- Open a tty for exclusive access. */ /* Call with: ttname: character string - device name or network host name. lcl: If called with lcl < 0, sets value of lcl as follows: 0: the terminal named by ttname is the job's controlling terminal. 1: the terminal named by ttname is not the job's controlling terminal. But watch out: if a line is already open, or if requested line can't be opened, then lcl remains (and is returned as) -1. modem: Less than zero: ttname is a network host name. Zero or greater: ttname is a terminal device name. Zero means a local connection (don't use modem signals). Positive means use modem signals. timo: 0 = no timer. nonzero = number of seconds to wait for open() to return before timing out. Returns: 0 on success -5 if device is in use -4 if access to device is denied -3 if access to lock directory denied -2 upon timeout waiting for device to open -1 on other error */ ttopen(ttname,lcl,modem,timo) char *ttname; int *lcl, modem, timo; { if (ttyfd > -1) return(0); /* If already open, ignore this call */ ttmdm = modem; /* Make this available to other fns */ xlocal = *lcl; /* Make this available to other fns */ if (strcmp(ttname, "aux:") == 0) { if (xlocal < 0) { if (isatty(0)) /* If con: is controlling terminal */ xlocal = 1; /* ttname(aux) not controlling terminal */ else xlocal = 0; /* ttname(aux) is controlling terminal */ } } else return(-1); /* aux: is the only legal device! */ /* Got the line, now set the desired value for local. */ if (*lcl != 0) *lcl = xlocal; ttyfd = 1; /* Done, make entries in debug log, restore Ctrl-C trap, and return. */ debug(F101,"ttopen, ttyfd","",ttyfd); debug(F101," lcl","",*lcl); return(0); } /* T T C L O S -- Close the TTY, releasing any lock. */ int ttclos(foo) int foo; { /* Arg req'd for signal() prototype */ debug(F101,"ttclos ttyfd","",ttyfd); if (ttyfd < 0) return(0); /* Wasn't open. */ tvtflg = 0; if (xlocal) { debug(F100,"ttclos about to call ttres","",0); ttres(); /* Reset device modes. */ tthang(); } ttyfd = -1; /* Invalidate the file descriptor. */ debug(F100,"ttclos done","",0); return(0); } /* T T H A N G -- Hangup phone line or network connection. */ /* Returns: 0 if it does nothing. 1 if it believes that it hung up successfully. -1 if it believes that the hangup attempt failed. */ int tthang() { /* Maybe later... */ return (0); } /* T T R E S -- Restore terminal to "normal" mode. */ /* ske@pkmab.se: There are two choices for what this function should do. * (1) Restore the tty to current "normal" mode, with carrier treatment * according to ttcarr, to be used after every kermit command. (2) Restore * the tty to the state it was in before kermit opened it. These choices * conflict, since ttold can't hold both choices of tty parameters. ttres() * is currently being called as in choice (1), but ttold basically holds * the initial parameters, as in (2), and the description at the beginning * of this file says (2). * * I don't think restoring tty parameters after all kermit commands makes * much of a difference. Restoring them upon exit from kermit may be of * some use in some cases (when the line is not restored automatically on * close, by the operating system). * * I can't choose which one it should be, so I haven't changed it. It * probably works as it is, too. It would probably even work even with * ttres() entirely deleted... * * (from fdc: Actually, this function operates in remote mode too, so * it restores the console (command) terminal to whatever mode it was * in before packet operations began, so that commands work right again.) */ ttres() { /* Restore the tty to normal. */ if (ttyfd < 0) return(-1); /* Not open. */ return(0); } /* T T P K T -- Condition the communication line for packets. */ /* or for modem dialing */ #define DIALING 4 /* flags (via flow) for modem handling */ #define CONNECT 5 /* If called with speed > -1, also set the speed. */ /* Returns 0 on success, -1 on failure. */ ttpkt(speed,flow,parity) long speed; int flow, parity; { int s2; int s = 0; if (ttyfd < 0) return(-1); /* Not open. */ debug(F101,"ttpkt flow","",flow); debug(F101,"ttpkt speed","",(int) speed); debug(F101,"ttpkt flow","",flow); if (tvtflg == 0 && speed == ttspeed && flow == ttflow) return(0); /* Already been called */ ttprty = parity; /* Let other tt functions see these. */ ttpmsk = ttprty ? 0177 : 0377; /* Parity stripping mask */ ttspeed = speed; ttflow = flow; /* Now make this available too. */ if (xlocal) { s2 = (int) (speed / 10L); /* Convert bps to cps */ s = ttsspd(s2); /* Check and set the speed */ debug(F101,"ttpkt carrier","",flow); } else s = 0; tvtflg = 0; /* So ttvt() will work next time */ return(s); } /* T T V T -- Condition communication line for use as virtual terminal */ ttvt(speed,flow) long speed; int flow; { int s, s2; debug(F101,"ttvt ttyfd","",ttyfd); debug(F101,"ttvt tvtflg","",tvtflg); if (ttyfd < 0) return(-1); /* Not open. */ if (tvtflg != 0 && speed == ttspeed && flow == ttflow && ttcarr == curcarr) return(0); /* Already been called. */ if (xlocal) { /* For external lines... */ s2 = (int) (speed / 10L); s = ttsspd(s2); /* Check/set the speed */ } else s = 0; ttspeed = speed; /* Done, remember how we were */ ttflow = flow; /* called, so we can decide how to */ ttcarr = curcarr; /* respond next time. */ tvtflg = 0; debug(F101,"ttvt done","",tvtflg); return(s); } /* T T S S P D -- Checks and sets transmission rate. */ /* Call with speed in characters (not bits!) per second. */ /* Returns internal speed code if successful, -1 otherwise. */ int ttsspd(cps) int cps; { int s; debug(F101,"ttsspd","",cps); s = -1; /* First check that the given speed is valid. */ switch (cps >= 0 ? cps : (-cps)) { case 5: s = 15; break; /* Just the common ones. */ case 11: s = 13; break; case 15: s = 11; break; case 30: s = 9; break; case 60: s = 8; break; case 120: s = 7; break; case 180: s = 6; break; case 240: s = 4; break; case 480: s = 2; break; case 960: s = 1; break; case 1920: s = 0; break; default: return(-1); } if ((long) cps * 10 == ttspeed) return(s); if (cps >= 0) { Rsconf(s, !!ttflow, -1,-1,-1,-1); /* Set speed, flow */ ttspeed = (long) cps * 10; } return(s); } /* T T G S P D - Get speed of currently selected tty line */ long ttgspd() { /* Get current tty speed */ char *s; if (ttspeed == -1) { if ((s = getenv("SPEED")) || (s=getenv("BAUD")) ) ttspeed = (long) atoi(s); } return(ttspeed); } /* T T F L U I -- Flush tty input buffer */ int ttflui() { while (_auxis()) (void) _auxin(); return(0); } /* Interrupt Functions */ /* 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 conint(SIGTYP (*f)(int), SIGTYP (*s)(int)) #else conint(f,s) SIGTYP (*f)(), (*s)(); #endif /* CK_ANSIC */ /* conint */ { cc_handler = f; oldint = signal(SIGINT,f); /* Catch terminal interrupt */ } /* C O N N O I -- Reset console terminal interrupts */ VOID connoi() { /* Console-no-interrupts */ cc_handler = NULL; signal(SIGINT,oldint); /* Restore old terminal interrupt */ } /* G E N B R K -- Simulate a modem break. */ #define BSPEED 5 VOID genbrk(fn,msec) int fn, msec; { int oldspeed; int x, y; oldspeed = (int) (ttgspd() / 10); ttsspd(15); /* 150 baud */ y = strlen(brnuls); x = ( BSPEED * 100 ) / msec; if (x > y) x = y; ttol(brnuls, (( BSPEED * 100 ) / msec )); /* A plethora of nuls */ msleep(100); /* Sleep 100 ms. */ ttsspd(oldspeed); /* restore old speed */ return(0); } /* T T C H K -- Tell how many characters are waiting in tty input buffer */ /* Some callers of this want to know whether there is something to read * either in the system buffers or in our private buffers (and mostly don't * care how many characters, just whether it's more than zero or not), while * some others would be better off with the number of characters in our * private buffers only. * * Some systems can say how many characters there are in the system buffers. * Others can not. For those that can't, the number in the private buffers * will have to do (or should we put the tty into O_NDELAY-mode and try to * read one character?). If the system can tell whether there is zero or * more than zero characters, we can return 1 in the latter case even if the * private buffer is empty. (That is good for sliding windows.) */ int ttchk() { return(_auxis()); } /* T T X I N -- Get n characters from tty input buffer */ /* Returns number of characters actually gotten, or -1 on failure */ /* Intended for use only when it is known that n characters are actually */ /* Available in the input buffer. */ int ttxin(n,buf) int n; CHAR *buf; { CHAR *p; ttpmsk = (ttprty) ? 0177 : 0377; /* Parity stripping mask. */ debug(F101,"ttxin n","",n); for (p = buf; _auxis() && n--; ) *p++ = _auxin() & ttpmsk; *p = '\0'; return((int) (p - buf)); } /* T T O L -- Write string s, length n, to communication device. */ /* Returns: >= 0 on success, number of characters actually written. -1 on failure. */ int ttol(s,n) int n; char *s; { int i; for(i = n; i--; ) _auxout(*s++); return(n); } /* T T O C -- Output a character to the communication line */ /* This function should only be used for interactive, character-mode operations, like terminal connection, script execution, dialer i/o, where the overhead of the signals and alarms does not create a bottleneck. */ int #ifdef CK_ANSIC ttoc(char c) #else ttoc(c) char c; #endif /* CK_ANSIC */ /* ttoc */ { c &= 0xff; if (ttyfd < 0) return(-1); /* Check for not open. */ _auxout(c); return(0); } /* T T I N L -- Read a record (up to break character) from comm line. */ /* Reads up to "max" characters from the communication line, terminating on: (a) the packet length field if the "turn" argument is zero, or (b) on the packet-end character (eol) if the "turn" argument is nonzero and returns the number of characters read upon success, or if "max" was exceeded or the timeout interval expired before (a) or (b), returns -1. The characters that were input are copied into "dest" with their parity bits stripped if parity was selected. Returns the number of characters read. Characters after the eol are available upon the next call to this function. The idea is to minimize the number of system calls per packet, and also to minimize timeouts. This function is the inner loop of the program and must be as efficient as possible. The current strategy is to use myread(). WARNING: this function calls parchk(), which is defined in another module. Normally, ckutio.c does not depend on code from any other module, but there is an exception in this case because all the other ck?tio.c modules also need to call parchk(), so it's better to have it defined in a common place. */ #ifdef CTRLC #undef CTRLC #endif /* CTRLC */ #define CTRLC '\03' /* We have four different declarations here because: (a) to allow Kermit to be built without the automatic parity sensing feature (b) one of each type for ANSI C, one for non-ANSI. */ int #ifdef PARSENSE #ifdef CK_ANSIC ttinl(CHAR *dest, int max,int timo, CHAR eol, CHAR start, int turn) #else ttinl(dest,max,timo,eol,start,turn) int max,timo,turn; CHAR *dest, eol, start; #endif /* CK_ANSIC */ #else /* not PARSENSE */ #ifdef CK_ANSIC ttinl(CHAR *dest, int max,int timo, CHAR eol) #else ttinl(dest,max,timo,eol) int max,timo; CHAR *dest, eol; #endif /* __SDTC__ */ #endif /* PARSENSE */ /* ttinl */ { time_t tfinal; /* Time to quit */ int count; /* Number rec'd so far */ int c; /* Current character */ int ccn; /* Control-C counter */ if (ttyfd < 0) return(-1); /* Not open. */ debug(F101,"ttinl max","",max); debug(F101,"ttinl timo","",timo); ccn = 0; /* Control-C counter */ ttpmsk = (ttprty) ? 0177 : 0377; /* Parity stripping mask. */ *dest = '\0'; /* Clear destination buffer */ if (timo < 0) timo = 0; /* Safety */ tfinal = time(NULL) + timo; for (count = 0; count < max; count++) { while (timo && ! _auxis()) { /* Timed read... */ if (_conis() && (pushchar = coninc(0)) == CTRLC) { /* ^C on con?*/ if (cc_handler) { /* Handler active? */ pushchar = 0; /* Flush push character */ (* cc_handler) (SIGINT); /* Call handler */ } } if (time(NULL) > tfinal) { /* If read times out */ debug(F100,"ttinl timout","",0); debug(F111," with", dest, count); return(-1); /* Time out */ } } c = _auxin(); if ((c & 0x7f) == CTRLC) { if (++ccn > 1) { fprintf(stderr, "^C...\r\n"); /* Echo Ctrl-C */ return(-2); } } else /* Not ^C, so reset ^C counter */ ccn = 0; if ((c & 0x7f) == eol) { debug(F101,"ttinl got eol","",eol); *dest = '\0'; /* Yes, terminate the string, */ break; } *dest++ = c & ttpmsk; } return(count); } /* T T I N C -- Read a character from the communication line */ /* On success, returns the character that was read, >= 0. On failure, returns -1 or other negative myread error code. */ int ttinc(timo) int timo; { time_t tfinal; int m; if (ttyfd < 0) return(-1); /* Not open. */ ttpmsk = (ttprty) ? 0177 : 0377; /* Parity stripping mask. */ if (timo < 0) timo = 0; /* Safety */ tfinal = time(NULL) + timo; while (timo && ! _auxis()) { /* Timed read... */ if (_conis() && (pushchar = coninc(0)) == CTRLC) { /* ^C on con?*/ if (cc_handler) { /* Handler active? */ pushchar = 0; /* Flush push character */ (* cc_handler) (SIGINT); /* Call handler */ } } if (time(NULL) > tfinal) return(-1); } return(_auxin() & ttpmsk); } /* S N D B R K -- Send a BREAK signal of the given duration */ static int #ifdef CK_ANSIC sndbrk(int msec) /* Argument is milliseconds */ #else sndbrk(msec) int msec; #endif /* CK_ANSIC */ /* sndbrk */ { genbrk(ttyfd, msec); } /* T T S N D B -- Send a BREAK signal */ int ttsndb() { return(sndbrk(275)); } /* T T S N D L B -- Send a Long BREAK signal */ int ttsndlb() { return(sndbrk(1500)); } /* M S L E E P -- Millisecond version of sleep(). */ /* Call with number of milliseconds (thousandths of seconds) to sleep. Intended only for small intervals. For big ones, just use sleep(). Highly system-dependent. Returns 0 always, even if it didn't work. The problem is that MWC\msleep takes a long. Kludge, kludge! */ #ifdef GEMDOS #ifdef msleep #undef msleep #else /* msleep */ #error Must add -Dmsleep=mnap on command line! #endif /* msleep */ int mnap(m) int m; { msleep((long) m); /* Use MWC function */ } #else /* GEMDOS */ int msleep(m) int m; { clock_t elapsed; clock_t done; done = clock() + (clock_t) m / CLK_TCK; while ((elapsed = clock() - done) < 0x7FFF) ; } #endif /* GEMDOS */ /* R T I M E R -- Reset elapsed time counter */ VOID rtimer() { tcount = time( (time_t *) 0 ); } /* G T I M E R -- Get current value of elapsed time counter in seconds */ int gtimer() { int x; x = (int) (time( (time_t *) 0 ) - tcount); debug(F101,"gtimer","",x); return( (x < 0) ? 0 : x ); } /* Z T I M E -- Return date/time string */ VOID ztime(s) char **s; { char *ctime(); time_t clock_storage; clock_storage = time( (time_t *) 0 ); *s = ctime( &clock_storage ); } /* C O N G M -- Get console terminal modes. */ /* Saves initial console mode, and establishes variables for switching between current (presumably normal) mode and other modes. Should be called when program starts, but only after establishing whether program is in the foreground or background. Returns 1 if it got the modes OK, 0 if it did nothing, -1 on error. */ int congm() { return(0); } /* C O N C B -- Put console in cbreak mode. */ /* Returns 0 if ok, -1 if not */ int #ifdef CK_ANSIC concb(char esc) #else concb(esc) char esc; #endif /* CK_ANSIC */ /* concb */ { if (!isatty(0)) return(0); /* only for real ttys */ escchr = esc; /* Make this available to other fns */ ckxech = 1; /* Program can echo characters */ return(0); } /* C O N B I N -- Put console in binary mode */ /* Returns 0 if ok, -1 if not */ int #ifdef CK_ANSIC conbin(char esc) #else conbin(esc) char esc; #endif /* CK_ANSIC */ /* conbin */ { if (!isatty(0)) return(0); /* only for real ttys */ debug(F100,"conbin","",0); escchr = esc; /* Make this available to other fns */ ckxech = 1; /* Program can echo characters */ return(0); } /* C O N R E S -- Restore the console terminal */ int conres() { debug(F100,"entering conres","",0); if (!isatty(0)) return(0); /* only for real ttys */ debug(F100,"conres isatty ok","",0); ckxech = 0; /* System should echo chars */ return(0); } /* C O N O C -- Output a character to the console terminal */ int #ifdef CK_ANSIC conoc(char c) #else conoc(c) char c; #endif /* CK_ANSIC */ /* conoc */ { putchar(c); fflush(stdout); } /* C O N X O -- Write x characters to the console terminal */ int conxo(x,s) char *s; int x; { while (x--) putchar(*s++); fflush(stdout); } /* C O N O L -- Write a line to the console terminal */ int conol(s) char *s; { fputs(s, stdout); fflush(stdout); } /* C O N O L A -- Write an array of lines to the console terminal */ int conola(s) char *s[]; { int i; for (i=0 ; *s[i] ; i++) conol(s[i]); } /* C O N O L L -- Output a string followed by CRLF */ int conoll(s) char *s; { fputs(s, stdout); fputs("\r\n", stdout); } /* C O N C H K -- Return how many characters available at console */ int conchk() { if (xlocal) /* If this Kermit is running on a local box */ return(_conis()); /* Return chars available at console */ else /* This Kermit running on remote box */ return(_auxis()); /* Otherwise return chars available */ } /* C O N I N C -- Get a character from the console */ int coninc(timo) int timo; { time_t tfinal; CHAR ch; if (timo < 0) timo = 0; tfinal = time(NULL) + timo; if (pushchar) { /* Do we have a pushed character? */ ch = pushchar & 0377; /* If so, use it */ pushchar = 0; /* But only once */ } else if (xlocal) { /* If Kermit is running on local box */ if (timo) { /* If timed read... */ while (! _conis()) { /* While no console chars */ if (time(NULL) > tfinal) /* If time is up... */ return(-1); /* tell our caller */ } } ch = _necin() & 0377; } else { /* This Kermit running on remote box */ if (timo) { /* If timed read... */ while (! _auxis()) { /* While no console chars */ if (time(NULL) > tfinal) /* If time is up... */ return(-1); /* tell our caller */ } } ch = _auxin() & 0377; } if (ch == CTRLC) { /* ^C ? */ if (cc_handler) /* Handler active? */ (* cc_handler) (SIGINT); /* Call handler */ } return(ch); } /* C O N G K S -- Console Get Keyboard Scancode */ #ifndef congks /* This function needs to be filled in with the various system-dependent system calls used by SUNOS, NeXT OS, Xenix, Aviion, etc, to read a full keyboard scan code. For now, it's a dummy. */ int congks(timo) int timo; { return(coninc(timo)); } #endif /* congks */ /* T T S C A R R -- Set ttcarr variable, controlling carrier handling. * * 0 = Off: Always ignore carrier. E.g. you can connect without carrier. * 1 = On: Heed carrier, except during dialing. Carrier loss gives disconnect. * 2 = Auto: For "modem direct": The same as "Off". * For real modem types: Heed carrier during connect, but ignore * it anytime else. Compatible with pre-5A C-Kermit versions. * * As you can see, this setting does not affect dialing, which always ignores * carrier (unless there is some special exception for some modem type). It * does affect ttopen() if it is set before ttopen() is used. This setting * takes effect on the next call to ttopen()/ttpkt()/ttvt(). And they are * (or should be) always called before any communications is tried, which * means that, practically speaking, the effect is immediate. * * Of course, nothing of this applies to remote mode (xlocal = 0). * * Someone has yet to uncover how to manipulate the carrier in the BSD * environment (or any non-termio using environment). Until that time, this * will simply be a no-op for BSD. * * Note that in previous versions, the carrier was most often left unchanged * in ttpkt()/ttvt() unless they were called with DIALING or CONNECT. This * has changed. Now it is controlled by ttcarr in conjunction with these * modes. */ int ttscarr(carrier) int carrier; { ttcarr = carrier; debug(F101, "ttscarr","",ttcarr); return(ttcarr); } /* T T G M D M -- Get modem signals */ /* Looks for RS-232 modem signals, and returns those that are on in as its return value, in a bit mask composed of the BM_xxx values defined in ckcdeb.h. Returns: -3 Not implemented -2 if the communication device does not have modem control (e.g. telnet) -1 on error. >= 0 on success, with a bit mask containing the modem signals that are on. */ int ttgmdm() { return(-3); } /* P S U S P E N D -- Put this process in the background. */ /* Call with flag nonzero if suspending is allowed, zero if not allowed. Returns 0 on apparent success, -1 on failure (flag was zero, or kill() returned an error code. */ int psuspend(flag) int flag; { return(-1); }