Commit | Line | Data |
---|---|---|
ee2abe03 C |
1 | char *ckxv = "Unix tty I/O, 4C(037), 31 Jul 85"; |
2 | ||
3 | /* C K U T I O */ | |
4 | ||
5 | /* C-Kermit interrupt, terminal control & i/o functions for Unix systems */ | |
6 | ||
7 | /* | |
8 | Author: Frank da Cruz (SY.FDC@CU20B), | |
9 | Columbia University Center for Computing Activities, January 1985. | |
10 | Copyright (C) 1985, Trustees of Columbia University in the City of New York. | |
11 | Permission is granted to any individual or institution to use, copy, or | |
12 | redistribute this software so long as it is not sold for profit, provided this | |
13 | copyright notice is retained. | |
14 | */ | |
15 | /* Includes for all Unixes (conditional includes come later) */ | |
16 | ||
17 | #include <sys/types.h> /* Types */ | |
18 | #include <sys/dir.h> /* Directory */ | |
19 | #include <ctype.h> /* Character types */ | |
20 | #include <stdio.h> /* Unix Standard i/o */ | |
21 | #include <signal.h> /* Interrupts */ | |
22 | #include <setjmp.h> /* Longjumps */ | |
23 | #include "ckcdeb.h" /* Typedefs, formats for debug() */ | |
24 | ||
25 | /* Maximum length for the name of a tty device */ | |
26 | ||
27 | #ifndef DEVNAMLEN | |
28 | #define DEVNAMLEN 25 | |
29 | #endif | |
30 | ||
31 | /* 4.1 BSD support added by Charles E. Brooks, EDN-VAX */ | |
32 | /* Fortune 16:32 For:Pro 1.7 support mostly like 4.1, added by J-P Dumas */ | |
33 | ||
34 | #ifdef BSD4 | |
35 | #define ANYBSD | |
36 | #undef DIRSIZ | |
37 | #define DIRSIZ (sizeof(struct direct)) | |
38 | #ifdef MAXNAMLEN | |
39 | #define BSD42 | |
40 | char *ckxsys = " 4.2 BSD"; | |
41 | #else | |
42 | #ifdef FT17 | |
43 | #define BSD41 | |
44 | char *ckxsys = " For:Pro Fortune 1.7"; | |
45 | #else | |
46 | #define BSD41 | |
47 | #ifndef C70 | |
48 | char *ckxsys = " 4.1 BSD"; | |
49 | #endif | |
50 | #endif | |
51 | #endif | |
52 | #endif | |
53 | ||
54 | /* 2.9bsd support contributed by Bradley Smith, UCLA */ | |
55 | #ifdef BSD29 | |
56 | #define ANYBSD | |
57 | char *ckxsys = " 2.9 BSD"; | |
58 | #endif | |
59 | ||
60 | /* | |
61 | Version 7 UNIX support contributed by Gregg Wonderly, | |
62 | Oklahoma State University: gregg@okstate.csnet | |
63 | */ | |
64 | #ifdef V7 | |
65 | char *ckxsys = " Version 7 UNIX (tm)"; | |
66 | #endif V7 | |
67 | ||
68 | /* BBN C70 support from Frank Wancho, WANCHO@SIMTEL20 */ | |
69 | #ifdef C70 | |
70 | char *ckxsys = " BBN C/70"; | |
71 | #endif | |
72 | ||
73 | /* Amdahl UTS 2.4 (v7 derivative) for IBM 370 series compatible mainframes */ | |
74 | /* Contributed by Garard Gaye, Jean-Pierre Dumas, DUMAS@SUMEX-AIM. */ | |
75 | #ifdef UTS24 | |
76 | char *ckxsys = " Amdahl UTS 2.4"; | |
77 | #endif | |
78 | ||
79 | /* Pro/Venix Version 1.x support from Columbia U. */ | |
80 | #ifdef PROVX1 | |
81 | char *ckxsys = " Pro-3xx Venix v1"; | |
82 | #endif | |
83 | ||
84 | /* Tower support contributed by John Bray, Auburn, Alabama */ | |
85 | #ifdef TOWER1 | |
86 | char *ckxsys = " NCR Tower 1632, OS 1.02"; | |
87 | #endif | |
88 | ||
89 | /* Sys III/V, Xenix, PC/IX support by Herm Fischer, Encino, CA */ | |
90 | #ifdef UXIII | |
91 | #ifdef XENIX | |
92 | char *ckxsys = " Xenix/286"; | |
93 | #else | |
94 | #ifdef PCIX | |
95 | char *ckxsys = " PC/IX"; | |
96 | #else | |
97 | #ifdef ISIII | |
98 | char *ckxsys = " Interactive Systems Corp System III"; | |
99 | #else | |
100 | char *ckxsys = " AT&T System III/System V"; | |
101 | #endif | |
102 | #endif | |
103 | #endif | |
104 | #endif | |
105 | ||
106 | /* Features... */ | |
107 | ||
108 | /* Do own buffering, using unbuffered read() calls... */ | |
109 | #ifdef UXIII | |
110 | #define MYREAD | |
111 | #endif | |
112 | ||
113 | #ifdef BSD42 | |
114 | #define MYREAD | |
115 | #endif | |
116 | ||
117 | /* | |
118 | Note - KERLD is the Berkeley Unix Berknet line driver, modified to pass | |
119 | through all 8 bits, and to allow an arbitrary break character to be set. | |
120 | Don't define this symbol unless you have made this modification to your | |
121 | 4.2BSD kernel! | |
122 | */ | |
123 | #ifdef BSD4 | |
124 | /* #define KERLD */ /* <-- note, commented out */ | |
125 | #endif | |
126 | \f | |
127 | /* | |
128 | Variables available to outside world: | |
129 | ||
130 | dftty -- Pointer to default tty name string, like "/dev/tty". | |
131 | dfloc -- 0 if dftty is console, 1 if external line. | |
132 | dfprty -- Default parity | |
133 | dfflow -- Default flow control | |
134 | ckxech -- Flag for who echoes console typein: | |
135 | 1 - The program (system echo is turned off) | |
136 | 0 - The system (or front end, or terminal). | |
137 | functions that want to do their own echoing should check this flag | |
138 | before doing so. | |
139 | ||
140 | flfnam -- Name of lock file, including its path, e.g., | |
141 | "/usr/spool/uucp/LCK..cul0" or "/etc/locks/tty77" | |
142 | hasLock -- Flag set if this kermit established a uucp lock. | |
143 | inbufc -- number of tty line rawmode unread characters | |
144 | (system III/V unixes) | |
145 | backgrd -- Flag indicating program executing in background ( & on | |
146 | end of shell command). Used to ignore INT and QUIT signals. | |
147 | ||
148 | Functions for assigned communication line (either external or console tty): | |
149 | ||
150 | sysinit() -- System dependent program initialization | |
151 | ttopen(ttname,local,mdmtyp) -- Open the named tty for exclusive access. | |
152 | ttclos() -- Close & reset the tty, releasing any access lock. | |
153 | ttpkt(speed,flow) -- Put the tty in packet mode and set the speed. | |
154 | ttvt(speed,flow) -- Put the tty in virtual terminal mode. | |
155 | or in DIALING or CONNECTED modem control state. | |
156 | ttinl(dest,max,timo) -- Timed read line from the tty. | |
157 | ttinc(timo) -- Timed read character from tty. | |
158 | myread() -- System 3 raw mode bulk buffer read, gives | |
159 | -- subsequent chars one at a time and simulates | |
160 | -- FIONREAD! | |
161 | myunrd(c) -- Places c back in buffer to be read (one only) | |
162 | ttchk() -- See how many characters in tty input buffer. | |
163 | ttxin(n,buf) -- Read n characters from tty (untimed). | |
164 | ttol(string,length) -- Write a string to the tty. | |
165 | ttoc(c) -- Write a character to the tty. | |
166 | ttflui() -- Flush tty input buffer. | |
167 | ||
168 | ttlock(ttname) -- Lock against uucp collisions (Sys III) | |
169 | ttunlck() -- Unlock " " " | |
170 | look4lk(ttname) -- Check if a lock file exists | |
171 | */ | |
172 | \f | |
173 | /* | |
174 | Functions for console terminal: | |
175 | ||
176 | congm() -- Get console terminal modes. | |
177 | concb(esc) -- Put the console in single-character wakeup mode with no echo. | |
178 | conbin(esc) -- Put the console in binary (raw) mode. | |
179 | conres() -- Restore the console to mode obtained by congm(). | |
180 | conoc(c) -- Unbuffered output, one character to console. | |
181 | conol(s) -- Unbuffered output, null-terminated string to the console. | |
182 | conola(s) -- Unbuffered output, array of strings to the console. | |
183 | conxo(n,s) -- Unbuffered output, n characters to the console. | |
184 | conchk() -- Check if characters available at console (bsd 4.2). | |
185 | Check if escape char (^\) typed at console (System III/V). | |
186 | coninc(timo) -- Timed get a character from the console. | |
187 | conint() -- Enable terminal interrupts on the console if not background. | |
188 | connoi() -- Disable terminal interrupts on the console if not background. | |
189 | ||
190 | Time functions | |
191 | ||
192 | msleep(m) -- Millisecond sleep | |
193 | ztime(&s) -- Return pointer to date/time string | |
194 | rtimer() -- Reset timer | |
195 | gtimer() -- Get elapsed time since last call to rtimer() | |
196 | */ | |
197 | \f | |
198 | /* Conditional Includes */ | |
199 | ||
200 | #ifdef FT17 | |
201 | #include <sys/file.h> /* File information */ | |
202 | #endif | |
203 | ||
204 | #ifndef PROVX1 | |
205 | #include <sys/file.h> /* File information */ | |
206 | #endif | |
207 | ||
208 | /* System III, System V */ | |
209 | ||
210 | #ifdef UXIII | |
211 | #include <termio.h> | |
212 | #include <sys/ioctl.h> | |
213 | #include <fcntl.h> /* directory reading for locking */ | |
214 | #include <errno.h> /* error numbers for system returns */ | |
215 | #endif | |
216 | ||
217 | /* Not Sys III/V */ | |
218 | ||
219 | #ifndef UXIII | |
220 | #include <sgtty.h> /* Set/Get tty modes */ | |
221 | #ifndef PROVX1 | |
222 | #ifndef V7 | |
223 | #ifndef BSD41 | |
224 | #include <sys/time.h> /* Clock info (for break generation) */ | |
225 | #endif | |
226 | #endif | |
227 | #endif | |
228 | #endif | |
229 | ||
230 | #ifdef BSD41 | |
231 | #include <sys/timeb.h> /* BSD 4.1 ... ceb */ | |
232 | #endif | |
233 | ||
234 | #ifdef TOWER1 | |
235 | #include <sys/timeb.h> /* Clock info for NCR Tower */ | |
236 | #endif | |
237 | \f | |
238 | /* Declarations */ | |
239 | ||
240 | long time(); /* All Unixes should have this... */ | |
241 | extern int errno; /* System call error return */ | |
242 | ||
243 | /* Special stuff for V7 input buffer peeking */ | |
244 | ||
245 | #ifdef V7 | |
246 | int kmem[2] = { -1, -1}; | |
247 | char *initrawq(), *qaddr[2]={0,0}; | |
248 | #define CON 0 | |
249 | #define TTY 1 | |
250 | #endif | |
251 | ||
252 | /* dftty is the device name of the default device for file transfer */ | |
253 | /* dfloc is 0 if dftty is the user's console terminal, 1 if an external line */ | |
254 | ||
255 | #ifdef PROVX1 | |
256 | char *dftty = "/dev/com1.dout"; /* Only example so far of a system */ | |
257 | int dfloc = 1; /* that goes in local mode by default */ | |
258 | #else | |
259 | char *dftty = CTTNAM; /* Remote by default, use normal */ | |
260 | int dfloc = 0; /* controlling terminal name. */ | |
261 | #endif | |
262 | ||
263 | int dfprty = 0; /* Parity (0 = none) */ | |
264 | int dfflow = 1; /* Xon/Xoff flow control */ | |
265 | int backgrd = 0; /* Assume in foreground (no '&' ) */ | |
266 | ||
267 | int ckxech = 0; /* 0 if system normally echoes console characters, else 1 */ | |
268 | ||
269 | /* Declarations of variables global within this module */ | |
270 | ||
271 | static long tcount; /* Elapsed time counter */ | |
272 | ||
273 | static char *brnuls = "\0\0\0\0\0\0\0"; /* A string of nulls */ | |
274 | ||
275 | static jmp_buf sjbuf, jjbuf; /* Longjump buffer */ | |
276 | static int lkf = 0, /* Line lock flag */ | |
277 | conif = 0, /* Console interrupts on/off flag */ | |
278 | cgmf = 0, /* Flag that console modes saved */ | |
279 | xlocal = 0, /* Flag for tty local or remote */ | |
280 | ttyfd = -1; /* TTY file descriptor */ | |
281 | static char escchr; /* Escape or attn character */ | |
282 | ||
283 | /* Special line discipline, 4.2bsd only, and only with kernel mods... */ | |
284 | #ifdef KERLD | |
285 | static int kerld = 1; /* Special Kermit line discipline... */ | |
286 | struct tchars oldc, newc; /* Special characters */ | |
287 | int ld = NETLDISC; /* Really a hack to "Berknet" l.d. */ | |
288 | int oldld; /* Old discipline */ | |
289 | #else | |
290 | static int kerld = 0; /* Not selected, no special l.d. */ | |
291 | #endif | |
292 | ||
293 | #ifdef BSD42 | |
294 | static struct timeval tv; /* For getting time, from sys/time.h */ | |
295 | static struct timezone tz; | |
296 | #endif | |
297 | ||
298 | #ifdef BSD29 | |
299 | static struct timeval tv; /* For getting time, from sys/time.h */ | |
300 | static struct timezone tz; /* Same as 4.2 */ | |
301 | #endif | |
302 | ||
303 | #ifdef BSD41 | |
304 | static long clock; /* For getting time from sys/time.h */ | |
305 | static struct timeb ftp; /* And from sys/timeb.h */ | |
306 | #endif | |
307 | ||
308 | #ifdef TOWER1 | |
309 | static long clock; /* For getting time from sys/time.h */ | |
310 | static struct timeb ftp; /* And from sys/timeb.h */ | |
311 | #endif | |
312 | ||
313 | #ifdef V7 | |
314 | static long clock; | |
315 | #endif | |
316 | ||
317 | #ifdef UXIII | |
318 | static struct termio /* sgtty info... */ | |
319 | ttold, ttraw, tttvt, /* for communication line */ | |
320 | ccold, ccraw, cccbrk; /* and for console */ | |
321 | #else | |
322 | static struct sgttyb /* sgtty info... */ | |
323 | ttold, ttraw, tttvt, ttbuf, /* for communication line */ | |
324 | ccold, ccraw, cccbrk; /* and for console */ | |
325 | #endif | |
326 | ||
327 | static char flfnam[80]; /* uucp lock file path name */ | |
328 | static int hasLock = 0; /* =1 if this kermit locked uucp */ | |
329 | static int inbufc = 0; /* stuff for efficient SIII raw line */ | |
330 | static int ungotn = -1; /* pushback to unread character */ | |
331 | static int conesc = 0; /* set to 1 if esc char (^\) typed */ | |
332 | ||
333 | static int ttlock(); /* definition of ttlock subprocedure */ | |
334 | static int ttunlck(); /* and unlock subprocedure */ | |
335 | static char ttnmsv[DEVNAMLEN]; /* copy of open path for tthang */ | |
336 | \f | |
337 | /* S Y S I N I T -- System-dependent program initialization. */ | |
338 | ||
339 | sysinit() { | |
340 | ||
341 | /* for now, nothing... */ | |
342 | ||
343 | } | |
344 | \f | |
345 | /* T T O P E N -- Open a tty for exclusive access. */ | |
346 | ||
347 | /* Returns 0 on success, -1 on failure. */ | |
348 | /* | |
349 | If called with lcl < 0, sets value of lcl as follows: | |
350 | 0: the terminal named by ttname is the job's controlling terminal. | |
351 | 1: the terminal named by ttname is not the job's controlling terminal. | |
352 | But watch out: if a line is already open, or if requested line can't | |
353 | be opened, then lcl remains (and is returned as) -1. | |
354 | */ | |
355 | ttopen(ttname,lcl,modem) char *ttname; int *lcl, modem; { | |
356 | ||
357 | #ifdef UXIII | |
358 | char *ctermid(); /* Wish they all had this! */ | |
359 | #endif | |
360 | char *x; extern char* ttyname(); | |
361 | char cname[DEVNAMLEN]; | |
362 | ||
363 | if (ttyfd > -1) return(0); /* If already open, ignore this call */ | |
364 | xlocal = *lcl; /* Make this available to other fns */ | |
365 | ||
366 | #ifndef UXIII | |
367 | ttyfd = open(ttname,2); /* Try to open for read/write */ | |
368 | #else | |
369 | /* if modem connection, don't wait for carrier */ | |
370 | ttyfd = open(ttname,O_RDWR | (modem ? O_NDELAY : 0) ); | |
371 | #endif | |
372 | ||
373 | if (ttyfd < 0) { /* If couldn't open, fail. */ | |
374 | return(-1); | |
375 | } | |
376 | strncpy(ttnmsv,ttname,DEVNAMLEN); /* Open, keep copy of name locally. */ | |
377 | ||
378 | /* Caller wants us to figure out if line is controlling tty */ | |
379 | ||
380 | debug(F111,"ttopen",ttname,*lcl); | |
381 | if (*lcl == -1) { | |
382 | if (strcmp(ttname,CTTNAM) == 0) { /* "/dev/tty" always remote */ | |
383 | debug(F110," Same as CTTNAM",ttname,0); | |
384 | xlocal = 0; | |
385 | } else if (isatty(0)) { /* Else, if stdin not redirected */ | |
386 | x = ttyname(0); /* then compare its device name */ | |
387 | strncpy(cname,x,DEVNAMLEN); /* (copy from internal static buf) */ | |
388 | debug(F110," ttyname(0)",x,0); | |
389 | x = ttyname(ttyfd); /* ...with real name of ttname. */ | |
390 | xlocal = (strncmp(x,cname,DEVNAMLEN) == 0) ? 0 : 1; | |
391 | debug(F111," ttyname",x,xlocal); | |
392 | } else { /* Else, if stdin redirected... */ | |
393 | #ifdef UXIII | |
394 | /* Sys III/V provides nice ctermid() function to get name of controlling tty */ | |
395 | ctermid(cname); /* Get name of controlling terminal */ | |
396 | debug(F110," ctermid",cname,0); | |
397 | x = ttyname(ttyfd); /* Compare with name of comm line. */ | |
398 | xlocal = (strncmp(x,cname,DEVNAMLEN) == 0) ? 0 : 1; | |
399 | debug(F111," ttyname",x,xlocal); | |
400 | #else | |
401 | /* Just assume local, so "set speed" and similar commands will work */ | |
402 | /* If not really local, how could it work anyway?... */ | |
403 | xlocal = 1; | |
404 | debug(F101," redirected stdin","",xlocal); | |
405 | #endif | |
406 | } | |
407 | } | |
408 | ||
409 | /* Now check if line is locked -- if so fail, else lock for ourselves */ | |
410 | ||
411 | lkf = 0; /* Check lock */ | |
412 | if (xlocal > 0) { | |
413 | if (ttlock(ttname) < 0) { | |
414 | fprintf(stderr,"Exclusive access to %s denied\n",ttname); | |
415 | close(ttyfd); ttyfd = -1; | |
416 | debug(F110," Access denied by lock",ttname,0); | |
417 | return(-1); /* Not if already locked */ | |
418 | } else lkf = 1; | |
419 | } | |
420 | ||
421 | /* Got the line, now set the desired value for local. */ | |
422 | ||
423 | if (*lcl < 0) *lcl = xlocal; | |
424 | ||
425 | /* Some special stuff for v7... */ | |
426 | ||
427 | #ifdef V7 | |
428 | if (kmem[TTY] < 0) { /* If open, then skip this. */ | |
429 | qaddr[TTY] = initrawq(ttyfd); /* Init the queue. */ | |
430 | if ((kmem[TTY] = open("/dev/kmem", 0)) < 0) { | |
431 | fprintf(stderr, "Can't read /dev/kmem in ttopen.\n"); | |
432 | perror("/dev/kmem"); | |
433 | exit(1); | |
434 | } | |
435 | } | |
436 | #endif V7 | |
437 | ||
438 | /* Request exclusive access on systems that allow it. */ | |
439 | ||
440 | #ifndef XENIX | |
441 | /* Xenix exclusive access prevents open(close(...)) from working... */ | |
442 | #ifdef TIOCEXCL | |
443 | if (ioctl(ttyfd,TIOCEXCL, NULL) < 0) | |
444 | fprintf(stderr,"Warning, problem getting exclusive access\n"); | |
445 | #endif | |
446 | #endif | |
447 | ||
448 | /* Get tty device settings */ | |
449 | ||
450 | #ifndef UXIII | |
451 | gtty(ttyfd,&ttold); /* Get sgtty info */ | |
452 | gtty(ttyfd,&ttraw); /* And a copy of it for packets*/ | |
453 | gtty(ttyfd,&tttvt); /* And one for virtual tty service */ | |
454 | #else | |
455 | ioctl(ttyfd,TCGETA,&ttold); /* Same deal for Sys III, Sys V */ | |
456 | ioctl(ttyfd,TCGETA,&ttraw); | |
457 | ioctl(ttyfd,TCGETA,&tttvt); | |
458 | #endif | |
459 | debug(F101,"ttopen, ttyfd","",ttyfd); | |
460 | debug(F101," lcl","",*lcl); | |
461 | debug(F111," lock file",flfnam,lkf); | |
462 | return(0); | |
463 | } | |
464 | \f | |
465 | /* T T C L O S -- Close the TTY, releasing any lock. */ | |
466 | ||
467 | ttclos() { | |
468 | if (ttyfd < 0) return(0); /* Wasn't open. */ | |
469 | if (xlocal) { | |
470 | if (tthang()) /* Hang up phone line */ | |
471 | fprintf(stderr,"Warning, problem hanging up the phone\n"); | |
472 | if (ttunlck()) /* Release uucp-style lock */ | |
473 | fprintf(stderr,"Warning, problem releasing lock\n"); | |
474 | } | |
475 | ttres(); /* Reset modes. */ | |
476 | /* Relinquish exclusive access if we might have had it... */ | |
477 | #ifndef XENIX | |
478 | #ifdef TIOCEXCL | |
479 | #ifdef TIOCNXCL | |
480 | if (ioctl(ttyfd, TIOCNXCL, NULL) < 0) | |
481 | fprintf(stderr,"Warning, problem relinquishing exclusive access\n"); | |
482 | #endif | |
483 | #endif | |
484 | #endif | |
485 | close(ttyfd); /* Close it. */ | |
486 | ttyfd = -1; /* Mark it as closed. */ | |
487 | return(0); | |
488 | } | |
489 | ||
490 | /* T T H A N G -- Hangup phone line */ | |
491 | ||
492 | tthang() { | |
493 | #ifdef UXIII | |
494 | unsigned short ttc_save; | |
495 | #endif | |
496 | ||
497 | if (ttyfd < 0) return(0); /* Not open. */ | |
498 | #ifdef ANYBSD | |
499 | ioctl(ttyfd,TIOCCDTR,0); /* Clear DTR */ | |
500 | msleep(500); /* Let things settle */ | |
501 | ioctl(ttyfd,TIOCSDTR,0); /* Restore DTR */ | |
502 | #endif | |
503 | #ifdef UXIII | |
504 | ttc_save = ttraw.c_cflag; | |
505 | ttraw.c_cflag &= ~CBAUD; /* swa: set baud rate to 0 to hangup */ | |
506 | if (ioctl(ttyfd,TCSETAF,&ttraw) < 0) return(-1); /* do it */ | |
507 | msleep(100); /* let things settle */ | |
508 | ttraw.c_cflag = ttc_save; | |
509 | #ifndef XENIX /* xenix cannot do close/open when carrier drops */ | |
510 | /* following corrects a PC/IX defficiency */ | |
511 | ttc_save = fcntl(ttyfd,F_GETFL,0); | |
512 | close(ttyfd); /* close/reopen file descriptor */ | |
513 | if ((ttyfd = open(ttnmsv, ttc_save)) < 0) return(-1); | |
514 | #endif | |
515 | if (ioctl(ttyfd,TCSETAF,&ttraw) < 0) return(-1); /* un-do it */ | |
516 | #endif | |
517 | return (0); | |
518 | } | |
519 | ||
520 | ||
521 | /* T T R E S -- Restore terminal to "normal" mode. */ | |
522 | ||
523 | ttres() { /* Restore the tty to normal. */ | |
524 | if (ttyfd < 0) return(-1); /* Not open. */ | |
525 | #ifndef UXIII /* except for sIII, */ | |
526 | sleep(1); /* Wait for pending i/o to finish. */ | |
527 | #endif /* (sIII does wait in ioctls) */ | |
528 | #ifdef KERLD | |
529 | if (kerld) ioctl(ttyfd,TIOCSETD,&oldld); /* Restore old line discipline. */ | |
530 | #endif | |
531 | #ifdef UXIII | |
532 | if (ioctl(ttyfd,TCSETAW,&ttold) < 0) return(-1); /* restore termio stuff */ | |
533 | #else | |
534 | if (stty(ttyfd,&ttold) < 0) return(-1); /* Restore sgtty stuff */ | |
535 | #endif | |
536 | #ifdef KERLD | |
537 | if (kerld) ioctl(ttyfd,TIOCSETC,&oldc); /* Restore old special chars. */ | |
538 | #endif | |
539 | ||
540 | return(0); | |
541 | } | |
542 | \f | |
543 | /* Exclusive uucp file locking control */ | |
544 | /* | |
545 | by H. Fischer, creative non-Bell coding ! | |
546 | copyright rights for lock modules assigned to Columbia University | |
547 | */ | |
548 | static char * | |
549 | xxlast(s,c) char *s; char c; { /* Equivalent to strrchr() */ | |
550 | int i; | |
551 | for (i = strlen(s); i > 0; i--) | |
552 | if ( s[i-1] == c ) return( s + (i - 1) ); | |
553 | return(NULL); | |
554 | } | |
555 | static | |
556 | look4lk(ttname) char *ttname; { | |
557 | extern char *strcat(), *strcpy(); | |
558 | char *device, *devname; | |
559 | char lockfil[DIRSIZ+1]; | |
560 | ||
561 | #ifdef ISIII | |
562 | char *lockdir = "/etc/locks"; | |
563 | #else | |
564 | #ifdef ATT3BX | |
565 | char *lockdir = "/usr/spool/locks"; | |
566 | #else | |
567 | char *lockdir = "/usr/spool/uucp"; | |
568 | #endif | |
569 | #endif | |
570 | ||
571 | device = ( (devname=xxlast(ttname,'/')) != NULL ? devname+1 : ttname); | |
572 | ||
573 | #ifdef ISIII | |
574 | (void) strcpy( lockfil, device ); | |
575 | #else | |
576 | strcat( strcpy( lockfil, "LCK.." ), device ); | |
577 | #endif | |
578 | ||
579 | if (access( lockdir, 04 ) < 0) { /* read access denied on lock dir */ | |
580 | fprintf(stderr,"Warning, read access to lock directory denied\n"); | |
581 | return( 1 ); /* cannot check or set lock file */ | |
582 | } | |
583 | ||
584 | strcat(strcat(strcpy(flfnam,lockdir),"/"), lockfil); | |
585 | debug(F110,"look4lk",flfnam,0); | |
586 | ||
587 | if ( ! access( flfnam, 00 ) ) { /* print out lock file entry */ | |
588 | char lckcmd[40] ; | |
589 | strcat( strcpy(lckcmd, "ls -l ") , flfnam); | |
590 | system(lckcmd); | |
591 | if (access(flfnam,02) == 0) | |
592 | printf("(You may type \"! rm %s\" to remove this file)\n",flfnam); | |
593 | return( -1 ); | |
594 | } | |
595 | if ( access( lockdir, 02 ) < 0 ) { /* lock file cannot be written */ | |
596 | fprintf(stderr,"Warning, write access to lock directory denied\n"); | |
597 | return( 1 ); | |
598 | } | |
599 | return( 0 ); /* okay to go ahead and lock */ | |
600 | } | |
601 | \f | |
602 | /* T T L O C K */ | |
603 | ||
604 | ||
605 | static | |
606 | ttlock(ttyfd) char *ttyfd; { /* lock uucp if possible */ | |
607 | #ifdef ATT3BX | |
608 | FILE *lck_fild; | |
609 | #endif | |
610 | int lck_fil, l4l; | |
611 | int pid_buf = getpid(); /* pid to save in lock file */ | |
612 | ||
613 | hasLock = 0; /* not locked yet */ | |
614 | l4l = look4lk(ttyfd); | |
615 | if (l4l < 0) return (-1); /* already locked */ | |
616 | if (l4l == 1) return (0); /* can't read/write lock directory */ | |
617 | lck_fil = creat(flfnam, 0444); /* create lock file ... */ | |
618 | if (lck_fil < 0) return (-1); /* create of lockfile failed */ | |
619 | /* creat leaves file handle open for writing -- hf */ | |
620 | #ifdef ATT3BX | |
621 | fprintf((lck_fild = fdopen(lck_fil, "w")), "%10d\n", pid_buf); | |
622 | fflush(lck_fild); | |
623 | #else | |
624 | write (lck_fil, &pid_buf, sizeof(pid_buf) ); /* uucp expects int in file */ | |
625 | #endif | |
626 | close (lck_fil); | |
627 | hasLock = 1; /* now is locked */ | |
628 | return(0); | |
629 | } | |
630 | ||
631 | /* T T U N L O C K */ | |
632 | ||
633 | static | |
634 | ttunlck() { /* kill uucp lock if possible */ | |
635 | if (hasLock) return( unlink( flfnam ) ); | |
636 | } | |
637 | \f | |
638 | /* T T P K T -- Condition the communication line for packets. */ | |
639 | /* or for modem dialing */ | |
640 | ||
641 | #define DIALING 4 /* flags (via flow) for modem handling */ | |
642 | #define CONNECT 5 | |
643 | ||
644 | /* If called with speed > -1, also set the speed. */ | |
645 | ||
646 | /* Returns 0 on success, -1 on failure. */ | |
647 | ||
648 | ttpkt(speed,flow) int speed, flow; { | |
649 | int s; | |
650 | if (ttyfd < 0) return(-1); /* Not open. */ | |
651 | ||
652 | #ifdef KERLD | |
653 | /* Note, KERLD ignores the TANDEM, ECHO, and CRMOD bits */ | |
654 | if (kerld) { | |
655 | ioctl(ttyfd,TIOCGETD,&oldld); /* Get line discipline */ | |
656 | ioctl(ttyfd,TIOCGETC,&oldc); /* Get special chars */ | |
657 | newc = oldc; /* Copy special chars */ | |
658 | newc.t_brkc = '\r'; /* Set CR to be break character */ | |
659 | if(ioctl(ttyfd,TIOCSETC,&newc) < 0) return(-1); | |
660 | } | |
661 | #endif | |
662 | ||
663 | s = ttsspd(speed); /* Check the speed */ | |
664 | ||
665 | #ifndef UXIII | |
666 | if (flow == 1) ttraw.sg_flags |= TANDEM; /* Use XON/XOFF if selected */ | |
667 | if (flow == 0) ttraw.sg_flags &= ~TANDEM; | |
668 | ttraw.sg_flags |= RAW; /* Go into raw mode */ | |
669 | ttraw.sg_flags &= ~(ECHO|CRMOD); /* Use CR for break character */ | |
670 | #ifdef TOWER1 | |
671 | ttraw.sg_flags &= ~ANYP; /* Must tell Tower no parityr */ | |
672 | #endif | |
673 | if (s > -1) ttraw.sg_ispeed = ttraw.sg_ospeed = s; /* Do the speed */ | |
674 | if (stty(ttyfd,&ttraw) < 0) return(-1); /* Set the new modes. */ | |
675 | ||
676 | #ifdef MYREAD | |
677 | #ifdef BSD4 | |
678 | /* Try to make reads nonblocking */ | |
679 | if (kerld == 0) { | |
680 | if (fcntl(ttyfd,F_SETFL,fcntl(ttyfd,F_GETFL,0) & FNDELAY) == -1) | |
681 | return(-1); | |
682 | else return(0); | |
683 | } | |
684 | #endif | |
685 | #endif | |
686 | #endif | |
687 | ||
688 | #ifdef UXIII | |
689 | if (flow == 1) ttraw.c_iflag |= (IXON|IXOFF); | |
690 | if (flow == 0) ttraw.c_iflag &= ~(IXON|IXOFF); | |
691 | ||
692 | if (flow == DIALING) ttraw.c_cflag |= CLOCAL|HUPCL; | |
693 | if (flow == CONNECT) ttraw.c_cflag &= ~CLOCAL; | |
694 | ||
695 | ttraw.c_lflag &= ~(ICANON|ECHO); | |
696 | ttraw.c_lflag |= ISIG; /* do check for interrupt */ | |
697 | ttraw.c_iflag |= (BRKINT|IGNPAR); | |
698 | ttraw.c_iflag &= ~(IGNBRK|INLCR|IGNCR|ICRNL|IUCLC|INPCK|ISTRIP|IXANY); | |
699 | ttraw.c_oflag &= ~OPOST; | |
700 | ttraw.c_cflag &= ~(CSIZE|PARENB); | |
701 | ttraw.c_cflag |= (CS8|CREAD); | |
702 | ttraw.c_cc[4] = 1; | |
703 | ttraw.c_cc[5] = 0; | |
704 | ||
705 | if (s > -1) ttraw.c_cflag &= ~CBAUD, ttraw.c_cflag |= s; /* set speed */ | |
706 | ||
707 | if (ioctl(ttyfd,TCSETAW,&ttraw) < 0) return(-1); /* set new modes . */ | |
708 | if (flow == DIALING) { | |
709 | if (fcntl(ttyfd,F_SETFL, fcntl(ttyfd, F_GETFL, 0) & ~O_NDELAY) < 0 ) | |
710 | return(-1); | |
711 | close( open(ttnmsv,2) ); /* magic to force mode change!!! */ | |
712 | } | |
713 | #endif | |
714 | ||
715 | #ifdef KERLD | |
716 | if (kerld) { | |
717 | if (ioctl(ttyfd,TIOCSETD,&ld) < 0) | |
718 | return(-1); /* Set line discpline. */ | |
719 | } | |
720 | #endif | |
721 | ||
722 | ttflui(); /* Flush any pending input */ | |
723 | return(0); | |
724 | } | |
725 | \f | |
726 | /* T T V T -- Condition communication line for use as virtual terminal */ | |
727 | ||
728 | ttvt(speed,flow) int speed, flow; { | |
729 | int s; | |
730 | if (ttyfd < 0) return(-1); /* Not open. */ | |
731 | ||
732 | s = ttsspd(speed); /* Check the speed */ | |
733 | ||
734 | #ifndef UXIII | |
735 | if (flow == 1) tttvt.sg_flags |= TANDEM; /* XON/XOFF if selected */ | |
736 | if (flow == 0) tttvt.sg_flags &= ~TANDEM; | |
737 | tttvt.sg_flags |= RAW; /* Raw mode */ | |
738 | #ifdef TOWER1 | |
739 | tttvt.sg_flags &= ~(ECHO|ANYP); /* No echo or system III ??? parity */ | |
740 | #else | |
741 | tttvt.sg_flags &= ~ECHO; /* No echo */ | |
742 | #endif | |
743 | if (s > -1) tttvt.sg_ispeed = tttvt.sg_ospeed = s; /* Do the speed */ | |
744 | if (stty(ttyfd,&tttvt) < 0) return(-1); | |
745 | #ifdef MYREAD | |
746 | #ifdef BSD4 | |
747 | /* Make reads nonblocking */ | |
748 | if (kerld == 0) { | |
749 | if (fcntl(ttyfd,F_SETFL,fcntl(ttyfd,F_GETFL,0) & FNDELAY) == -1) | |
750 | return(-1); | |
751 | else return(0); | |
752 | } | |
753 | #endif | |
754 | #endif | |
755 | ||
756 | #else | |
757 | if (flow == 1) tttvt.c_iflag |= (IXON|IXOFF); | |
758 | if (flow == 0) tttvt.c_iflag &= ~(IXON|IXOFF); | |
759 | ||
760 | if (flow == DIALING) tttvt.c_cflag |= CLOCAL|HUPCL; | |
761 | if (flow == CONNECT) tttvt.c_cflag &= ~CLOCAL; | |
762 | ||
763 | tttvt.c_lflag &= ~(ISIG|ICANON|ECHO); | |
764 | tttvt.c_iflag |= (IGNBRK|IGNPAR); | |
765 | tttvt.c_iflag &= ~(INLCR|IGNCR|ICRNL|IUCLC|BRKINT|INPCK|ISTRIP|IXANY); | |
766 | tttvt.c_oflag &= ~OPOST; | |
767 | tttvt.c_cflag &= ~(CSIZE|PARENB); | |
768 | tttvt.c_cflag |= (CS8|CREAD); | |
769 | tttvt.c_cc[4] = 1; | |
770 | tttvt.c_cc[5] = 0; | |
771 | ||
772 | if (s > -1) tttvt.c_cflag &= ~CBAUD, tttvt.c_cflag |= s; /* set speed */ | |
773 | ||
774 | if (ioctl(ttyfd,TCSETAW,&tttvt) < 0) return(-1); /* set new modes . */ | |
775 | if (flow == DIALING) { | |
776 | if (fcntl(ttyfd,F_SETFL, fcntl(ttyfd, F_GETFL, 0) & ~O_NDELAY) < 0 ) | |
777 | return(-1); | |
778 | close( open(ttnmsv,2) ); /* magic to force mode change!!! */ | |
779 | } | |
780 | return(0); | |
781 | #endif | |
782 | } | |
783 | \f | |
784 | /* T T S S P D -- Return the internal baud rate code for 'speed'. */ | |
785 | ||
786 | ttsspd(speed) { | |
787 | int s, spdok; | |
788 | ||
789 | if (speed < 0) return(-1); | |
790 | spdok = 1; /* Assume arg ok */ | |
791 | switch (speed) { | |
792 | case 0: s = B0; break; /* Just the common ones. */ | |
793 | case 110: s = B110; break; /* The others from ttydev.h */ | |
794 | case 150: s = B150; break; /* could also be included if */ | |
795 | case 300: s = B300; break; /* necessary... */ | |
796 | case 600: s = B600; break; | |
797 | case 1200: s = B1200; break; | |
798 | case 1800: s = B1800; break; | |
799 | case 2400: s = B2400; break; | |
800 | case 4800: s = B4800; break; | |
801 | case 9600: s = B9600; break; | |
802 | #ifdef PLEXUS | |
803 | case 19200: s = EXTA; break; | |
804 | #endif | |
805 | default: | |
806 | spdok = 0; | |
807 | fprintf(stderr,"Unsupported line speed - %d\n",speed); | |
808 | fprintf(stderr,"Current speed not changed\n"); | |
809 | break; | |
810 | } | |
811 | if (spdok) return(s); else return(-1); | |
812 | } | |
813 | ||
814 | ||
815 | ||
816 | /* T T F L U I -- Flush tty input buffer */ | |
817 | ||
818 | ttflui() { | |
819 | ||
820 | #ifndef UXIII | |
821 | long n; | |
822 | #endif | |
823 | if (ttyfd < 0) return(-1); /* Not open. */ | |
824 | ||
825 | ungotn = -1; /* Initialize myread() stuff */ | |
826 | inbufc = 0; | |
827 | ||
828 | #ifdef UXIII | |
829 | if (ioctl(ttyfd,TCFLSH,0) < 0) perror("flush failed"); | |
830 | #else | |
831 | #ifdef TIOCFLUSH | |
832 | #ifdef ANYBSD | |
833 | n = FREAD; /* Specify read queue */ | |
834 | if (ioctl(ttyfd,TIOCFLUSH,&n) < 0) perror("flush failed"); | |
835 | #else | |
836 | if (ioctl(ttyfd,TIOCFLUSH,0) < 0) perror("flush failed"); | |
837 | #endif | |
838 | #endif | |
839 | #endif | |
840 | return(0); | |
841 | } | |
842 | \f | |
843 | /* Interrupt Functions */ | |
844 | ||
845 | ||
846 | /* Timeout handler for communication line input functions */ | |
847 | ||
848 | timerh() { | |
849 | longjmp(sjbuf,1); | |
850 | } | |
851 | ||
852 | ||
853 | /* Set up terminal interrupts on console terminal */ | |
854 | ||
855 | #ifdef UXIII | |
856 | esctrp() { /* trap console escapes (^\) */ | |
857 | conesc = 1; | |
858 | signal(SIGQUIT,SIG_IGN); /* ignore until trapped */ | |
859 | } | |
860 | #endif | |
861 | ||
862 | #ifdef V7 | |
863 | esctrp() { /* trap console escapes (^\) */ | |
864 | conesc = 1; | |
865 | signal(SIGQUIT,SIG_IGN); /* ignore until trapped */ | |
866 | } | |
867 | #endif | |
868 | ||
869 | #ifdef C70 | |
870 | esctrp() { /* trap console escapes (^\) */ | |
871 | conesc = 1; | |
872 | signal(SIGQUIT,SIG_IGN); /* ignore until trapped */ | |
873 | } | |
874 | #endif | |
875 | ||
876 | /* C O N I N T -- Console Interrupt setter */ | |
877 | ||
878 | conint(f) int (*f)(); { /* Set an interrupt trap. */ | |
879 | ||
880 | if (backgrd) return; /* must ignore signals in bkgrd */ | |
881 | ||
882 | /* | |
883 | Except for special cases below, ignore keyboard quit signal. | |
884 | ^\ too easily confused with connect escape, and besides, we don't want | |
885 | to leave lock files around. (Frank Prindle) | |
886 | */ | |
887 | signal(SIGQUIT,SIG_IGN); | |
888 | ||
889 | #ifdef UXIII | |
890 | signal(SIGQUIT,esctrp); /* console escape in pkt modes */ | |
891 | if (conesc) { /* clear out pending escapes */ | |
892 | conesc = 0; | |
893 | } | |
894 | #endif | |
895 | ||
896 | #ifdef V7 | |
897 | signal(SIGQUIT,esctrp); /* console escape in pkt modes */ | |
898 | if (conesc) { /* clear out pending escapes */ | |
899 | conesc = 0; | |
900 | } | |
901 | #endif | |
902 | ||
903 | if (conif) return; /* Nothing to do if already on. */ | |
904 | ||
905 | /* check if invoked in background -- if so signals set to be ignored */ | |
906 | ||
907 | if (signal(SIGINT,SIG_IGN) == SIG_IGN) { | |
908 | backgrd = 1; /* means running in background */ | |
909 | #ifdef UXIII | |
910 | signal(SIGQUIT,SIG_IGN); /* must leave signals ignored */ | |
911 | #endif | |
912 | #ifdef V7 | |
913 | signal(SIGQUIT,SIG_IGN); /* must leave signals ignored */ | |
914 | #endif | |
915 | return; | |
916 | } | |
917 | signal(SIGINT,f); /* Function to trap to on interrupt. */ | |
918 | signal(SIGHUP,f); /* Or hangup, so lock file cleared. */ | |
919 | conif = 1; /* Flag console interrupts on. */ | |
920 | } | |
921 | ||
922 | ||
923 | /* C O N N O I -- Reset console terminal interrupts */ | |
924 | ||
925 | connoi() { /* Console-no-interrupts */ | |
926 | ||
927 | if (backgrd) return; /* Ignore signals in background */ | |
928 | ||
929 | signal(SIGINT,SIG_DFL); | |
930 | signal(SIGHUP,SIG_DFL); | |
931 | signal(SIGQUIT,SIG_DFL); | |
932 | conif = 0; /* Flag interrupt trapping off */ | |
933 | } | |
934 | \f | |
935 | /* myread() -- For use by systems that can do nonblocking read() calls */ | |
936 | /* | |
937 | Returns: | |
938 | -1 if no characters available, | |
939 | -2 upon error (such as disconnect), | |
940 | otherwise value of character (0 or greater) | |
941 | */ | |
942 | myread() { | |
943 | static int inbuf_item; | |
944 | static CHAR inbuf[257]; | |
945 | CHAR readit; | |
946 | ||
947 | if (ungotn >= 0) { | |
948 | readit = ungotn; | |
949 | } else { | |
950 | if (inbufc > 0) { | |
951 | readit = inbuf[++inbuf_item]; | |
952 | } else { | |
953 | if ((inbufc = read(ttyfd,inbuf,256)) == 0) { /* end of file */ | |
954 | /* means carrier dropped on modem connection */ | |
955 | errno = 9999; /* magic number for no carrier */ | |
956 | return(-2); /* end of file has no errno */ | |
957 | } | |
958 | if (inbufc < 0) return(-2); | |
959 | readit = inbuf[inbuf_item = 0]; | |
960 | } | |
961 | inbufc--; | |
962 | } | |
963 | ungotn = -1; | |
964 | return(readit); | |
965 | } | |
966 | ||
967 | myunrd(ch) CHAR ch; { /* push back up to one character */ | |
968 | ungotn = ch; | |
969 | } | |
970 | \f | |
971 | /* I N I T R A W Q -- Set up to read /DEV/KMEM for character count. */ | |
972 | ||
973 | #ifdef V7 | |
974 | /* | |
975 | Used in Version 7 to simulate Berkeley's FIONREAD ioctl call. This | |
976 | eliminates blocking on a read, because we can read /dev/kmem to get the | |
977 | number of characters available for raw input. If your system can't | |
978 | or you won't let it read /dev/kmem (the world that is) then you must | |
979 | figure out a different way to do the counting of characters available, | |
980 | or else replace this by a dummy function that always returns 0. | |
981 | */ | |
982 | /* | |
983 | * Call this routine as: initrawq(tty) | |
984 | * where tty is the file descriptor of a terminal. It will return | |
985 | * (as a char *) the kernel-mode memory address of the rawq character | |
986 | * count, which may then be read. It has the side-effect of flushing | |
987 | * input on the terminal. | |
988 | */ | |
989 | /* | |
990 | * John Mackin, Physiology Dept., University of Sydney (Australia) | |
991 | * ...!decvax!mulga!physiol.su.oz!john | |
992 | * | |
993 | * Permission is hereby granted to do anything with this code, as | |
994 | * long as this comment is retained unmodified and no commercial | |
995 | * advantage is gained. | |
996 | */ | |
997 | #include <a.out.h> | |
998 | #include <sys/proc.h> | |
999 | ||
1000 | char *initrawq(tty) int tty; { | |
1001 | #ifdef UTS24 | |
1002 | return(0); | |
1003 | #else | |
1004 | #ifdef BSD29 | |
1005 | return(0); | |
1006 | #else | |
1007 | long lseek(); | |
1008 | static struct nlist nl[] = { | |
1009 | {PROCNAME}, | |
1010 | {NPROCNAME}, | |
1011 | {""} | |
1012 | }; | |
1013 | static struct proc *pp; | |
1014 | char *malloc(), *qaddr, *p, c; | |
1015 | int m, pid, me; | |
1016 | NPTYPE xproc; /* Its type is defined in makefile. */ | |
1017 | int catch(); | |
1018 | ||
1019 | me = getpid(); | |
1020 | if ((m = open("/dev/kmem", 0)) < 0) err("kmem"); | |
1021 | nlist(BOOTNAME, nl); | |
1022 | if (nl[0].n_type == 0) err("proc array"); | |
1023 | ||
1024 | if (nl[1].n_type == 0) err("nproc"); | |
1025 | \f | |
1026 | lseek(m, (long)(nl[1].n_value), 0); | |
1027 | read (m, &xproc, sizeof(xproc)); | |
1028 | signal(SIGALRM, catch); | |
1029 | if ((pid = fork()) == 0) { | |
1030 | while(1) | |
1031 | read(tty, &c, 1); | |
1032 | } | |
1033 | alarm(2); | |
1034 | ||
1035 | if(setjmp(jjbuf) == 0) { | |
1036 | while(1) | |
1037 | read(tty, &c, 1); | |
1038 | } | |
1039 | signal(SIGALRM, SIG_DFL); | |
1040 | ||
1041 | #ifdef DIRECT | |
1042 | pp = (struct proc *) nl[0].n_value; | |
1043 | #else | |
1044 | if (lseek(m, (long)(nl[0].n_value), 0) < 0L) err("seek"); | |
1045 | if (read(m, &pp, sizeof(pp)) != sizeof(pp)) err("no read of proc ptr"); | |
1046 | #endif | |
1047 | lseek(m, (long)(nl[1].n_value), 0); | |
1048 | read(m, &xproc, sizeof(xproc)); | |
1049 | ||
1050 | if (lseek(m, (long)pp, 0) < 0L) err("Can't seek to proc"); | |
1051 | if ((p = malloc(xproc * sizeof(struct proc))) == NULL) err("malloc"); | |
1052 | if (read(m,p,xproc * sizeof(struct proc)) != xproc*sizeof(struct proc)) | |
1053 | err("read proc table"); | |
1054 | for (pp = (struct proc *)p; xproc > 0; --xproc, ++pp) { | |
1055 | if (pp -> p_pid == (short) pid) goto iout; | |
1056 | } | |
1057 | err("no such proc"); | |
1058 | ||
1059 | iout: | |
1060 | close(m); | |
1061 | qaddr = (char *)(pp -> p_wchan); | |
1062 | free (p); | |
1063 | kill(pid, SIGKILL); | |
1064 | wait((int *)0); /* Destroy the ZOMBIEs! */ | |
1065 | return (qaddr); | |
1066 | #endif | |
1067 | #endif | |
1068 | } | |
1069 | \f | |
1070 | /* More V7-support functions... */ | |
1071 | ||
1072 | static | |
1073 | err(s) char *s; { | |
1074 | char buf[200]; | |
1075 | ||
1076 | sprintf(buf, "fatal error in initrawq: %s", s); | |
1077 | perror(buf); | |
1078 | doexit(1); | |
1079 | } | |
1080 | ||
1081 | static | |
1082 | catch() { | |
1083 | longjmp(jjbuf, -1); | |
1084 | } | |
1085 | ||
1086 | ||
1087 | /* G E N B R K -- Simulate a modem break. */ | |
1088 | ||
1089 | #define BSPEED B150 | |
1090 | ||
1091 | genbrk(fn) int fn; { | |
1092 | struct sgttyb ttbuf; | |
1093 | int ret, sospeed; | |
1094 | ||
1095 | ret = ioctl(fn, TIOCGETP, &ttbuf); | |
1096 | sospeed = ttbuf.sg_ospeed; | |
1097 | ttbuf.sg_ospeed = BSPEED; | |
1098 | ret = ioctl(fn, TIOCSETP, &ttbuf); | |
1099 | ret = write(fn, "\0\0\0\0\0\0\0\0\0\0\0\0", 8); | |
1100 | ttbuf.sg_ospeed = sospeed; | |
1101 | ret = ioctl(fn, TIOCSETP, &ttbuf); | |
1102 | ret = write(fn, "@", 1); | |
1103 | return; | |
1104 | } | |
1105 | #endif V7 | |
1106 | \f | |
1107 | /* T T C H K -- Tell how many characters are waiting in tty input buffer */ | |
1108 | ||
1109 | ttchk() { | |
1110 | int x; long n; | |
1111 | #ifdef FIONREAD | |
1112 | x = ioctl(ttyfd, FIONREAD, &n); /* Berkeley and maybe some others */ | |
1113 | debug(F101,"ttchk","",n); | |
1114 | return((x < 0) ? 0 : n); | |
1115 | #else | |
1116 | #ifdef V7 | |
1117 | lseek(kmem[TTY], (long) qaddr[TTY], 0); | |
1118 | x = read(kmem[TTY], &n, sizeof(int)); | |
1119 | return((x == sizeof(int))? n: 0); | |
1120 | #else V7 | |
1121 | #ifdef UXIII | |
1122 | return(inbufc + (ungotn >= 0) ); | |
1123 | #else | |
1124 | #ifdef C70 | |
1125 | return(inbufc + (ungotn >= 0) ); | |
1126 | #else | |
1127 | #ifdef PROVX1 | |
1128 | x = ioctl(ttyfd, TIOCQCNT, &ttbuf); | |
1129 | n = ttbuf.sg_ispeed & 0377; | |
1130 | return((x < 0) ? 0 : n); | |
1131 | #else | |
1132 | return(0); | |
1133 | #endif | |
1134 | #endif | |
1135 | #endif | |
1136 | #endif | |
1137 | #endif | |
1138 | } | |
1139 | ||
1140 | ||
1141 | /* T T X I N -- Get n characters from tty input buffer */ | |
1142 | ||
1143 | /* Returns number of characters actually gotten, or -1 on failure */ | |
1144 | ||
1145 | /* Intended for use only when it is known that n characters are actually */ | |
1146 | /* Available in the input buffer. */ | |
1147 | ||
1148 | ttxin(n,buf) int n; char *buf; { | |
1149 | int x; | |
1150 | CHAR c; | |
1151 | ||
1152 | #ifdef MYREAD | |
1153 | for( x = 0; (x > -1) && (x < n); buf[x++] = myread() ); | |
1154 | #else | |
1155 | debug(F101,"ttxin: n","",n); | |
1156 | x = read(ttyfd,buf,n); | |
1157 | debug(F101," x","",x); | |
1158 | #endif | |
1159 | if (x > 0) buf[x] = '\0'; | |
1160 | if (x < 0) x = -1; | |
1161 | return(x); | |
1162 | } | |
1163 | \f | |
1164 | /* T T O L -- Similar to "ttinl", but for writing. */ | |
1165 | ||
1166 | ttol(s,n) int n; char *s; { | |
1167 | int x; | |
1168 | if (ttyfd < 0) return(-1); /* Not open. */ | |
1169 | x = write(ttyfd,s,n); | |
1170 | debug(F111,"ttol",s,n); | |
1171 | if (x < 0) debug(F101,"ttol failed","",x); | |
1172 | return(x); | |
1173 | } | |
1174 | ||
1175 | ||
1176 | /* T T O C -- Output a character to the communication line */ | |
1177 | ||
1178 | ttoc(c) char c; { | |
1179 | if (ttyfd < 0) return(-1); /* Not open. */ | |
1180 | return(write(ttyfd,&c,1)); | |
1181 | } | |
1182 | \f | |
1183 | /* T T I N L -- Read a record (up to break character) from comm line. */ | |
1184 | /* | |
1185 | If no break character encountered within "max", return "max" characters, | |
1186 | with disposition of any remaining characters undefined. Otherwise, return | |
1187 | the characters that were read, including the break character, in "dest" and | |
1188 | the number of characters read as the value of function, or 0 upon end of | |
1189 | file, or -1 if an error occurred. Times out & returns error if not completed | |
1190 | within "timo" seconds. | |
1191 | */ | |
1192 | ||
1193 | ttinl(dest,max,timo,eol) int max,timo; char *dest; char eol; { | |
1194 | int x, y; | |
1195 | CHAR c; | |
1196 | ||
1197 | if (ttyfd < 0) return(-1); /* Not open. */ | |
1198 | if (timo <= 0) { /* Untimed read... */ | |
1199 | ||
1200 | #ifdef MYREAD | |
1201 | for (x = y = 0; (x < max) && (c != eol); x++) { | |
1202 | while ((y = myread()) == -1) ; | |
1203 | if (y == -2) return(-1); | |
1204 | dest[x] = y & 0377; | |
1205 | } | |
1206 | #else | |
1207 | x = read(ttyfd,dest,max); /* Try to read. */ | |
1208 | #endif | |
1209 | return(x); /* Return the count. */ | |
1210 | } | |
1211 | ||
1212 | /* Timed read... */ | |
1213 | ||
1214 | signal(SIGALRM,timerh); /* Set up timeout action. */ | |
1215 | alarm(timo); /* Set the timer. */ | |
1216 | if (setjmp(sjbuf)) /* Do this if timer went off. */ | |
1217 | x = -1; | |
1218 | else if (kerld) { /* Efficient Kermit line discipline */ | |
1219 | x = read(ttyfd,dest,max); /* for 4.2bsd only... */ | |
1220 | } else { /* Normal case... */ | |
1221 | for (x = c = y = 0; (x < max) && (c != eol); x++) { | |
1222 | #ifdef MYREAD | |
1223 | while ((y = myread()) == -1) /* Use own buffering if we can */ | |
1224 | ; | |
1225 | if (y == -2) y++; | |
1226 | c = y & 0377; | |
1227 | #else | |
1228 | while ((y = read(ttyfd,&c,1)) == 0) /* Else call system */ | |
1229 | ; /* ...for each character. */ | |
1230 | #endif | |
1231 | if (y < 0) { | |
1232 | alarm(0); /* Error, turn off timer, */ | |
1233 | signal(SIGALRM,SIG_DFL); /* and associated interrupt. */ | |
1234 | return(y); /* Return the error indication. */ | |
1235 | } | |
1236 | dest[x] = c; | |
1237 | } | |
1238 | x++; | |
1239 | } | |
1240 | alarm(0); /* Success, turn off timer, */ | |
1241 | signal(SIGALRM,SIG_DFL); /* and associated interrupt. */ | |
1242 | return(x); /* Return the count. */ | |
1243 | } | |
1244 | \f | |
1245 | /* T T I N C -- Read a character from the communication line */ | |
1246 | ||
1247 | ttinc(timo) int timo; { | |
1248 | int n = 0; | |
1249 | CHAR ch = 0; | |
1250 | ||
1251 | if (ttyfd < 0) return(-1); /* Not open. */ | |
1252 | if (timo <= 0) { /* Untimed. */ | |
1253 | #ifdef MYREAD | |
1254 | /* comm line failure returns -1 thru myread, so no &= 0377 */ | |
1255 | while ((n = myread()) == -1) ; /* Wait for a character... */ | |
1256 | if (n == -2) n++; | |
1257 | return( n ); | |
1258 | #else | |
1259 | while ((n = read(ttyfd,&ch,1)) == 0) ; /* Wait for a character. */ | |
1260 | return( (n > 0) ? (ch & 0377) : n ); | |
1261 | #endif | |
1262 | } | |
1263 | ||
1264 | signal(SIGALRM,timerh); /* Timed, set up timer. */ | |
1265 | alarm(timo); | |
1266 | if (setjmp(sjbuf)) { | |
1267 | n = -1; | |
1268 | } else { | |
1269 | #ifdef MYREAD | |
1270 | while ((n = myread()) == -1) ; /* If managing own buffer... */ | |
1271 | if (n == -2) { | |
1272 | n++; | |
1273 | } else { | |
1274 | ch = n; | |
1275 | n = 1; | |
1276 | } | |
1277 | #else | |
1278 | n = read(ttyfd,&ch,1); /* Otherwise call the system. */ | |
1279 | #endif | |
1280 | } | |
1281 | alarm(0); /* Turn off timer, */ | |
1282 | signal(SIGALRM,SIG_DFL); /* and interrupt. */ | |
1283 | return( (n > 0) ? (ch & 0377) : n ); /* Return char or -1. */ | |
1284 | } | |
1285 | \f | |
1286 | /* T T S N D B -- Send a BREAK signal */ | |
1287 | ||
1288 | ttsndb() { | |
1289 | int x; long n; char spd; | |
1290 | ||
1291 | if (ttyfd < 0) return(-1); /* Not open. */ | |
1292 | ||
1293 | #ifdef PROVX1 | |
1294 | gtty(ttyfd,&ttbuf); /* Get current tty flags */ | |
1295 | spd = ttbuf.sg_ospeed; /* Save speed */ | |
1296 | ttbuf.sg_ospeed = B50; /* Change to 50 baud */ | |
1297 | stty(ttyfd,&ttbuf); /* ... */ | |
1298 | write(ttyfd,brnuls,3); /* Send 3 nulls */ | |
1299 | ttbuf.sg_ospeed = spd; /* Restore speed */ | |
1300 | stty(ttyfd,&ttbuf); /* ... */ | |
1301 | return(0); | |
1302 | #else | |
1303 | #ifdef UXIII | |
1304 | if (ioctl(ttyfd,TCSBRK,(char *)0) < 0) { /* Send a BREAK */ | |
1305 | perror("Can't send BREAK"); | |
1306 | return(-1); | |
1307 | } | |
1308 | return(0); | |
1309 | #else | |
1310 | #ifdef ANYBSD | |
1311 | n = FWRITE; /* Flush output queue. */ | |
1312 | ioctl(ttyfd,TIOCFLUSH,&n); /* Ignore any errors.. */ | |
1313 | if (ioctl(ttyfd,TIOCSBRK,(char *)0) < 0) { /* Turn on BREAK */ | |
1314 | perror("Can't send BREAK"); | |
1315 | return(-1); | |
1316 | } | |
1317 | x = msleep(275); /* Sleep for so many milliseconds */ | |
1318 | if (ioctl(ttyfd,TIOCCBRK,(char *)0) < 0) { /* Turn off BREAK */ | |
1319 | perror("BREAK stuck!!!"); | |
1320 | doexit(1); /* Get out, closing the line. */ | |
1321 | /* with exit status = 1 */ | |
1322 | } | |
1323 | return(x); | |
1324 | #else | |
1325 | #ifdef V7 | |
1326 | genbrk(ttyfd); /* Simulate a BREAK */ | |
1327 | return(x); | |
1328 | #endif | |
1329 | #endif | |
1330 | #endif | |
1331 | #endif | |
1332 | } | |
1333 | \f | |
1334 | /* M S L E E P -- Millisecond version of sleep(). */ | |
1335 | ||
1336 | /* | |
1337 | Intended only for small intervals. For big ones, just use sleep(). | |
1338 | */ | |
1339 | ||
1340 | msleep(m) int m; { | |
1341 | ||
1342 | #ifdef PROVX1 | |
1343 | sleep(-((m * 60 + 500) / 1000)); | |
1344 | return(0); | |
1345 | #endif | |
1346 | ||
1347 | #ifdef ANYBSD | |
1348 | int t1, t3, t4; | |
1349 | #ifdef BSD41 | |
1350 | if (ftime(&ftp) < 0) return(-1); /* Get current time. */ | |
1351 | t1 = ((ftp.time & 0xff) * 1000) + ftp.millitm; | |
1352 | while (1) { | |
1353 | ftime(&ftp); /* new time */ | |
1354 | t3 = (((ftp.time & 0xff) * 1000) + ftp.millitm) - t1; | |
1355 | if (t3 > m) return (t3); | |
1356 | } | |
1357 | #else | |
1358 | /* 2.9 and 4.1 BSD do it this way */ | |
1359 | if (gettimeofday(&tv, &tz) < 0) return(-1); /* Get current time. */ | |
1360 | t1 = tv.tv_sec; /* Seconds */ | |
1361 | ||
1362 | tv.tv_sec = 0; /* Use select() */ | |
1363 | tv.tv_usec = m * 1000; | |
1364 | return(select( 0, (int *)0, (int *)0, (int *)0, &tv) ); | |
1365 | #endif | |
1366 | #endif | |
1367 | ||
1368 | #ifdef UXIII | |
1369 | #ifdef XENIX | |
1370 | #define CLOCK_TICK 50 /* millisecs per clock tick */ | |
1371 | #else | |
1372 | #define CLOCK_TICK 17 /* 1/60 sec */ | |
1373 | #endif | |
1374 | extern long times(); | |
1375 | long t1, t2, tarray[4]; | |
1376 | int t3; | |
1377 | ||
1378 | if ((t1 = times(tarray)) < 0) return(-1); | |
1379 | while (1) { | |
1380 | if ((t2 = times(tarray)) < 0) return(-1); | |
1381 | t3 = ((int)(t2 - t1)) * CLOCK_TICK; | |
1382 | if (t3 > m) return(t3); | |
1383 | } | |
1384 | #endif | |
1385 | ||
1386 | #ifdef TOWER1 | |
1387 | int t1, t3; | |
1388 | if (ftime(&ftp) < 0) return(-1); /* Get current time. */ | |
1389 | t1 = ((ftp.time & 0xff) * 1000) + ftp.millitm; | |
1390 | while (1) { | |
1391 | ftime(&ftp); /* new time */ | |
1392 | t3 = (((ftp.time & 0xff) * 1000) + ftp.millitm) - t1; | |
1393 | if (t3 > m) return (t3); | |
1394 | } | |
1395 | #endif | |
1396 | } | |
1397 | \f | |
1398 | /* R T I M E R -- Reset elapsed time counter */ | |
1399 | ||
1400 | rtimer() { | |
1401 | tcount = time( (long *) 0 ); | |
1402 | } | |
1403 | ||
1404 | ||
1405 | /* G T I M E R -- Get current value of elapsed time counter in seconds */ | |
1406 | ||
1407 | gtimer() { | |
1408 | int x; | |
1409 | x = (int) (time( (long *) 0 ) - tcount); | |
1410 | rtimer(); | |
1411 | return( (x < 0) ? 0 : x ); | |
1412 | } | |
1413 | ||
1414 | ||
1415 | /* Z T I M E -- Return date/time string */ | |
1416 | ||
1417 | ztime(s) char **s; { | |
1418 | ||
1419 | #ifdef UXIII | |
1420 | extern long time(); /* Sys III/V way to do it */ | |
1421 | char *ctime(); | |
1422 | long clock_storage; | |
1423 | ||
1424 | clock_storage = time( (long *) 0 ); | |
1425 | *s = ctime( &clock_storage ); | |
1426 | #endif | |
1427 | ||
1428 | #ifdef PROVX1 | |
1429 | int utime[2]; /* Venix way */ | |
1430 | time(utime); | |
1431 | *s = ctime(utime); | |
1432 | #endif | |
1433 | ||
1434 | #ifdef ANYBSD | |
1435 | char *asctime(); /* Berkeley way */ | |
1436 | struct tm *localtime(); | |
1437 | struct tm *tp; | |
1438 | #ifndef BSD41 | |
1439 | gettimeofday(&tv, &tz); /* BSD 2.9, 4.2 ... */ | |
1440 | time(&tv.tv_sec); | |
1441 | tp = localtime(&tv.tv_sec); | |
1442 | #else | |
1443 | time(&clock); /* BSD 4.1 ... ceb */ | |
1444 | tp = localtime(&clock); | |
1445 | #endif | |
1446 | *s = asctime(tp); | |
1447 | #endif | |
1448 | ||
1449 | #ifdef TOWER1 | |
1450 | char *asctime(); /* Tower way */ | |
1451 | struct tm *localtime(); | |
1452 | struct tm *tp; | |
1453 | ||
1454 | time(&clock); | |
1455 | tp = localtime(&clock); | |
1456 | *s = asctime(tp); | |
1457 | #endif | |
1458 | #ifdef V7 | |
1459 | char *asctime(); /* V7 way */ | |
1460 | struct tm *localtime(); | |
1461 | struct tm *tp; | |
1462 | ||
1463 | time(&clock); | |
1464 | tp = localtime(&clock); | |
1465 | *s = asctime(tp); | |
1466 | #endif | |
1467 | } | |
1468 | \f | |
1469 | /* C O N G M -- Get console terminal modes. */ | |
1470 | ||
1471 | /* | |
1472 | Saves current console mode, and establishes variables for switching between | |
1473 | current (presumably normal) mode and other modes. | |
1474 | */ | |
1475 | ||
1476 | congm() { | |
1477 | #ifndef UXIII | |
1478 | gtty(0,&ccold); /* Structure for restoring */ | |
1479 | gtty(0,&cccbrk); /* For setting CBREAK mode */ | |
1480 | gtty(0,&ccraw); /* For setting RAW mode */ | |
1481 | #else | |
1482 | ioctl(0,TCGETA,&ccold); | |
1483 | ioctl(0,TCGETA,&cccbrk); | |
1484 | ioctl(0,TCGETA,&ccraw); | |
1485 | #endif | |
1486 | cgmf = 1; /* Flag that we got them. */ | |
1487 | } | |
1488 | ||
1489 | ||
1490 | /* C O N C B -- Put console in cbreak mode. */ | |
1491 | ||
1492 | /* Returns 0 if ok, -1 if not */ | |
1493 | ||
1494 | concb(esc) char esc; { | |
1495 | int x; | |
1496 | if (cgmf == 0) congm(); /* Get modes if necessary. */ | |
1497 | escchr = esc; /* Make this available to other fns */ | |
1498 | ckxech = 1; /* Program can echo characters */ | |
1499 | #ifndef UXIII | |
1500 | cccbrk.sg_flags |= CBREAK; /* Set to character wakeup, */ | |
1501 | cccbrk.sg_flags &= ~ECHO; /* no echo. */ | |
1502 | x = stty(0,&cccbrk); | |
1503 | #else | |
1504 | cccbrk.c_lflag &= ~(ICANON|ECHO); | |
1505 | cccbrk.c_cc[0] = 003; /* interrupt char is control-c */ | |
1506 | cccbrk.c_cc[1] = escchr; /* escape during packet modes */ | |
1507 | cccbrk.c_cc[4] = 1; | |
1508 | cccbrk.c_cc[5] = 1; | |
1509 | x = ioctl(0,TCSETAW,&cccbrk); /* set new modes . */ | |
1510 | #endif | |
1511 | if (x > -1) setbuf(stdout,NULL); /* Make console unbuffered. */ | |
1512 | #ifdef V7 | |
1513 | if (kmem[CON] < 0) { | |
1514 | qaddr[CON] = initrawq(0); | |
1515 | if((kmem[CON] = open("/dev/kmem", 0)) < 0) { | |
1516 | fprintf(stderr, "Can't read /dev/kmem in concb.\n"); | |
1517 | perror("/dev/kmem"); | |
1518 | exit(1); | |
1519 | } | |
1520 | } | |
1521 | #endif V7 | |
1522 | return(x); | |
1523 | } | |
1524 | \f | |
1525 | /* C O N B I N -- Put console in binary mode */ | |
1526 | ||
1527 | /* Returns 0 if ok, -1 if not */ | |
1528 | ||
1529 | conbin(esc) char esc; { | |
1530 | if (cgmf == 0) congm(); /* Get modes if necessary. */ | |
1531 | escchr = esc; /* Make this available to other fns */ | |
1532 | ckxech = 1; /* Program can echo characters */ | |
1533 | #ifndef UXIII | |
1534 | ccraw.sg_flags |= (RAW|TANDEM); /* Set rawmode, XON/XOFF */ | |
1535 | ccraw.sg_flags &= ~(ECHO|CRMOD); /* Set char wakeup, no echo */ | |
1536 | return(stty(0,&ccraw)); | |
1537 | #else | |
1538 | ccraw.c_lflag &= ~(ISIG|ICANON|ECHO); | |
1539 | ccraw.c_iflag |= (BRKINT|IGNPAR); | |
1540 | ccraw.c_iflag &= ~(IGNBRK|INLCR|IGNCR|ICRNL|IUCLC|IXON|IXANY|IXOFF | |
1541 | |INPCK|ISTRIP); | |
1542 | ccraw.c_oflag &= ~OPOST; | |
1543 | ||
1544 | /*** Kermit used to put the console in 8-bit raw mode, but some users have | |
1545 | *** pointed out that this should not be done, since some sites actually | |
1546 | *** use terminals with parity settings on their Unix systems, and if we | |
1547 | *** override the current settings and stop doing parity, then their terminals | |
1548 | *** will display blotches for characters whose parity is wrong. Therefore, | |
1549 | *** the following two lines are commented out (Larry Afrin, Clemson U): | |
1550 | *** | |
1551 | *** ccraw.c_cflag &= ~(PARENB|CSIZE); | |
1552 | *** ccraw.c_cflag |= (CS8|CREAD); | |
1553 | *** | |
1554 | *** Sys III/V sites that have trouble with this can restore these lines. | |
1555 | ***/ | |
1556 | ccraw.c_cc[4] = 1; | |
1557 | ccraw.c_cc[5] = 1; | |
1558 | return(ioctl(0,TCSETAW,&ccraw) ); /* set new modes . */ | |
1559 | #endif | |
1560 | } | |
1561 | ||
1562 | ||
1563 | /* C O N R E S -- Restore the console terminal */ | |
1564 | ||
1565 | conres() { | |
1566 | if (cgmf == 0) return(0); /* Don't do anything if modes */ | |
1567 | #ifndef UXIII /* except for sIII, */ | |
1568 | sleep(1); /* not known! */ | |
1569 | #endif /* (sIII does wait in ioctls) */ | |
1570 | ckxech = 0; /* System should echo chars */ | |
1571 | #ifndef UXIII | |
1572 | return(stty(0,&ccold)); /* Restore controlling tty */ | |
1573 | #else | |
1574 | return(ioctl(0,TCSETAW,&ccold)); | |
1575 | #endif | |
1576 | } | |
1577 | \f | |
1578 | /* C O N O C -- Output a character to the console terminal */ | |
1579 | ||
1580 | conoc(c) char c; { | |
1581 | write(1,&c,1); | |
1582 | } | |
1583 | ||
1584 | /* C O N X O -- Write x characters to the console terminal */ | |
1585 | ||
1586 | conxo(x,s) char *s; int x; { | |
1587 | write(1,s,x); | |
1588 | } | |
1589 | ||
1590 | /* C O N O L -- Write a line to the console terminal */ | |
1591 | ||
1592 | conol(s) char *s; { | |
1593 | int len; | |
1594 | len = strlen(s); | |
1595 | write(1,s,len); | |
1596 | } | |
1597 | ||
1598 | /* C O N O L A -- Write an array of lines to the console terminal */ | |
1599 | ||
1600 | conola(s) char *s[]; { | |
1601 | int i; | |
1602 | for (i=0 ; *s[i] ; i++) conol(s[i]); | |
1603 | } | |
1604 | ||
1605 | /* C O N O L L -- Output a string followed by CRLF */ | |
1606 | ||
1607 | conoll(s) char *s; { | |
1608 | conol(s); | |
1609 | write(1,"\r\n",2); | |
1610 | } | |
1611 | \f | |
1612 | /* C O N C H K -- Return how many characters available at console */ | |
1613 | ||
1614 | conchk() { | |
1615 | int x; long n; | |
1616 | ||
1617 | #ifdef PROVX1 | |
1618 | x = ioctl(0, TIOCQCNT, &ttbuf); | |
1619 | n = ttbuf.sg_ispeed & 0377; | |
1620 | return((x < 0) ? 0 : n); | |
1621 | #else | |
1622 | #ifdef V7 | |
1623 | lseek(kmem[CON], (long) qaddr[CON], 0); | |
1624 | x = read(kmem[CON], &n, sizeof(int)); | |
1625 | return((x == sizeof(int))? n: 0); | |
1626 | #else | |
1627 | #ifdef UXIII | |
1628 | if (conesc) { /* Escape typed */ | |
1629 | conesc = 0; | |
1630 | signal(SIGQUIT,esctrp); /* Restore escape */ | |
1631 | return(1); | |
1632 | } | |
1633 | return(0); | |
1634 | #else | |
1635 | #ifdef C70 | |
1636 | if (conesc) { /* Escape typed */ | |
1637 | conesc = 0; | |
1638 | signal(SIGQUIT,esctrp); /* Restore escape */ | |
1639 | return(1); | |
1640 | } | |
1641 | return(0); | |
1642 | #else | |
1643 | #ifdef FIONREAD | |
1644 | x = ioctl(0, FIONREAD, &n); /* BSD and maybe some others */ | |
1645 | return((x < 0) ? 0 : n); | |
1646 | #else | |
1647 | return(0); /* Others can't do. */ | |
1648 | #endif | |
1649 | #endif | |
1650 | #endif | |
1651 | #endif | |
1652 | #endif | |
1653 | } | |
1654 | \f | |
1655 | /* C O N I N C -- Get a character from the console */ | |
1656 | ||
1657 | coninc(timo) int timo; { | |
1658 | int n = 0; char ch; | |
1659 | if (timo <= 0 ) { /* untimed */ | |
1660 | n = read(0, &ch, 1); /* Read a character. */ | |
1661 | ch &= 0377; | |
1662 | if (n > 0) return(ch); /* Return the char if read */ | |
1663 | else | |
1664 | #ifdef UXIII | |
1665 | if (n < 0 && errno == EINTR) /* if read was interrupted by QUIT */ | |
1666 | return(escchr); /* user entered escape character */ | |
1667 | else /* couldnt be ^c, sigint never returns */ | |
1668 | #endif | |
1669 | return(-1); /* Return the char, or -1. */ | |
1670 | } | |
1671 | signal(SIGALRM,timerh); /* Timed read, so set up timer */ | |
1672 | alarm(timo); | |
1673 | if (setjmp(sjbuf)) n = -2; | |
1674 | else { | |
1675 | n = read(0, &ch, 1); | |
1676 | ch &= 0377; | |
1677 | } | |
1678 | alarm(0); /* Stop timing, we got our character */ | |
1679 | signal(SIGALRM,SIG_DFL); | |
1680 | if (n > 0) return(ch); | |
1681 | else | |
1682 | #ifdef UXIII | |
1683 | if (n == -1 && errno == EINTR) /* If read interrupted by QUIT, */ | |
1684 | return(escchr); /* user entered escape character, */ | |
1685 | else /* can't be ^c, sigint never returns */ | |
1686 | #endif | |
1687 | return(-1); | |
1688 | } |