|
|
1.1 root 1: /* Interfaces to system-dependent kernel and library entries.
2: Copyright (C) 1985, 1986, 1987, 1988 Free Software Foundation, Inc.
3:
4: This file is part of GNU Emacs.
5:
6: GNU Emacs is distributed in the hope that it will be useful,
7: but WITHOUT ANY WARRANTY. No author or distributor
8: accepts responsibility to anyone for the consequences of using it
9: or for whether it serves any particular purpose or works at all,
10: unless he says so in writing. Refer to the GNU Emacs General Public
11: License for full details.
12:
13: Everyone is granted permission to copy, modify and redistribute
14: GNU Emacs, but only under the conditions described in the
15: GNU Emacs General Public License. A copy of this license is
16: supposed to have been given to you along with GNU Emacs so you
17: can know your rights and responsibilities. It should be in a
18: file named COPYING. Among other things, the copyright notice
19: and this notice must be preserved on all copies. */
20:
21:
22: #include <signal.h>
23: #include <setjmp.h>
24:
25: #define USE_OLD_TTY
26:
27: #include "config.h"
28: #include "lisp.h"
29: #undef NULL
30:
31: #define min(x,y) ((x) > (y) ? (y) : (x))
32:
33: /* In this file, open, read and write refer to the system calls,
34: not our sugared interfaces sys_open, sys_read and sys_write.
35: Contrariwise, for systems where we use the system calls directly,
36: define sys_read, etc. here as aliases for them. */
37: #ifndef read
38: #define sys_read read
39: #define sys_write write
40: #endif /* `read' is not a macro */
41:
42: #undef read
43: #undef write
44:
45: #ifndef close
46: #define sys_close close
47: #else
48: #undef close
49: #endif
50:
51: #ifndef open
52: #define sys_open open
53: #else /* `open' is a macro */
54: #undef open
55: #endif /* `open' is a macro */
56:
57: #include <stdio.h>
58: #include <sys/types.h>
59: #include <sys/stat.h>
60: #include <errno.h>
61:
62: extern int errno;
63: #ifndef VMS
64: extern char *sys_errlist[];
65: #endif
66:
67: #ifdef VMS
68: #include <rms.h>
69: #include <ttdef.h>
70: #include <tt2def.h>
71: #include <iodef.h>
72: #include <ssdef.h>
73: #include <descrip.h>
74: #include <ctype.h>
75: #include <file.h>
76: #ifndef RAB$C_BID
77: #include <rab.h>
78: #endif
79: #define MAXIOSIZE ( 32 * PAGESIZE ) /* Don't I/O more than 32 blocks at a time */
80: #endif /* VMS */
81:
82: #ifndef BSD4_1
83: #ifdef BSD /* this is done this way to avoid defined(BSD) || defined (USG)
84: because the vms compiler doesn't grok `defined' */
85: #include <fcntl.h>
86: #endif
87: #ifdef USG
88: #include <fcntl.h>
89: #endif
90: #endif /* not 4.1 bsd */
91:
92: #ifdef BSD
93: #include <sys/ioctl.h>
94: #ifdef BSD4_1
95: #include <wait.h>
96: #else /* not 4.1 */
97: #include <sys/wait.h>
98: #endif /* not 4.1 */
99: #endif /* BSD */
100:
101: #ifdef STRIDE
102: #include <sys/ioctl.h>
103: #endif
104:
105: #ifdef mips
106: #include <sys/ioctl.h>
107: #endif
108:
109: /* Get rid of LLITOUT in 4.1, since it is said to stimulate kernel bugs. */
110: #ifdef BSD4_1
111: #undef LLITOUT
112: #define LLITOUT 0
113: #endif /* 4.1 */
114:
115: #ifdef HAVE_TERMIO
116: #include <termio.h>
117: #undef TIOCGETP
118: #define TIOCGETP TCGETA
119: #undef TIOCSETN
120: #define TIOCSETN TCSETAW
121: #undef TIOCSETP
122: #define TIOCSETP TCSETAF
123: #define TERMINAL struct termio
124: #define OSPEED(str) (str.c_cflag & CBAUD)
125: #define SETOSPEED(str,new) (str.c_cflag = (str.c_cflag & ~CBAUD) | (new))
126: #define TABS_OK(str) ((str.c_oflag & TABDLY) != TAB3)
127: #endif /* HAVE_TERMIO */
128:
129: #ifdef XENIX
130: #undef TIOCGETC /* Avoid confusing some conditionals that test this. */
131: #endif
132:
133: #ifndef HAVE_TERMIO
134: #ifndef VMS
135: #include <sgtty.h>
136: #define TERMINAL struct sgttyb
137: #define OSPEED(str) str.sg_ospeed
138: #define SETOSPEED(str,new) (str.sg_ospeed = (new))
139: #define TABS_OK(str) ((str.sg_flags & XTABS) != XTABS)
140: #undef TCSETAW
141: #define TCSETAW TIOCSETN
142: #endif /* not VMS */
143: #endif /* not HAVE_TERMIO */
144:
145: #ifdef USG
146: #include <sys/utsname.h>
147: #include <memory.h>
148: #include <string.h>
149: #ifdef TIOCGWINSZ
150: #ifndef IRIS_4D
151: #ifndef mips
152: /* Some USG systems with TIOCGWINSZ need this file; some don't have it.
153: We don't know how to distinguish them.
154: If this #include gets an error, just delete it. */
155: #include <sys/sioctl.h>
156: #endif
157: #endif
158: #endif
159: #ifdef HAVE_TIMEVAL
160: #ifdef HPUX
161: #include <time.h>
162: #else
163: #include <sys/time.h>
164: #endif
165: #endif /* HAVE_TIMEVAL */
166: #endif /* USG */
167:
168: #ifdef VMS
169: #include "window.h"
170: #endif
171:
172: #ifdef NEED_BSDTTY
173: #include <sys/bsdtty.h>
174: #endif
175:
176: #include "termhooks.h"
177: #include "termchar.h"
178: #include "termopts.h"
179: #include "dispextern.h"
180:
181: #ifdef NONSYSTEM_DIR_LIBRARY
182: #include "ndir.h"
183: #endif /* NONSYSTEM_DIR_LIBRARY */
184:
185: #ifndef sigmask
186: #define sigmask(no) (1L << ((no) - 1))
187: #endif
188:
189: /* Define SIGCHLD as an alias for SIGCLD. There are many conditionals
190: testing SIGCHLD. */
191:
192: #ifndef VMS
193: #ifdef SIGCLD
194: #ifndef SIGCHLD
195: #define SIGCHLD SIGCLD
196: #endif /* not SIGCHLD */
197: #endif /* SIGCLD */
198: #endif /* not VMS */
199:
200: static int baud_convert[] =
201: #ifdef BAUD_CONVERT
202: BAUD_CONVERT;
203: #else
204: {
205: 0, 50, 75, 110, 135, 150, 200, 300, 600, 1200,
206: 1800, 2400, 4800, 9600, 19200, 38400
207: };
208: #endif
209:
210: extern short ospeed;
211:
212: #ifdef VMS
213: static struct iosb
214: {
215: short status;
216: short offset;
217: short termlen;
218: short term;
219: } input_iosb;
220:
221: int kbd_input_ast ();
222:
223: int waiting_for_ast;
224: int stop_input;
225: int input_ef = 0;
226: int timer_ef = 0;
227: int process_ef = 0;
228: int input_eflist;
229: int timer_eflist;
230:
231: static int input_chan;
232: static $DESCRIPTOR (input_dsc, "TT");
233: static int terminator_mask[2] = { 0, 0 };
234:
235: static struct sensemode {
236: short status;
237: unsigned char xmit_baud;
238: unsigned char rcv_baud;
239: unsigned char crfill;
240: unsigned char lffill;
241: unsigned char parity;
242: unsigned char unused;
243: char class;
244: char type;
245: short scr_wid;
246: unsigned long tt_char : 24, scr_len : 8;
247: unsigned long tt2_char;
248: } sensemode_iosb;
249: #define TERMINAL struct sensemode
250: #define OSPEED(str) (str.xmit_baud)
251: #define TABS_OK(str) ((str.tt_char & TT$M_MECHTAB) != 0)
252: #endif /* VMS */
253:
254: discard_tty_input ()
255: {
256: TERMINAL buf;
257:
258: if (noninteractive)
259: return;
260:
261: #ifdef VMS
262: end_kbd_input ();
263: SYS$QIOW (0, input_chan, IO$_READVBLK|IO$M_PURGE, input_iosb, 0, 0,
264: &buf, 0, 0, terminator_mask, 0, 0);
265: queue_kbd_input ();
266: #else /* not VMS */
267: ioctl (0, TIOCGETP, &buf);
268: ioctl (0, TIOCSETP, &buf);
269: #endif /* not VMS */
270: }
271:
272: #ifdef SIGTSTP
273:
274: stuff_char (c)
275: char c;
276: {
277: /* Should perhaps error if in batch mode */
278: #ifdef TIOCSTI
279: ioctl (0, TIOCSTI, &c);
280: #else /* no TIOCSTI */
281: error ("Cannot stuff terminal input characters in this version of Unix.");
282: #endif /* no TIOCSTI */
283: }
284:
285: #endif /* SIGTSTP */
286:
287: init_baud_rate ()
288: {
289: TERMINAL sg;
290:
291: if (noninteractive)
292: ospeed = 0;
293: else
294: {
295: #ifdef VMS
296: SYS$QIOW (0, input_chan, IO$_SENSEMODE, &sg, 0, 0,
297: &sg.class, 12, 0, 0, 0, 0 );
298: #else
299: SETOSPEED (sg, B9600);
300: ioctl (0, TIOCGETP, &sg);
301: #endif /* not VMS */
302: ospeed = OSPEED (sg);
303: }
304: baud_rate = ospeed == 0 ? 1200
305: : ospeed < sizeof baud_convert / sizeof baud_convert[0]
306: ? baud_convert[ospeed] : 9600;
307: }
308:
309: /*ARGSUSED*/
310: set_exclusive_use (fd)
311: int fd;
312: {
313: #ifdef FIOCLEX
314: ioctl (fd, FIOCLEX, 0);
315: #endif
316: /* Ok to do nothing if this feature does not exist */
317: }
318:
319: #ifndef subprocesses
320:
321: wait_without_blocking ()
322: {
323: #ifdef BSD
324: wait3 (0, WNOHANG | WUNTRACED, 0);
325: #else
326: croak ("wait_without_blocking");
327: #endif
328: }
329:
330: #endif /* not subprocesses */
331:
332: int wait_debugging; /* Set nonzero to make following function work under dbx
333: (at least for bsd). */
334:
335: /* Wait for subprocess with process id `pid' to terminate and
336: make sure it will get eliminated (not remain forever as a zombie) */
337:
338: wait_for_termination (pid)
339: int pid;
340: {
341: while (1)
342: {
343: #ifdef subprocesses
344: #if defined(BSD) || (defined(HPUX) && !defined(HPUX_5))
345: /* Note that kill returns -1 even if the process is just a zombie now.
346: But inevitably a SIGCHLD interrupt should be generated
347: and child_sig will do wait3 and make the process go away. */
348: /* There is some indication that there is a bug involved with
349: termination of subprocesses, perhaps involving a kernel bug too,
350: but no idea what it is. Just as a hunch we signal SIGCHLD to see
351: if that causes the problem to go away or get worse. */
352: #ifdef BSD4_1
353: extern int synch_process_pid;
354: sighold (SIGCHLD);
355: if (synch_process_pid == 0)
356: {
357: sigrelse (SIGCHLD);
358: break;
359: }
360: if (wait_debugging)
361: sleep (1);
362: else
363: sigpause (SIGCHLD);
364: #else /* not BSD4_1 */
365: sigsetmask (1 << (SIGCHLD - 1));
366: if (0 > kill (pid, 0))
367: {
368: sigsetmask (0);
369: kill (getpid (), SIGCHLD);
370: break;
371: }
372: if (wait_debugging)
373: sleep (1);
374: else
375: sigpause (0);
376: #endif /* not BSD4_1 */
377: #else /* not BSD, and not HPUX version >= 6 */
378: #ifdef UNIPLUS
379: if (0 > kill (pid, 0))
380: break;
381: wait (0);
382: #else /* neither BSD nor UNIPLUS: random sysV */
383: if (0 > kill (pid, 0))
384: break;
385: pause ();
386: #endif /* not UNIPLUS */
387: #endif /* not BSD, and not HPUX version >= 6 */
388: #else /* not subprocesses */
389: #ifndef BSD4_1
390: if (0 > kill (pid, 0))
391: break;
392: wait (0);
393: #else /* BSD4_1 */
394: int status;
395: status = wait (0);
396: if (status == pid || status == -1)
397: break;
398: #endif /* BSD4_1 */
399: #endif /* not subprocesses */
400: }
401: }
402:
403: #ifdef subprocesses
404:
405: /*
406: * flush any pending output
407: * (may flush input as well; it does not matter the way we use it)
408: */
409:
410: flush_pending_output (channel)
411: int channel;
412: {
413: #ifdef TCFLSH
414: ioctl (channel, TCFLSH, 1);
415: #else
416: #ifdef TIOCFLUSH
417: int zero = 0;
418: /* 3rd arg should be ignored
419: but some 4.2 kernels actually want the address of an int
420: and nonzero means something different. */
421: ioctl (channel, TIOCFLUSH, &zero);
422: #endif
423: #endif
424: }
425:
426: /* Set up the terminal at the other end of a pseudo-terminal that
427: we will be controlling an inferior through.
428: It should not echo or do line-editing, since that is done
429: in Emacs. No padding needed for insertion into an Emacs buffer. */
430:
431: child_setup_tty (out)
432: int out;
433: {
434: TERMINAL s;
435:
436: ioctl (out, TIOCGETP, &s);
437: #ifdef HAVE_TERMIO
438: s.c_oflag |= OPOST; /* Enable output postprocessing */
439: s.c_oflag &= ~ONLCR; /* Disable map of NL to CR-NL on output */
440: s.c_oflag &= ~(NLDLY|CRDLY|TABDLY|BSDLY|VTDLY|FFDLY); /* No output delays */
441: s.c_lflag &= ~ECHO; /* Disable echo */
442: s.c_lflag |= ISIG; /* Enable signals */
443: s.c_iflag &= ~IUCLC; /* Disable map of upper case to lower on input */
444: s.c_oflag &= ~OLCUC; /* Disable map of lower case to upper on output */
445: /* said to be unnecesary
446: s.c_cc[VMIN] = 1; /* minimum number of characters to accept
447: s.c_cc[VTIME] = 0; /* wait forever for at least 1 character
448: */
449: s.c_lflag |= ICANON; /* Enable erase/kill and eof processing */
450: s.c_cc[VEOF] = 04; /* insure that EOF is Control-D */
451: s.c_cc[VERASE] = 0377; /* disable erase processing */
452: s.c_cc[VKILL] = 0377; /* disable kill processing */
453: #ifdef HPUX
454: s.c_cflag = (s.c_cflag & ~CBAUD) | B9600; /* baud rate sanity */
455: #endif HPUX
456: #ifdef IBMRTAIX
457: /* AIX enhanced edit loses NULs, so disable it */
458: s.c_line = 0;
459: s.c_iflag &= ~ASCEDIT;
460: /* Also, PTY overloads NUL and BREAK.
461: don't ignore break, but don't signal either, so it looks like NUL. */
462: s.c_iflag &= ~IGNBRK;
463: s.c_iflag &= ~BRKINT;
464: /* QUIT and INTR work better as signals, so disable character forms */
465: s.c_cc[VQUIT] = 0377;
466: s.c_cc[VINTR] = 0377;
467: s.c_cc[VEOL] = 0377;
468: s.c_lflag &= ~ISIG;
469: s.c_cflag = (s.c_cflag & ~CBAUD) | B9600; /* baud rate sanity */
470: #endif /* IBMRTAIX */
471:
472: #else /* not HAVE_TERMIO */
473: s.sg_flags &= ~(ECHO | CRMOD | ANYP | ALLDELAY | RAW | LCASE | CBREAK | TANDEM);
474: #endif /* not HAVE_TERMIO */
475:
476: ioctl (out, TIOCSETN, &s);
477:
478: #ifdef BSD4_1
479: if (interrupt_input)
480: reset_sigio ();
481: #endif /* BSD4_1 */
482: #ifdef RTU
483: {
484: int zero = 0;
485: ioctl (out, FIOASYNC, &zero);
486: }
487: #endif /* RTU */
488: }
489:
490: #endif /* subprocesses */
491:
492: /*ARGSUSED*/
493: setpgrp_of_tty (pid)
494: int pid;
495: {
496: #ifdef TIOCSPGRP
497: ioctl (0, TIOCSPGRP, &pid);
498: #else
499: /* Just ignore this for now and hope for the best */
500: #endif
501: }
502:
503: /* Suspend the Emacs process; give terminal to its superior. */
504:
505: sys_suspend ()
506: {
507: #ifdef VMS
508: unsigned long parent_id;
509:
510: parent_id = getppid ();
511: if (parent_id && parent_id != 0xffffffff)
512: {
513: int oldsig = signal (SIGINT, SIG_IGN);
514: int status = LIB$ATTACH (&parent_id) & 1;
515: signal (SIGINT, oldsig);
516: return status;
517: }
518: return -1;
519: #else
520: #ifdef SIGTSTP
521: #ifdef BSD
522: killpg (getpgrp (0), SIGTSTP);
523: #else
524: kill (-getpgrp (0), SIGTSTP);
525: #endif
526:
527: #else
528: #ifdef USG_JOBCTRL /* If you don't know what this is don't mess with it */
529: ptrace (0, 0, 0, 0); /* set for ptrace - caught by csh */
530: kill (getpid (), SIGQUIT);
531:
532: #else
533:
534: /* On a system where suspending is not implemented,
535: instead fork a subshell and let it talk directly to the terminal
536: while we wait. */
537: int pid = fork ();
538: int (*interrupt) ();
539: int (*quit) ();
540: int (*term) ();
541: #ifdef SIGIO
542: int (*sigio) ();
543: #endif SIGIO
544:
545: if (pid == -1)
546: error ("Can't spawn subshell");
547: if (pid == 0)
548: {
549: char *sh;
550:
551: sh = (char *) egetenv ("SHELL");
552: if (sh == 0)
553: sh = "sh";
554: /* Use our buffer's default directory for the subshell. */
555: {
556: Lisp_Object dir;
557: unsigned char *str;
558: int len;
559:
560: /* mentioning bf_cur->buffer would mean including buffer.h,
561: which somehow wedges the hp compiler. So instead... */
562:
563: dir = intern ("default-directory");
564: /* Can't use NULL */
565: if (XFASTINT (Fboundp (dir)) == XFASTINT (Qnil))
566: goto xyzzy;
567: dir = Fsymbol_value (dir);
568: if (XTYPE (dir) != Lisp_String)
569: goto xyzzy;
570:
571: str = (unsigned char *) alloca (XSTRING (dir)->size + 2);
572: len = XSTRING (dir)->size;
573: bcopy (XSTRING (dir)->data, str, len);
574: if (str[len - 1] != '/') str[len++] = '/';
575: str[len] = 0;
576: chdir (str);
577: }
578: xyzzy:
579: #ifdef subprocesses
580: close_process_descs (); /* Close Emacs's pipes/ptys */
581: #endif
582: execlp (sh, sh, 0);
583: write (1, "Can't execute subshell", 22);
584: _exit (1);
585: }
586: interrupt = (int (*)()) signal (SIGINT, SIG_IGN);
587: quit = (int (*)()) signal (SIGQUIT, SIG_IGN);
588: term = (int (*)()) signal (SIGTERM, SIG_IGN);
589: #ifdef SIGIO
590: sigio = (int (*)()) signal (SIGIO, SIG_IGN);
591: #endif /* SIGIO */
592: wait_for_termination (pid);
593: signal (SIGINT, interrupt);
594: signal (SIGQUIT, quit);
595: signal (SIGTERM, term);
596: #ifdef SIGIO
597: signal (SIGIO, sigio);
598: #endif /* SIGIO */
599: #endif /* no USG_JOBCTRL */
600: #endif /* no SIGTSTP */
601: #endif /* not VMS */
602: }
603:
604: #ifdef F_SETFL
605:
606: int old_fcntl_flags;
607:
608: init_sigio ()
609: {
610: #ifdef FASYNC
611: old_fcntl_flags = fcntl (0, F_GETFL, 0) & ~FASYNC;
612: #endif
613: request_sigio ();
614: }
615:
616: reset_sigio ()
617: {
618: unrequest_sigio ();
619: }
620:
621: #ifdef FASYNC /* F_SETFL does not imply existance of FASYNC */
622:
623: request_sigio ()
624: {
625: #ifdef SIGWINCH
626: int omask = sigblock (0);
627: sigsetmask (omask & ~sigmask (SIGWINCH));
628: #endif
629: fcntl (0, F_SETFL, old_fcntl_flags | FASYNC);
630:
631: interrupts_deferred = 0;
632: }
633:
634: unrequest_sigio ()
635: {
636: #ifdef SIGWINCH
637: sigblock (sigmask (SIGWINCH));
638: #endif
639: fcntl (0, F_SETFL, old_fcntl_flags);
640: interrupts_deferred = 1;
641: }
642:
643: #else /* no FASYNC */
644: #ifdef STRIDE /* Stride doesn't have FASYNC - use FIOASYNC */
645:
646: request_sigio ()
647: {
648: int on = 1;
649: ioctl (0, FIOASYNC, &on);
650: interrupts_deferred = 0;
651: }
652:
653: unrequest_sigio ()
654: {
655: int off = 0;
656:
657: ioctl (0, FIOASYNC, &off);
658: interrupts_deferred = 1;
659: }
660:
661: #else /* not FASYNC, not STRIDE */
662:
663: request_sigio ()
664: {
665: croak ("request_sigio");
666: }
667:
668: unrequest_sigio ()
669: {
670: croak ("unrequest_sigio");
671: }
672:
673: #endif /* STRIDE */
674: #endif /* FASYNC */
675: #endif /* F_SETFL */
676:
677: TERMINAL old_gtty; /* The initial tty mode bits */
678:
679: int term_initted; /* 1 if outer tty status has been recorded */
680:
681: #ifdef F_SETOWN
682: int old_fcntl_owner;
683: #endif /* F_SETOWN */
684:
685: #ifdef TIOCGLTC
686: struct ltchars old_ltchars;
687: #endif /* TIOCGLTC */
688:
689: #ifdef TIOCGETC
690: struct tchars old_tchars;
691: int old_lmode;
692:
693: int lmode; /* Current lmode value. */
694: /* Needed as global for 4.1 */
695: #endif /* TIOCGETC */
696:
697: /* This may also be defined in stdio,
698: but if so, this does no harm,
699: and using the same name avoids wasting the other one's space. */
700:
701: #ifdef USG
702: unsigned char _sobuf[BUFSIZ+8];
703: #else
704: char _sobuf[BUFSIZ];
705: #endif
706:
707: #ifdef TIOCGLTC
708: static struct ltchars new_ltchars = {-1,-1,-1,-1,-1,-1};
709: #endif
710: #ifdef TIOCGETC
711: static struct tchars new_tchars = {-1,-1,-1,-1,-1,-1};
712: #endif
713:
714: init_sys_modes ()
715: {
716: TERMINAL sg;
717: #ifdef TIOCGETC
718: struct tchars tchars;
719: #endif
720: #ifdef VMS
721: #if 0
722: static int oob_chars[2] = {0, 1 << 7}; /* catch C-g's */
723: extern int (*interrupt_signal) ();
724: #endif
725: #endif
726:
727: if (noninteractive)
728: return;
729:
730: #ifdef VMS
731: if (!input_ef)
732: LIB$GET_EF (&input_ef);
733: SYS$CLREF (input_ef);
734: waiting_for_ast = 0;
735: if (!timer_ef)
736: LIB$GET_EF (&timer_ef);
737: SYS$CLREF (timer_ef);
738: if (!process_ef)
739: LIB$GET_EF (&process_ef);
740: SYS$CLREF (process_ef);
741: if (input_ef / 32 != process_ef / 32)
742: croak ("Input and process event flags in different clusters.");
743: if (input_ef / 32 != timer_ef / 32)
744: croak ("Input and process event flags in different clusters.");
745: input_eflist = ((unsigned) 1 << (input_ef % 32)) |
746: ((unsigned) 1 << (process_ef % 32));
747: timer_eflist = ((unsigned) 1 << (input_ef % 32)) |
748: ((unsigned) 1 << (timer_ef % 32));
749: SYS$QIOW (0, input_chan, IO$_SENSEMODE, &old_gtty, 0, 0,
750: &old_gtty.class, 12, 0, 0, 0, 0);
751: #ifndef VMS4_4
752: sys_access_reinit ();
753: #endif
754: #else /* not VMS */
755: ioctl (0, TIOCGETP, &old_gtty);
756: #endif /* not VMS */
757: if (!read_socket_hook)
758: {
759: sg = old_gtty;
760:
761: #ifdef HAVE_TERMIO
762: sg.c_iflag |= (IGNBRK); /* Ignore break condition */
763: sg.c_iflag &= ~ICRNL; /* Disable map of CR to NL on input */
764: #ifdef ISTRIP
765: sg.c_iflag &= ~ISTRIP; /* don't strip 8th bit on input */
766: #endif
767: sg.c_lflag &= ~ECHO; /* Disable echo */
768: sg.c_lflag &= ~ICANON; /* Disable erase/kill processing */
769: sg.c_lflag |= ISIG; /* Enable signals */
770: if (flow_control)
771: {
772: sg.c_iflag |= IXON; /* Enable start/stop output control */
773: #ifdef IXANY
774: sg.c_iflag &= ~IXANY;
775: #endif /* IXANY */
776: }
777: else
778: sg.c_iflag &= ~IXON; /* Disable start/stop output control */
779: sg.c_oflag &= ~ONLCR; /* Disable map of NL to CR-NL on output */
780: sg.c_oflag &= ~TAB3; /* Disable tab expansion */
781: #ifdef CS8
782: sg.c_cflag |= CS8; /* allow 8th bit on input */
783: sg.c_cflag &= ~PARENB; /* Don't check parity */
784: #endif
785: sg.c_cc[VINTR] = '\007'; /* ^G gives SIGINT */
786: /* Set up C-g for both SIGQUIT and SIGINT.
787: We don't know which we will get, but we handle both alike
788: so which one it really gives us does not matter. */
789: sg.c_cc[VQUIT] = '\007';
790: sg.c_cc[VMIN] = 1; /* Input should wait for at least 1 char */
791: sg.c_cc[VTIME] = 0; /* no matter how long that takes. */
792: #ifdef VSWTCH
793: sg.c_cc[VSWTCH] = CDEL; /* Turn off shell layering use of C-z */
794: #endif /* VSWTCH */
795: #ifdef IBMRTAIX
796: /* AIX enhanced edit loses NULs, so disable it */
797: sg.c_line = 0;
798: sg.c_iflag &= ~ASCEDIT;
799: /* Also, PTY overloads NUL and BREAK.
800: don't ignore break, but don't signal either, so it looks like NUL.
801: This really serves a purpose only if running in an XTERM window
802: or via TELNET or the like, but does no harm elsewhere. */
803: sg.c_iflag &= ~IGNBRK;
804: sg.c_iflag &= ~BRKINT;
805: #endif
806: #else /* if not HAVE_TERMIO */
807: #ifdef VMS
808: sg.tt_char |= TT$M_NOECHO | TT$M_EIGHTBIT;
809: if (flow_control)
810: sg.tt_char |= TT$M_TTSYNC;
811: else
812: sg.tt_char &= ~TT$M_TTSYNC;
813: sg.tt2_char |= TT2$M_PASTHRU | TT2$M_XON;
814: #else /* not VMS (BSD, that is) */
815: sg.sg_flags &= ~(ECHO | CRMOD | XTABS);
816: sg.sg_flags |= ANYP;
817: sg.sg_flags |= interrupt_input ? RAW : CBREAK;
818: #endif /* not VMS (BSD, that is) */
819: #endif /* not HAVE_TERMIO */
820:
821: #ifdef VMS
822: SYS$QIOW (0, input_chan, IO$_SETMODE, &input_iosb, 0, 0,
823: &sg.class, 12, 0, 0, 0, 0);
824: #else
825: ioctl (0, TIOCSETN, &sg);
826: #endif /* not VMS */
827:
828: /* This code added to insure that, if flow-control is not to be used,
829: we have an unlocked screen at the start. */
830: #ifdef TCXONC
831: if (!flow_control) ioctl (0, TCXONC, 1);
832: #endif
833: #ifdef TIOCSTART
834: if (!flow_control) ioctl (0, TIOCSTART, 0);
835: #endif
836:
837: #ifdef AIX
838: hft_init ();
839: #endif
840:
841: #ifdef F_SETFL
842: #ifdef F_GETOWN /* F_SETFL does not imply existance of F_GETOWN */
843: if (interrupt_input)
844: {
845: old_fcntl_owner = fcntl (0, F_GETOWN, 0);
846: fcntl (0, F_SETOWN, getpid ());
847: init_sigio ();
848: }
849: #endif /* F_GETOWN */
850: #endif /* F_SETFL */
851:
852: /* If going to use CBREAK mode, we must request C-g to interrupt
853: and turn off start and stop chars, etc.
854: If not going to use CBREAK mode, do this anyway
855: so as to turn off local flow control for user coming over
856: network on 4.2; in this case, only t_stopc and t_startc really matter. */
857: #ifdef TIOCGLTC
858: ioctl (0, TIOCGLTC, &old_ltchars);
859: #endif /* TIOCGLTC */
860: #ifndef HAVE_TERMIO
861: #ifdef TIOCGETC
862: ioctl (0, TIOCGETC, &old_tchars);
863: ioctl (0, TIOCLGET, &old_lmode);
864:
865: /* Note: if not using CBREAK mode, it makes no difference how we set this */
866: tchars = new_tchars;
867: tchars.t_intrc = 07;
868: if (flow_control)
869: {
870: tchars.t_startc = '\021';
871: tchars.t_stopc = '\023';
872: }
873: /* LPASS8 is new in 4.3, and makes cbreak mode provide all 8 bits. */
874: #ifndef LPASS8
875: #define LPASS8 0
876: #endif
877:
878: #ifdef BSD4_1
879: #define LNOFLSH 0100000
880: #endif
881:
882: lmode = LDECCTQ | LLITOUT | LPASS8 | LNOFLSH | old_lmode;
883:
884: ioctl (0, TIOCSETC, &tchars);
885: ioctl (0, TIOCLSET, &lmode);
886: #endif /* TIOCGETC */
887: #endif /* not HAVE_TERMIO */
888: #ifdef TIOCGLTC
889: ioctl (0, TIOCSLTC, &new_ltchars);
890: #endif /* TIOCGLTC */
891:
892: #ifdef BSD4_1
893: if (interrupt_input)
894: init_sigio ();
895: #endif
896: #ifdef VMS
897: /* Appears to do nothing when in PASTHRU mode.
898: SYS$QIOW (0, input_chan, IO$_SETMODE|IO$M_OUTBAND, 0, 0, 0,
899: interrupt_signal, oob_chars, 0, 0, 0, 0);
900: */
901: queue_kbd_input (0);
902: #endif /* VMS */
903: }
904: #ifdef VMS /* VMS sometimes has this symbol but lacks setvbuf. */
905: #undef _IOFBF
906: #endif
907: #ifdef _IOFBF
908: /* This symbol is defined on recent USG systems.
909: Someone says without this call USG won't really buffer the file
910: even with a call to setbuf(). */
911: setvbuf (stdout, _sobuf, _IOFBF, sizeof _sobuf);
912: #else
913: setbuf (stdout, _sobuf);
914: #endif
915: set_terminal_modes ();
916: if (term_initted && no_redraw_on_reenter)
917: {
918: if (display_completed)
919: direct_output_forward_char (0);
920: }
921: else
922: screen_garbaged = 1;
923: term_initted = 1;
924: }
925:
926: /* Return nonzero if safe to use tabs in output.
927: At the time this is called, init_sys_modes has not been done yet. */
928:
929: tabs_safe_p ()
930: {
931: TERMINAL sg;
932: if (noninteractive)
933: return 1;
934: #ifdef VMS
935: SYS$QIOW (0, input_chan, IO$_SENSEMODE, &sg, 0, 0,
936: &sg.class, 12, 0, 0, 0, 0);
937: #else
938: ioctl (0, TIOCGETP, &sg);
939: #endif /* not VMS */
940: return (TABS_OK(sg));
941: }
942:
943: /* Get terminal size from system.
944: Store number of lines into *heightp and width into *widthp.
945: If zero or a negative number is stored, the value is not valid. */
946:
947: get_screen_size (widthp, heightp)
948: int *widthp, *heightp;
949: {
950: /* Define the 4.3 names in terms of the Sun names
951: if the latter exist and the former do not. */
952: #ifdef TIOCGSIZE
953: #ifndef TIOCGWINSZ
954: #define TIOCGWINSZ TIOCGSIZE
955: #define winsize ttysize
956: #define ws_row ts_lines
957: #define ws_col ts_cols
958: #endif
959: #endif /* Sun */
960:
961: /* Do it using the 4.3 names if possible. */
962: #ifdef TIOCGWINSZ
963: struct winsize size;
964: *widthp = 0;
965: *heightp = 0;
966: if (ioctl (0, TIOCGWINSZ, &size) < 0)
967: return;
968: if ((unsigned) size.ws_col > MScreenWidth
969: || (unsigned) size.ws_row > MScreenLength)
970: return;
971: *widthp = size.ws_col;
972: *heightp = size.ws_row;
973: #else /* not TIOCGWNSIZ */
974: #ifdef VMS
975: TERMINAL sg;
976: SYS$QIOW (0, input_chan, IO$_SENSEMODE, &sg, 0, 0,
977: &sg.class, 12, 0, 0, 0, 0);
978: *widthp = sg.scr_wid;
979: *heightp = sg.scr_len;
980: #else /* system doesn't know size */
981: *widthp = 0;
982: *heightp = 0;
983: #endif /* system does not know size */
984: #endif /* not TIOCGWINSZ */
985: }
986:
987: reset_sys_modes ()
988: {
989: if (noninteractive)
990: {
991: fflush (stdout);
992: return;
993: }
994: if (!term_initted)
995: return;
996: if (read_socket_hook)
997: return;
998: topos (screen_height - 1, 0);
999: clear_end_of_line (screen_width);
1000: /* clear_end_of_line may move the cursor */
1001: topos (screen_height - 1, 0);
1002: /* Output raw CR so kernel can track the cursor hpos. */
1003: cmputc ('\r');
1004: reset_terminal_modes ();
1005: fflush (stdout);
1006: #ifdef BSD
1007: #ifndef BSD4_1
1008: /* Avoid possible loss of output when changing terminal modes. */
1009: fsync (fileno (stdout));
1010: #endif
1011: #endif
1012: #ifdef TIOCGLTC
1013: ioctl (0, TIOCSLTC, &old_ltchars);
1014: #endif /* TIOCGLTC */
1015: #ifndef HAVE_TERMIO
1016: #ifdef TIOCGETC
1017: ioctl (0, TIOCSETC, &old_tchars);
1018: ioctl (0, TIOCLSET, &old_lmode);
1019: #endif /* TIOCGETC */
1020: #endif /* not HAVE_TERMIO */
1021: #ifdef F_SETFL
1022: #ifdef F_SETOWN /* F_SETFL does not imply existance of F_SETOWN */
1023: if (interrupt_input)
1024: {
1025: reset_sigio ();
1026: fcntl (0, F_SETOWN, old_fcntl_owner);
1027: }
1028: #endif /* F_SETOWN */
1029: #endif /* F_SETFL */
1030: #ifdef BSD4_1
1031: if (interrupt_input)
1032: reset_sigio ();
1033: #endif /* BSD4_1 */
1034: #ifdef VMS
1035: end_kbd_input ();
1036: SYS$QIOW (0, input_chan, IO$_SETMODE, &input_iosb, 0, 0,
1037: &old_gtty.class, 12, 0, 0, 0, 0);
1038: #else /* not VMS */
1039: while (ioctl (0, TCSETAW, &old_gtty) < 0 && errno == EINTR);
1040: #endif /* not VMS */
1041:
1042: #ifdef AIX
1043: hft_reset ();
1044: #endif
1045: }
1046:
1047: #ifdef VMS
1048:
1049: /* Assigning an input channel is done at the start of Emacs execution.
1050: This is called each time Emacs is resumed, also, but does nothing
1051: because input_chain is no longer zero. */
1052:
1053: init_vms_input()
1054: {
1055: int status;
1056:
1057: if (input_chan == 0)
1058: {
1059: status = SYS$ASSIGN (&input_dsc, &input_chan, 0, 0);
1060: if (! (status & 1))
1061: LIB$STOP (status);
1062: }
1063: }
1064:
1065: /* Deassigning the input channel is done before exiting. */
1066:
1067: stop_vms_input ()
1068: {
1069: return SYS$DASSGN (input_chan);
1070: }
1071:
1072: short input_buffer;
1073:
1074: /* Request reading one character into the keyboard buffer.
1075: This is done as soon as the buffer becomes empty. */
1076:
1077: queue_kbd_input ()
1078: {
1079: int status;
1080: waiting_for_ast = 0;
1081: stop_input = 0;
1082: status = SYS$QIO (0, input_chan, IO$_READVBLK,
1083: &input_iosb, kbd_input_ast, 1,
1084: &input_buffer, 1, 0, terminator_mask, 0, 0);
1085: }
1086:
1087: int input_count;
1088:
1089: /* Ast routine that is called when keyboard input comes in
1090: in accord with the SYS$QIO above. */
1091:
1092: kbd_input_ast ()
1093: {
1094: register int c = -1;
1095: int old_errno = errno;
1096:
1097: if (waiting_for_ast)
1098: SYS$SETEF (input_ef);
1099: waiting_for_ast = 0;
1100: input_count++;
1101: #ifdef ASTDEBUG
1102: if (input_count == 25)
1103: exit (1);
1104: printf ("Ast # %d,", input_count);
1105: printf (" iosb = %x, %x, %x, %x",
1106: input_iosb.offset, input_iosb.status, input_iosb.termlen,
1107: input_iosb.term);
1108: #endif
1109: if (input_iosb.offset)
1110: {
1111: c = input_buffer;
1112: #ifdef ASTDEBUG
1113: printf (", char = 0%o", c);
1114: #endif
1115: }
1116: #ifdef ASTDEBUG
1117: printf ("\n");
1118: fflush (stdout);
1119: sleep (1);
1120: #endif
1121: if (! stop_input)
1122: queue_kbd_input ();
1123: if (c >= 0)
1124: kbd_buffer_store_char (c);
1125:
1126: errno = old_errno;
1127: }
1128:
1129: /* Wait until there is something in kbd_buffer. */
1130:
1131: wait_for_kbd_input ()
1132: {
1133: extern int have_process_input, process_exited;
1134:
1135: /* If already something, avoid doing system calls. */
1136: if (detect_input_pending ())
1137: {
1138: return;
1139: }
1140: /* Clear a flag, and tell ast routine above to set it. */
1141: SYS$CLREF (input_ef);
1142: waiting_for_ast = 1;
1143: /* Check for timing error: ast happened while we were doing that. */
1144: if (!detect_input_pending ())
1145: {
1146: /* No timing error: wait for flag to be set. */
1147: SYS$WFLOR (input_ef, input_eflist);
1148: if (!detect_input_pending ())
1149: /* Check for subprocess input availability */
1150: {
1151: int dsp = have_process_input || process_exited;
1152:
1153: if (have_process_input)
1154: process_command_input ();
1155: if (process_exited)
1156: process_exit ();
1157: if (dsp)
1158: {
1159: RedoModes++;
1160: DoDsp (1);
1161: }
1162: }
1163: }
1164: waiting_for_ast = 0;
1165: }
1166:
1167: /* Get rid of any pending QIO, when we are about to suspend
1168: or when we want to throw away pending input.
1169: We wait for a positive sign that the AST routine has run
1170: and therefore there is no I/O request queued when we return.
1171: SYS$SETAST is used to avoid a timing error. */
1172:
1173: end_kbd_input()
1174: {
1175: #ifdef ASTDEBUG
1176: printf ("At end_kbd_input.\n");
1177: fflush (stdout);
1178: sleep (1);
1179: #endif
1180: if (LIB$AST_IN_PROG ()) /* Don't wait if suspending from kbd_buffer_store_char! */
1181: {
1182: SYS$CANCEL (input_chan);
1183: return;
1184: }
1185:
1186: SYS$SETAST (0);
1187: /* Clear a flag, and tell ast routine above to set it. */
1188: SYS$CLREF (input_ef);
1189: waiting_for_ast = 1;
1190: stop_input = 1;
1191: SYS$CANCEL (input_chan);
1192: SYS$SETAST (1);
1193: SYS$WAITFR (input_ef);
1194: waiting_for_ast = 0;
1195: }
1196:
1197: /* Wait for either input available or time interval expiry. */
1198:
1199: input_wait_timeout (timeval)
1200: int timeval; /* Time to wait, in seconds */
1201: {
1202: int time [2];
1203:
1204: LIB$EMUL (&timeval, &-10000000, &0, time); /* Convert to VMS format */
1205:
1206: /* If already something, avoid doing system calls. */
1207: if (detect_input_pending ())
1208: {
1209: return;
1210: }
1211: /* Clear a flag, and tell ast routine above to set it. */
1212: SYS$CLREF (input_ef);
1213: waiting_for_ast = 1;
1214: /* Check for timing error: ast happened while we were doing that. */
1215: if (!detect_input_pending ())
1216: {
1217: /* No timing error: wait for flag to be set. */
1218: SYS$CANTIM (1, 0);
1219: if (SYS$SETIMR (timer_ef, time, 0, 1) & 1) /* Set timer */
1220: SYS$WFLOR (timer_ef, timer_eflist); /* Wait for timer expiry or input */
1221: }
1222: waiting_for_ast = 0;
1223: }
1224:
1225: /* The standard `sleep' routine works some other way
1226: and it stops working if you have ever quit out of it.
1227: This one continues to work. */
1228:
1229: sys_sleep (timeval)
1230: int timeval;
1231: {
1232: int time [2];
1233:
1234: LIB$EMUL (&timeval, &-10000000, &0, time); /* Convert to VMS format */
1235:
1236: SYS$CANTIM (1, 0);
1237: if (SYS$SETIMR (timer_ef, time, 0, 1) & 1) /* Set timer */
1238: SYS$WAITFR (timer_ef); /* Wait for timer expiry only */
1239: }
1240:
1241: init_sigio ()
1242: {
1243: request_sigio ();
1244: }
1245:
1246: reset_sigio ()
1247: {
1248: unrequest_sigio ();
1249: }
1250:
1251: request_sigio ()
1252: {
1253: croak ("request sigio");
1254: }
1255:
1256: unrequest_sigio ()
1257: {
1258: croak ("unrequest sigio");
1259: }
1260:
1261: #endif /* VMS */
1262:
1263: /* Note that VMS compiler won't accept defined (CANNOT_DUMP). */
1264: #ifndef CANNOT_DUMP
1265: #define NEED_STARTS
1266: #endif
1267:
1268: #ifndef SYSTEM_MALLOC
1269: #ifndef NEED_STARTS
1270: #define NEED_STARTS
1271: #endif
1272: #endif
1273:
1274: #ifdef NEED_STARTS
1275: /* Some systems that cannot dump also cannot implement these. */
1276:
1277: /*
1278: * Return the address of the start of the text segment prior to
1279: * doing an unexec(). After unexec() the return value is undefined.
1280: * See crt0.c for further explanation and _start().
1281: *
1282: */
1283:
1284: #ifndef CANNOT_UNEXEC
1285: char *
1286: start_of_text ()
1287: {
1288: #ifdef TEXT_START
1289: return ((char *) TEXT_START);
1290: #else
1291: #ifdef GOULD
1292: extern csrt();
1293: return ((char *) csrt);
1294: #else /* not GOULD */
1295: extern int _start ();
1296: return ((char *) _start);
1297: #endif /* GOULD */
1298: #endif /* TEXT_START */
1299: }
1300: #endif /* not CANNOT_UNEXEC */
1301:
1302: /*
1303: * Return the address of the start of the data segment prior to
1304: * doing an unexec(). After unexec() the return value is undefined.
1305: * See crt0.c for further information and definition of data_start.
1306: *
1307: * Apparently, on BSD systems this is etext at startup. On
1308: * USG systems (swapping) this is highly mmu dependent and
1309: * is also dependent on whether or not the program is running
1310: * with shared text. Generally there is a (possibly large)
1311: * gap between end of text and start of data with shared text.
1312: *
1313: * On Uniplus+ systems with shared text, data starts at a
1314: * fixed address. Each port (from a given oem) is generally
1315: * different, and the specific value of the start of data can
1316: * be obtained via the UniPlus+ specific "uvar(2)" system call,
1317: * however the method outlined in crt0.c seems to be more portable.
1318: *
1319: * Probably what will have to happen when a USG unexec is available,
1320: * at least on UniPlus, is temacs will have to be made unshared so
1321: * that text and data are contiguous. Then once loadup is complete,
1322: * unexec will produce a shared executable where the data can be
1323: * at the normal shared text boundry and the startofdata variable
1324: * will be patched by unexec to the correct value.
1325: *
1326: */
1327:
1328: char *
1329: start_of_data ()
1330: {
1331: #ifdef DATA_START
1332: return ((char *) DATA_START);
1333: #else
1334: extern int data_start;
1335: return ((char *) &data_start);
1336: #endif
1337: }
1338: #endif /* NEED_STARTS (not CANNOT_DUMP or not SYSTEM_MALLOC) */
1339:
1340: #ifndef CANNOT_DUMP
1341: /* Some systems that cannot dump also cannot implement these. */
1342:
1343: /*
1344: * Return the address of the end of the text segment prior to
1345: * doing an unexec(). After unexec() the return value is undefined.
1346: */
1347:
1348: char *
1349: end_of_text ()
1350: {
1351: #ifdef TEXT_END
1352: return ((char *) TEXT_END);
1353: #else
1354: extern int etext;
1355: return ((char *) &etext);
1356: #endif
1357: }
1358:
1359: /*
1360: * Return the address of the end of the data segment prior to
1361: * doing an unexec(). After unexec() the return value is undefined.
1362: */
1363:
1364: char *
1365: end_of_data ()
1366: {
1367: #ifdef DATA_END
1368: return ((char *) DATA_END);
1369: #else
1370: extern int edata;
1371: return ((char *) &edata);
1372: #endif
1373: }
1374:
1375: #endif /* not CANNOT_DUMP */
1376:
1377: /* Get_system_name returns as its value
1378: a string for the Lisp function system-name to return. */
1379:
1380: #ifdef BSD4_1
1381: #include <whoami.h>
1382: #endif
1383:
1384: #ifdef USG
1385: /* Can't have this within the function since `static' is #defined to nothing */
1386: static struct utsname get_system_name_name;
1387: #endif
1388:
1389: char *
1390: get_system_name ()
1391: {
1392: #ifdef USG
1393: uname (&get_system_name_name);
1394: return (get_system_name_name.nodename);
1395: #else /* Not USG */
1396: #ifdef BSD4_1
1397: return sysname;
1398: #else /* not USG, not 4.1 */
1399: static char system_name_saved[32];
1400: #ifdef VMS
1401: char *sp;
1402: if ((sp = egetenv("SYS$NODE")) == 0)
1403: sp = "vax-vms";
1404: else
1405: {
1406: char *end;
1407:
1408: if ((end = index (sp, ':')) != 0)
1409: *end = '\0';
1410: }
1411: strcpy (system_name_saved, sp);
1412: #else /* not VMS */
1413: gethostname (system_name_saved, sizeof (system_name_saved));
1414: #endif /* not VMS */
1415: return system_name_saved;
1416: #endif /* not USG, not 4.1 */
1417: #endif /* not USG */
1418: }
1419:
1420: #ifndef HAVE_SELECT
1421:
1422: /* Emulate as much as select as is possible under 4.1 and needed by Gnu Emacs
1423: * Only checks read descriptors.
1424: */
1425: /* How long to wait between checking fds in select */
1426: #define SELECT_PAUSE 1
1427: int select_alarmed;
1428:
1429: /* For longjmp'ing back to read_input_waiting. */
1430:
1431: jmp_buf read_alarm_throw;
1432:
1433: /* Nonzero if the alarm signal should throw back to read_input_waiting.
1434: The read_socket_hook function sets this to 1 while it is waiting. */
1435:
1436: int read_alarm_should_throw;
1437:
1438: select_alarm ()
1439: {
1440: select_alarmed = 1;
1441: #ifdef BSD4_1
1442: sigrelse (SIGALRM);
1443: #else /* not BSD4_1 */
1444: signal (SIGALRM, SIG_IGN);
1445: #endif /* not BSD4_1 */
1446: if (read_alarm_should_throw)
1447: longjmp (read_alarm_throw, 1);
1448: }
1449:
1450: /* Only rfds are checked and timeout must point somewhere */
1451: int
1452: select (nfds, rfds, wfds, efds, timeout)
1453: int nfds;
1454: int *rfds, *wfds, *efds, *timeout;
1455: {
1456: int ravail = 0, orfds = 0, old_alarm;
1457: extern int kbd_count;
1458: extern int proc_buffered_char[];
1459: #ifndef subprocesses
1460: int child_changed = 0;
1461: #else
1462: extern int child_changed;
1463: #endif
1464: int (*old_trap) ();
1465: char buf;
1466:
1467: if (rfds)
1468: {
1469: orfds = *rfds;
1470: *rfds = 0;
1471: }
1472: if (wfds)
1473: *wfds = 0;
1474: if (efds)
1475: *efds = 0;
1476:
1477: /* If we are looking only for the terminal, with no timeout,
1478: just read it and wait -- that's more efficient. */
1479: if (orfds == 1 && *timeout == 100000 && !child_changed)
1480: {
1481: if (!kbd_count)
1482: read_input_waiting ();
1483: *rfds = 1;
1484: return 1;
1485: }
1486:
1487: /* Once a second, till the timer expires, check all the flagged read
1488: * descriptors to see if any input is available. If there is some then
1489: * set the corresponding bit in the return copy of rfds.
1490: */
1491: while (1)
1492: {
1493: register int to_check, bit, fd;
1494:
1495: if (rfds)
1496: {
1497: for (to_check = nfds, bit = 1, fd = 0; --to_check >= 0; bit <<= 1, fd++)
1498: {
1499: if (orfds & bit)
1500: {
1501: int avail = 0, status = 0;
1502:
1503: if (bit == 1)
1504: avail = detect_input_pending(); /* Special keyboard handler */
1505: else
1506: {
1507: #ifdef FIONREAD
1508: status = ioctl (fd, FIONREAD, &avail);
1509: #else /* no FIONREAD */
1510: /* Hoping it will return -1 if nothing available
1511: or 0 if all 0 chars requested are read. */
1512: if (proc_buffered_char[fd] >= 0)
1513: avail = 1;
1514: else
1515: {
1516: avail = read (fd, &buf, 1);
1517: if (avail > 0)
1518: proc_buffered_char[fd] = buf;
1519: }
1520: #endif /* no FIONREAD */
1521: }
1522: if (status >= 0 && avail > 0)
1523: {
1524: (*rfds) |= bit;
1525: ravail++;
1526: }
1527: }
1528: }
1529: }
1530: if (*timeout == 0 || ravail != 0 || child_changed)
1531: break;
1532: old_alarm = alarm (0);
1533: old_trap = (int (*)()) signal (SIGALRM, select_alarm);
1534: select_alarmed = 0;
1535: alarm (SELECT_PAUSE);
1536: /* Wait for a SIGALRM (or maybe a SIGTINT) */
1537: while (select_alarmed == 0 && *timeout != 0 && child_changed == 0)
1538: {
1539: /* If we are interested in terminal input,
1540: wait by reading the terminal.
1541: That makes instant wakeup for terminal input at least. */
1542: if (orfds & 1)
1543: {
1544: read_input_waiting ();
1545: if (kbd_count)
1546: select_alarmed = 1;
1547: }
1548: else
1549: pause();
1550: }
1551: (*timeout) -= SELECT_PAUSE;
1552: /* Reset the old alarm if there was one */
1553: alarm (0);
1554: signal (SIGALRM, old_trap);
1555: if (old_alarm != 0)
1556: {
1557: /* Reset or forge an interrupt for the original handler. */
1558: old_alarm -= SELECT_PAUSE;
1559: if (old_alarm <= 0)
1560: kill (getpid (), SIGALRM); /* Fake an alarm with the orig' handler */
1561: else
1562: alarm (old_alarm);
1563: }
1564: if (*timeout == 0) /* Stop on timer being cleared */
1565: break;
1566: }
1567: return ravail;
1568: }
1569:
1570: /* Read keyboard input into the standard buffer,
1571: waiting for at least one character. */
1572:
1573: /* Make all keyboard buffers much bigger when using X windows. */
1574: #ifdef HAVE_X_WINDOWS
1575: #define BUFFER_SIZE_FACTOR 16
1576: #else
1577: #define BUFFER_SIZE_FACTOR 1
1578: #endif
1579:
1580: read_input_waiting ()
1581: {
1582: extern int kbd_count;
1583: extern unsigned char kbd_buffer[];
1584: extern unsigned char *kbd_ptr;
1585: int val;
1586:
1587: if (read_socket_hook)
1588: {
1589: read_alarm_should_throw = 0;
1590: if (! setjmp (read_alarm_throw))
1591: val = (*read_socket_hook) (0, kbd_buffer, 256 * BUFFER_SIZE_FACTOR);
1592: else
1593: val = -1;
1594: }
1595: else
1596: val = read (fileno (stdin), kbd_buffer, 1);
1597:
1598: if (val > 0)
1599: {
1600: kbd_ptr = kbd_buffer;
1601: kbd_count = val;
1602: }
1603: }
1604:
1605: #endif /* not HAVE_SELECT */
1606:
1607: #ifdef BSD4_1
1608: /* VARARGS */
1609: setpriority ()
1610: {
1611: return 0;
1612: }
1613:
1614: /*
1615: * Partially emulate 4.2 open call.
1616: * open is defined as this in 4.1.
1617: *
1618: * - added by Michael Bloom @ Citicorp/TTI
1619: *
1620: */
1621:
1622: int
1623: sys_open (path, oflag, mode)
1624: char *path;
1625: int oflag, mode;
1626: {
1627: if (oflag & O_CREAT)
1628: return creat (path, mode);
1629: else
1630: return open (path, oflag);
1631: }
1632:
1633: init_sigio ()
1634: {
1635: if (noninteractive)
1636: return;
1637: lmode = LINTRUP | lmode;
1638: ioctl (0, TIOCLSET, &lmode);
1639: }
1640:
1641: reset_sigio ()
1642: {
1643: if (noninteractive)
1644: return;
1645: lmode = ~LINTRUP & lmode;
1646: ioctl (0, TIOCLSET, &lmode);
1647: }
1648:
1649: request_sigio ()
1650: {
1651: sigrelse (SIGTINT);
1652:
1653: interrupts_deferred = 0;
1654: }
1655:
1656: unrequest_sigio ()
1657: {
1658: sighold (SIGTINT);
1659:
1660: interrupts_deferred = 1;
1661: }
1662:
1663: /* still inside #ifdef BSD4_1 */
1664: #ifdef subprocesses
1665:
1666: int sigheld; /* Mask of held signals */
1667:
1668: sigholdx (signum)
1669: int signum;
1670: {
1671: sigheld |= sigbit (signum);
1672: sighold (signum);
1673: }
1674:
1675: sigisheld (signum)
1676: int signum;
1677: {
1678: sigheld |= sigbit (signum);
1679: }
1680:
1681: sigunhold (signum)
1682: int signum;
1683: {
1684: sigheld &= ~sigbit (signum);
1685: sigrelse (signum);
1686: }
1687:
1688: sigfree () /* Free all held signals */
1689: {
1690: int i;
1691: for (i = 0; i < NSIG; i++)
1692: if (sigheld & sigbit (i))
1693: sigrelse (i);
1694: sigheld = 0;
1695: }
1696:
1697: sigbit (i)
1698: {
1699: return 1 << (i - 1);
1700: }
1701: #endif /* subprocesses */
1702: #endif /* BSD4_1 */
1703:
1704: #ifndef BSTRING
1705:
1706: void
1707: bzero (b, length)
1708: register char *b;
1709: register int length;
1710: {
1711: #ifdef VMS
1712: short zero = 0;
1713: long max_str = 65535;
1714:
1715: while (length > max_str) {
1716: (void) LIB$MOVC5 (&zero, &zero, &zero, &max_str, b);
1717: length -= max_str;
1718: b += max_str;
1719: }
1720: (void) LIB$MOVC5 (&zero, &zero, &zero, &length, b);
1721: #else
1722: while (length-- > 0)
1723: *b++ = 0;
1724: #endif /* not VMS */
1725: }
1726:
1727: /* Saying `void' requires a declaration, above, where bcopy is used
1728: and that declaration causes pain for systems where bcopy is a macro. */
1729: bcopy (b1, b2, length)
1730: register char *b1;
1731: register char *b2;
1732: register int length;
1733: {
1734: #ifdef VMS
1735: long max_str = 65535;
1736:
1737: while (length > max_str) {
1738: (void) LIB$MOVC3 (&max_str, b1, b2);
1739: length -= max_str;
1740: b1 += max_str;
1741: b2 += max_str;
1742: }
1743: (void) LIB$MOVC3 (&length, b1, b2);
1744: #else
1745: while (length-- > 0)
1746: *b2++ = *b1++;
1747: #endif /* not VMS */
1748: }
1749:
1750: int
1751: bcmp (b1, b2, length) /* This could be a macro! */
1752: register char *b1;
1753: register char *b2;
1754: register int length;
1755: {
1756: #ifdef VMS
1757: struct dsc$descriptor_s src1 = {length, DSC$K_DTYPE_T, DSC$K_CLASS_S, b1};
1758: struct dsc$descriptor_s src2 = {length, DSC$K_DTYPE_T, DSC$K_CLASS_S, b2};
1759:
1760: return STR$COMPARE (&src1, &src2);
1761: #else
1762: while (length-- > 0)
1763: if (*b1++ != *b2++)
1764: return 1;
1765:
1766: return 0;
1767: #endif /* not VMS */
1768: }
1769: #endif /* not BSTRING */
1770:
1771: #ifdef BSD4_1
1772: long random ()
1773: {
1774: return (rand ());
1775: }
1776:
1777: srandom (arg)
1778: int arg;
1779: {
1780: srand (arg);
1781: }
1782: #endif BSD4_1
1783:
1784: #ifdef USG
1785: /*
1786: * The BSD random(3) returns numbers in the range of
1787: * 0 to 2e31 - 1. The USG rand(3C) returns numbers in the
1788: * range of 0 to 2e15 - 1. This is probably not significant
1789: * in this usage.
1790: */
1791:
1792: long
1793: random ()
1794: {
1795: /* Arrange to return a range centered on zero. */
1796: return rand () - (1 << 14);
1797: }
1798:
1799: srandom (arg)
1800: int arg;
1801: {
1802: srand (arg);
1803: }
1804:
1805: #endif /* USG */
1806:
1807:
1808: #ifdef VMS
1809:
1810: #ifdef getenv
1811: /* If any place else asks for the TERM variable,
1812: allow it to be overridden with the EMACS_TERM variable
1813: before attempting to translate the logical name TERM. As a last
1814: resort, ask for VAX C's special idea of the TERM variable. */
1815: #undef getenv
1816: char *
1817: sys_getenv (name)
1818: char *name;
1819: {
1820: register char *val;
1821: static char buf[256];
1822: static struct dsc$descriptor_s equiv
1823: = {sizeof(buf), DSC$K_DTYPE_T, DSC$K_CLASS_S, buf};
1824: static struct dsc$descriptor_s d_name
1825: = {0, DSC$K_DTYPE_T, DSC$K_CLASS_S, 0};
1826: short eqlen;
1827:
1828: if (!strcmp (name, "TERM"))
1829: {
1830: val = (char *) getenv ("EMACS_TERM");
1831: if (val)
1832: return val;
1833: }
1834:
1835: d_name.dsc$w_length = strlen (name);
1836: d_name.dsc$a_pointer = name;
1837: if (lib$sys_trnlog (&d_name, &eqlen, &equiv) == 1)
1838: {
1839: char *str = (char *) xmalloc (eqlen + 1);
1840: bcopy (buf, str, eqlen);
1841: str[eqlen] = '\0';
1842: /* This is a storage leak, but a pain to fix. With luck,
1843: no one will ever notice. */
1844: return str;
1845: }
1846: return (char *) getenv (name);
1847: }
1848: #endif /* getenv */
1849:
1850: #ifdef abort
1851: /* Since VMS doesn't believe in core dumps, the only way to debug this beast is
1852: to force a call on the debugger from within the image. */
1853: #undef abort
1854: sys_abort ()
1855: {
1856: reset_sys_modes ();
1857: LIB$SIGNAL (SS$_DEBUG);
1858: }
1859: #endif /* abort */
1860: #endif /* VMS */
1861:
1862: #ifdef VMS
1863: #ifdef LINK_CRTL_SHARE
1864: #ifdef SHAREABLE_LIB_BUG
1865: /* Variables declared noshare and initialized in shareable libraries
1866: cannot be shared. The VMS linker incorrectly forces you to use a private
1867: version which is uninitialized... If not for this "feature", we
1868: could use the C library definition of sys_nerr and sys_errlist. */
1869: int sys_nerr = 35;
1870: char *sys_errlist[] =
1871: {
1872: "error 0",
1873: "not owner",
1874: "no such file or directory",
1875: "no such process",
1876: "interrupted system call",
1877: "i/o error",
1878: "no such device or address",
1879: "argument list too long",
1880: "exec format error",
1881: "bad file number",
1882: "no child process",
1883: "no more processes",
1884: "not enough memory",
1885: "permission denied",
1886: "bad address",
1887: "block device required",
1888: "mount devices busy",
1889: "file exists",
1890: "cross-device link",
1891: "no such device",
1892: "not a directory",
1893: "is a directory",
1894: "invalid argument",
1895: "file table overflow",
1896: "too many open files",
1897: "not a typewriter",
1898: "text file busy",
1899: "file too big",
1900: "no space left on device",
1901: "illegal seek",
1902: "read-only file system",
1903: "too many links",
1904: "broken pipe",
1905: "math argument",
1906: "result too large",
1907: "I/O stream empty",
1908: "vax/vms specific error code nontranslatable error"
1909: };
1910: #endif /* SHAREABLE_LIB_BUG */
1911: #endif /* LINK_CRTL_SHARE */
1912: #endif /* VMS */
1913:
1914: #ifdef INTERRUPTABLE_OPEN
1915:
1916: int
1917: /* VARARGS 2 */
1918: sys_open (path, oflag, mode)
1919: char *path;
1920: int oflag, mode;
1921: {
1922: register int rtnval;
1923:
1924: while ((rtnval = open (path, oflag, mode)) == -1 && errno == EINTR);
1925: return (rtnval);
1926: }
1927:
1928: #endif /* INTERRUPTABLE_OPEN */
1929:
1930: #ifdef INTERRUPTABLE_CLOSE
1931:
1932: sys_close (fd)
1933: int fd;
1934: {
1935: register int rtnval;
1936:
1937: while ((rtnval = close(fd)) == -1 && errno == EINTR);
1938: return rtnval;
1939: }
1940:
1941: #endif /* INTERRUPTABLE_CLOSE */
1942:
1943: #ifdef INTERRUPTABLE_IO
1944:
1945: int
1946: sys_read (fildes, buf, nbyte)
1947: int fildes;
1948: char *buf;
1949: unsigned int nbyte;
1950: {
1951: register int rtnval;
1952:
1953: while ((rtnval = read (fildes, buf, nbyte)) == -1 && errno == EINTR);
1954: return (rtnval);
1955: }
1956:
1957: int
1958: sys_write (fildes, buf, nbyte)
1959: int fildes;
1960: char *buf;
1961: unsigned int nbyte;
1962: {
1963: register int rtnval;
1964:
1965: while ((rtnval = write (fildes, buf, nbyte)) == -1 && errno == EINTR);
1966: return (rtnval);
1967: }
1968:
1969: #endif /* INTERRUPTABLE_IO */
1970:
1971: #ifdef USG
1972: /*
1973: * All of the following are for USG.
1974: *
1975: * On USG systems the system calls are interruptable by signals
1976: * that the user program has elected to catch. Thus the system call
1977: * must be retried in these cases. To handle this without massive
1978: * changes in the source code, we remap the standard system call names
1979: * to names for our own functions in sysdep.c that do the system call
1980: * with retries. Actually, for portability reasons, it is good
1981: * programming practice, as this example shows, to limit all actual
1982: * system calls to a single occurance in the source. Sure, this
1983: * adds an extra level of function call overhead but it is almost
1984: * always negligible. Fred Fish, Unisoft Systems Inc.
1985: */
1986:
1987: char *sys_siglist[NSIG + 1] =
1988: {
1989: #ifdef IBMRTAIX
1990: /* AIX has changed the signals a bit */
1991: "bogus signal", /* 0 */
1992: "hangup", /* 1 SIGHUP */
1993: "interrupt", /* 2 SIGINT */
1994: "quit", /* 3 SIGQUIT */
1995: "illegal instruction", /* 4 SIGILL */
1996: "trace trap", /* 5 SIGTRAP */
1997: "IOT instruction", /* 6 SIGIOT */
1998: "crash likely", /* 7 SIGDANGER */
1999: "floating point exception", /* 8 SIGFPE */
2000: "kill", /* 9 SIGKILL */
2001: "bus error", /* 10 SIGBUS */
2002: "segmentation violation", /* 11 SIGSEGV */
2003: "bad argument to system call", /* 12 SIGSYS */
2004: "write on a pipe with no one to read it", /* 13 SIGPIPE */
2005: "alarm clock", /* 14 SIGALRM */
2006: "software termination signum", /* 15 SIGTERM */
2007: "user defined signal 1", /* 16 SIGUSR1 */
2008: "user defined signal 2", /* 17 SIGUSR2 */
2009: "death of a child", /* 18 SIGCLD */
2010: "power-fail restart", /* 19 SIGPWR */
2011: "bogus signal", /* 20 */
2012: "bogus signal", /* 21 */
2013: "bogus signal", /* 22 */
2014: "bogus signal", /* 23 */
2015: "bogus signal", /* 24 */
2016: "LAN I/O interrupt", /* 25 SIGAIO */
2017: "PTY I/O interrupt", /* 26 SIGPTY */
2018: "I/O intervention required", /* 27 SIGIOINT */
2019: "HFT grant", /* 28 SIGGRANT */
2020: "HFT retract", /* 29 SIGRETRACT */
2021: "HFT sound done", /* 30 SIGSOUND */
2022: "HFT input ready", /* 31 SIGMSG */
2023: #else /* not IBMRTAIX */
2024: "bogus signal", /* 0 */
2025: "hangup", /* 1 SIGHUP */
2026: "interrupt", /* 2 SIGINT */
2027: "quit", /* 3 SIGQUIT */
2028: "illegal instruction", /* 4 SIGILL */
2029: "trace trap", /* 5 SIGTRAP */
2030: "IOT instruction", /* 6 SIGIOT */
2031: "EMT instruction", /* 7 SIGEMT */
2032: "floating point exception", /* 8 SIGFPE */
2033: "kill", /* 9 SIGKILL */
2034: "bus error", /* 10 SIGBUS */
2035: "segmentation violation", /* 11 SIGSEGV */
2036: "bad argument to system call", /* 12 SIGSYS */
2037: "write on a pipe with no one to read it", /* 13 SIGPIPE */
2038: "alarm clock", /* 14 SIGALRM */
2039: "software termination signum", /* 15 SIGTERM */
2040: "user defined signal 1", /* 16 SIGUSR1 */
2041: "user defined signal 2", /* 17 SIGUSR2 */
2042: "death of a child", /* 18 SIGCLD */
2043: "power-fail restart", /* 19 SIGPWR */
2044: #endif /* not IBMRTAIX */
2045: 0
2046: };
2047:
2048: /*
2049: * Warning, this function may not duplicate 4.2 action properly
2050: * under error conditions.
2051: */
2052:
2053: #ifndef MAXPATHLEN
2054: /* In 4.1, param.h fails to define this. */
2055: #define MAXPATHLEN 1024
2056: #endif
2057:
2058: #ifndef HAVE_GETWD
2059:
2060: char *
2061: getwd (pathname)
2062: char *pathname;
2063: {
2064: char *npath, *spath;
2065: extern char *getcwd ();
2066:
2067: spath = npath = getcwd ((char *) 0, MAXPATHLEN);
2068: /* On Altos 3068, getcwd can return @hostname/dir, so discard
2069: up to first slash. Should be harmless on other systems. */
2070: while (*npath && *npath != '/')
2071: npath++;
2072: strcpy (pathname, npath);
2073: free (spath); /* getcwd uses malloc */
2074: return pathname;
2075: }
2076:
2077: #endif HAVE_GETWD
2078:
2079: /*
2080: * Emulate rename using unlink/link. Note that this is
2081: * only partially correct. Also, doesn't enforce restriction
2082: * that files be of same type (regular->regular, dir->dir, etc).
2083: */
2084:
2085: rename (from, to)
2086: char *from;
2087: char *to;
2088: {
2089: if (access (from, 0) == 0)
2090: {
2091: unlink (to);
2092: if (link (from, to) == 0)
2093: if (unlink (from) == 0)
2094: return (0);
2095: }
2096: return (-1);
2097: }
2098:
2099: /* VARARGS */
2100: setpriority ()
2101: {
2102: return (0);
2103: }
2104:
2105: #ifndef HAVE_VFORK
2106:
2107: /*
2108: * Substitute fork(2) for vfork(2) on USG flavors.
2109: */
2110:
2111: vfork ()
2112: {
2113: return (fork ());
2114: }
2115:
2116: #endif /* not HAVE_VFORK */
2117:
2118: #ifdef MISSING_UTIMES
2119:
2120: /* HPUX (among others) sets HAVE_TIMEVAL but does not implement utimes. */
2121:
2122: utimes ()
2123: {
2124: }
2125: #endif
2126:
2127: #ifdef IRIS_UTIME
2128:
2129: /* The IRIS (3.5) has timevals, but uses sys V utime, and doesn't have the
2130: utimbuf structure defined anywhere but in the man page. */
2131:
2132: struct utimbuf
2133: {
2134: long actime;
2135: long modtime;
2136: };
2137:
2138: utimes (name, tvp)
2139: char *name;
2140: struct timeval tvp[];
2141: {
2142: struct utimbuf utb;
2143: utb.actime = tvp[0].tv_sec;
2144: utb.modtime = tvp[1].tv_sec;
2145: utime (name, &utb);
2146: }
2147: #endif /* IRIS_UTIME */
2148:
2149:
2150: #ifdef HPUX
2151:
2152: /* HPUX curses library references perror, but as far as we know
2153: it won't be called. Anyway this definition will do for now. */
2154:
2155: perror ()
2156: {
2157: }
2158:
2159: #endif /* HPUX */
2160:
2161: #ifndef HAVE_DUP2
2162:
2163: /*
2164: * Emulate BSD dup2(2). First close newd if it already exists.
2165: * Then, attempt to dup oldd. If not successful, call dup2 recursively
2166: * until we are, then close the unsuccessful ones.
2167: */
2168:
2169: dup2 (oldd, newd)
2170: int oldd;
2171: int newd;
2172: {
2173: register int fd;
2174:
2175: sys_close (newd);
2176:
2177: #ifdef F_DUPFD
2178: fd = fcntl (oldd, F_DUPFD, newd);
2179: if (fd != newd)
2180: error ("cant dup2(%i,%i) : %s", oldd, newd, sys_errlist[errno]);
2181: #else
2182: while ((fd = dup (oldd)) != newd)
2183: {
2184: dup2 (oldd, newd);
2185: sys_close (fd);
2186: }
2187: #endif
2188: }
2189:
2190: #endif /* not HAVE_DUP2 */
2191:
2192: /*
2193: * Gettimeofday. Simulate as much as possible. Only accurate
2194: * to nearest second. Emacs doesn't use tzp so ignore it for now.
2195: * Only needed when subprocesses are defined.
2196: */
2197:
2198: #ifdef subprocesses
2199: #ifndef HAVE_GETTIMEOFDAY
2200: #ifdef HAVE_TIMEVAL
2201:
2202: /* ARGSUSED */
2203: gettimeofday (tp, tzp)
2204: struct timeval *tp;
2205: struct timezone *tzp;
2206: {
2207: extern long time ();
2208:
2209: tp->tv_sec = time ((long *)0);
2210: tp->tv_usec = 0;
2211: }
2212:
2213: #endif
2214: #endif
2215: #endif /* subprocess && !HAVE_GETTIMEOFDAY && HAVE_TIMEVAL */
2216:
2217: /*
2218: * This function will go away as soon as all the stubs fixed. (fnf)
2219: */
2220:
2221: croak (badfunc)
2222: char *badfunc;
2223: {
2224: printf ("%s not yet implemented\r\n", badfunc);
2225: reset_sys_modes ();
2226: exit (1);
2227: }
2228:
2229: #endif /* USG */
2230:
2231: /* Directory routines for systems that don't have them. */
2232:
2233: #ifdef SYSV_SYSTEM_DIR
2234:
2235: #include <dirent.h>
2236:
2237: #ifndef HAVE_CLOSEDIR
2238: int
2239: closedir (dirp)
2240: register DIR *dirp; /* stream from opendir() */
2241: {
2242: sys_close (dirp->dd_fd);
2243: free ((char *) dirp->dd_buf); /* directory block defined in <dirent.h> */
2244: free ((char *) dirp);
2245: }
2246: #endif /* not HAVE_CLOSEDIR */
2247:
2248: #endif /* SYSV_SYSTEM_DIR */
2249:
2250: #ifdef NONSYSTEM_DIR_LIBRARY
2251:
2252: DIR *
2253: opendir (filename)
2254: char *filename; /* name of directory */
2255: {
2256: register DIR *dirp; /* -> malloc'ed storage */
2257: register int fd; /* file descriptor for read */
2258: struct stat sbuf; /* result of fstat() */
2259:
2260: fd = sys_open (filename, 0);
2261: if (fd < 0)
2262: return 0;
2263:
2264: if (fstat (fd, &sbuf) < 0
2265: || (sbuf.st_mode & S_IFMT) != S_IFDIR
2266: || (dirp = (DIR *) malloc (sizeof (DIR))) == 0)
2267: {
2268: sys_close (fd);
2269: return 0; /* bad luck today */
2270: }
2271:
2272: dirp->dd_fd = fd;
2273: dirp->dd_loc = dirp->dd_size = 0; /* refill needed */
2274:
2275: return dirp;
2276: }
2277:
2278: void
2279: closedir (dirp)
2280: register DIR *dirp; /* stream from opendir() */
2281: {
2282: sys_close (dirp->dd_fd);
2283: free ((char *) dirp);
2284: }
2285:
2286:
2287: #ifndef VMS
2288: #define DIRSIZ 14
2289: struct olddir
2290: {
2291: ino_t od_ino; /* inode */
2292: char od_name[DIRSIZ]; /* filename */
2293: };
2294: #endif /* not VMS */
2295:
2296: struct direct dir_static; /* simulated directory contents */
2297:
2298: /* ARGUSED */
2299: struct direct *
2300: readdir (dirp)
2301: register DIR *dirp; /* stream from opendir() */
2302: {
2303: #ifndef VMS
2304: register struct olddir *dp; /* -> directory data */
2305: #else /* VMS */
2306: register struct dir$_name *dp; /* -> directory data */
2307: register struct dir$_version *dv; /* -> version data */
2308: #endif /* VMS */
2309:
2310: for (; ;)
2311: {
2312: if (dirp->dd_loc >= dirp->dd_size)
2313: dirp->dd_loc = dirp->dd_size = 0;
2314:
2315: if (dirp->dd_size == 0 /* refill buffer */
2316: && (dirp->dd_size = sys_read (dirp->dd_fd, dirp->dd_buf, DIRBLKSIZ)) <= 0)
2317: return 0;
2318:
2319: #ifndef VMS
2320: dp = (struct olddir *) &dirp->dd_buf[dirp->dd_loc];
2321: dirp->dd_loc += sizeof (struct olddir);
2322:
2323: if (dp->od_ino != 0) /* not deleted entry */
2324: {
2325: dir_static.d_ino = dp->od_ino;
2326: strncpy (dir_static.d_name, dp->od_name, DIRSIZ);
2327: dir_static.d_name[DIRSIZ] = '\0';
2328: dir_static.d_namlen = strlen (dir_static.d_name);
2329: dir_static.d_reclen = sizeof (struct direct)
2330: - MAXNAMLEN + 3
2331: + dir_static.d_namlen - dir_static.d_namlen % 4;
2332: return &dir_static; /* -> simulated structure */
2333: }
2334: #else /* VMS */
2335: dp = (struct dir$_name *) dirp->dd_buf;
2336: if (dirp->dd_loc == 0)
2337: dirp->dd_loc = (dp->dir$b_namecount&1) ? dp->dir$b_namecount + 1
2338: : dp->dir$b_namecount;
2339: dv = (struct dir$_version *)&dp->dir$t_name[dirp->dd_loc];
2340: dir_static.d_ino = dv->dir$w_fid_num;
2341: dir_static.d_namlen = dp->dir$b_namecount;
2342: dir_static.d_reclen = sizeof (struct direct)
2343: - MAXNAMLEN + 3
2344: + dir_static.d_namlen - dir_static.d_namlen % 4;
2345: strncpy (dir_static.d_name, dp->dir$t_name, dp->dir$b_namecount);
2346: dir_static.d_name[dir_static.d_namlen] = '\0';
2347: dirp->dd_loc = dirp->dd_size; /* only one record at a time */
2348: return &dir_static;
2349: #endif /* VMS */
2350: }
2351: }
2352:
2353: #ifdef VMS
2354: /* readdirver is just like readdir except it returns all versions of a file
2355: as separate entries. */
2356:
2357: /* ARGUSED */
2358: struct direct *
2359: readdirver (dirp)
2360: register DIR *dirp; /* stream from opendir() */
2361: {
2362: register struct dir$_name *dp; /* -> directory data */
2363: register struct dir$_version *dv; /* -> version data */
2364:
2365: if (dirp->dd_loc >= dirp->dd_size - sizeof (struct dir$_name))
2366: dirp->dd_loc = dirp->dd_size = 0;
2367:
2368: if (dirp->dd_size == 0 /* refill buffer */
2369: && (dirp->dd_size = sys_read (dirp->dd_fd, dirp->dd_buf, DIRBLKSIZ)) <= 0)
2370: return 0;
2371:
2372: dp = (struct dir$_name *) dirp->dd_buf;
2373: if (dirp->dd_loc == 0)
2374: dirp->dd_loc = (dp->dir$b_namecount & 1) ? dp->dir$b_namecount + 1
2375: : dp->dir$b_namecount;
2376: dv = (struct dir$_version *) &dp->dir$t_name[dirp->dd_loc];
2377: strncpy (dir_static.d_name, dp->dir$t_name, dp->dir$b_namecount);
2378: sprintf (&dir_static.d_name[dp->dir$b_namecount], ";%d", dv->dir$w_version);
2379: dir_static.d_namlen = strlen (dir_static.d_name);
2380: dir_static.d_ino = dv->dir$w_fid_num;
2381: dir_static.d_reclen = sizeof (struct direct) - MAXNAMLEN + 3
2382: + dir_static.d_namlen - dir_static.d_namlen % 4;
2383: dirp->dd_loc = ((char *) (++dv) - dp->dir$t_name);
2384: return &dir_static;
2385: }
2386:
2387: #endif /* VMS */
2388:
2389: #endif /* NONSYSTEM_DIR_LIBRARY */
2390:
2391: /* Functions for VMS */
2392: #ifdef VMS
2393: #include <pwd.h>
2394: #include <acldef.h>
2395: #include <chpdef.h>
2396: #include <jpidef.h>
2397:
2398: /* Return as a string the VMS error string pertaining to STATUS.
2399: Reuses the same static buffer each time it is called. */
2400:
2401: char *
2402: vmserrstr (status)
2403: int status; /* VMS status code */
2404: {
2405: int bufadr[2];
2406: short len;
2407: static char buf[257];
2408:
2409: bufadr[0] = sizeof buf - 1;
2410: bufadr[1] = buf;
2411: if (! (SYS$GETMSG (status, &len, bufadr, 0x1, 0) & 1))
2412: return "untranslatable VMS error status";
2413: buf[len] = '\0';
2414: return buf;
2415: }
2416:
2417: #ifdef access
2418: #undef access
2419:
2420: /* The following is necessary because 'access' emulation by VMS C (2.0) does
2421: * not work correctly. (It also doesn't work well in version 2.3.)
2422: */
2423:
2424: #ifdef VMS4_4
2425:
2426: #define DESCRIPTOR(name,string) struct dsc$descriptor_s name = \
2427: { strlen(string), DSC$K_DTYPE_T, DSC$K_CLASS_S, string }
2428:
2429: typedef union {
2430: struct {
2431: unsigned short s_buflen;
2432: unsigned short s_code;
2433: char *s_bufadr;
2434: unsigned short *s_retlenadr;
2435: } s;
2436: int end;
2437: } item;
2438: #define buflen s.s_buflen
2439: #define code s.s_code
2440: #define bufadr s.s_bufadr
2441: #define retlenadr s.s_retlenadr
2442:
2443: #define R_OK 4 /* test for read permission */
2444: #define W_OK 2 /* test for write permission */
2445: #define X_OK 1 /* test for execute (search) permission */
2446: #define F_OK 0 /* test for presence of file */
2447:
2448: int
2449: sys_access (path, mode)
2450: char *path;
2451: int mode;
2452: {
2453: static char *user = NULL;
2454: char dir_fn[512];
2455:
2456: /* translate possible directory spec into .DIR file name, so brain-dead
2457: * access() can treat the directory like a file. */
2458: if (directory_file_name (path, dir_fn))
2459: path = dir_fn;
2460:
2461: if (mode == F_OK)
2462: return access (path, mode);
2463: if (user == NULL && (user = getenv ("USER")) == NULL)
2464: return -1;
2465: {
2466: int stat;
2467: int flags;
2468: int acces;
2469: int dummy;
2470: item itemlst[3];
2471: DESCRIPTOR(path_desc, path);
2472: DESCRIPTOR(user_desc, user);
2473:
2474: flags = 0;
2475: acces = 0;
2476: if ((mode & X_OK) && ((stat = access(path, mode)) < 0 || mode == X_OK))
2477: return stat;
2478: if (mode & R_OK)
2479: acces |= CHP$M_READ;
2480: if (mode & W_OK)
2481: acces |= CHP$M_WRITE;
2482: itemlst[0].buflen = sizeof (int);
2483: itemlst[0].code = CHP$_FLAGS;
2484: itemlst[0].bufadr = &flags;
2485: itemlst[0].retlenadr = &dummy;
2486: itemlst[1].buflen = sizeof (int);
2487: itemlst[1].code = CHP$_ACCESS;
2488: itemlst[1].bufadr = &acces;
2489: itemlst[1].retlenadr = &dummy;
2490: itemlst[2].end = CHP$_END;
2491: stat = SYS$CHECK_ACCESS(&ACL$C_FILE, &path_desc, &user_desc, itemlst);
2492: return stat == SS$_NORMAL ? 0 : -1;
2493: }
2494: }
2495:
2496: #else /* not VMS4_4 */
2497:
2498: #include <prvdef.h>
2499: #define ACE$M_WRITE 2
2500: #define ACE$C_KEYID 1
2501:
2502: static unsigned short memid, grpid;
2503: static unsigned int uic;
2504:
2505: /* Called from init_sys_modes, so it happens not very often
2506: but at least each time Emacs is loaded. */
2507: sys_access_reinit ()
2508: {
2509: uic = 0;
2510: }
2511:
2512: int
2513: sys_access (filename, type)
2514: char * filename;
2515: int type;
2516: {
2517: struct FAB fab;
2518: struct XABPRO xab;
2519: int status, prvmask[2], size, i, typecode, acl_controlled;
2520: unsigned int *aclptr, *aclend, aclbuf[60];
2521:
2522: /* Get UIC and GRP values for protection checking. */
2523: if (uic == 0)
2524: {
2525: status = LIB$GETJPI (&JPI$_UIC, 0, 0, &uic, 0, 0);
2526: if (! (status & 1))
2527: return -1;
2528: memid = uic & 0xFFFF;
2529: grpid = uic >> 16;
2530: }
2531:
2532: if (type != 2) /* not checking write access */
2533: return access (filename, type);
2534:
2535: /* Check write protection. */
2536:
2537: #define CHECKPRIV(bit) (prvmask[bit / 32] & (1 << (bit % 32)))
2538: #define WRITEABLE(field) (! ((xab.xab$w_pro >> field) & XAB$M_NOWRITE))
2539:
2540: /* Find privilege bits */
2541: status = sys$setprv (0, 0, 0, prvmask);
2542: if (! (status & 1))
2543: error ("Unable to find privileges: %s", vmserrstr (status));
2544: if (CHECKPRIV (PRV$V_BYPASS))
2545: return 0; /* BYPASS enabled */
2546: fab = cc$rms_fab;
2547: fab.fab$b_fac = FAB$M_GET;
2548: fab.fab$l_fna = filename;
2549: fab.fab$b_fns = strlen (filename);
2550: fab.fab$l_xab = &xab;
2551: xab = cc$rms_xabpro;
2552: xab.xab$l_aclbuf = aclbuf;
2553: xab.xab$w_aclsiz = sizeof (aclbuf);
2554: status = sys$open (&fab, 0, 0);
2555: if (! (status & 1))
2556: return -1;
2557: sys$close (&fab, 0, 0);
2558: /* Check system access */
2559: if (CHECKPRIV (PRV$V_SYSPRV) && WRITEABLE (XAB$V_SYS))
2560: return 0;
2561: /* Check ACL entries, if any */
2562: acl_controlled = 0;
2563: if (xab.xab$w_acllen > 0)
2564: {
2565: aclptr = aclbuf;
2566: aclend = &aclbuf[xab.xab$w_acllen / 4];
2567: while (*aclptr && aclptr < aclend)
2568: {
2569: size = (*aclptr & 0xff) / 4;
2570: typecode = (*aclptr >> 8) & 0xff;
2571: if (typecode == ACE$C_KEYID)
2572: for (i = size - 1; i > 1; i--)
2573: if (aclptr[i] == uic)
2574: {
2575: acl_controlled = 1;
2576: if (aclptr[1] & ACE$M_WRITE)
2577: return 0; /* Write access through ACL */
2578: }
2579: aclptr = &aclptr[size];
2580: }
2581: if (acl_controlled) /* ACL specified, prohibits write access */
2582: return -1;
2583: }
2584: /* No ACL entries specified, check normal protection */
2585: if (WRITEABLE (XAB$V_WLD)) /* World writeable */
2586: return 0;
2587: if (WRITEABLE (XAB$V_GRP) &&
2588: (unsigned short) (xab.xab$l_uic >> 16) == grpid)
2589: return 0; /* Group writeable */
2590: if (WRITEABLE (XAB$V_OWN) &&
2591: (xab.xab$l_uic & 0xFFFF) == memid)
2592: return 0; /* Owner writeable */
2593:
2594: return -1; /* Not writeable */
2595: }
2596: #endif /* not VMS4_4 */
2597: #endif /* access */
2598:
2599: static char vtbuf[NAM$C_MAXRSS+1];
2600:
2601: /* translate a vms file spec to a unix path */
2602: char *
2603: sys_translate_vms (vfile)
2604: char * vfile;
2605: {
2606: char * p;
2607: char * targ;
2608:
2609: if (!vfile)
2610: return 0;
2611:
2612: targ = vtbuf;
2613:
2614: /* leading device or logical name is a root directory */
2615: if (p = strchr (vfile, ':'))
2616: {
2617: *targ++ = '/';
2618: while (vfile < p)
2619: *targ++ = *vfile++;
2620: vfile++;
2621: *targ++ = '/';
2622: }
2623: p = vfile;
2624: if (*p == '[' || *p == '<')
2625: {
2626: while (*++vfile != *p + 2)
2627: switch (*vfile)
2628: {
2629: case '.':
2630: if (vfile[-1] == *p)
2631: *targ++ = '.';
2632: *targ++ = '/';
2633: break;
2634:
2635: case '-':
2636: *targ++ = '.';
2637: *targ++ = '.';
2638: break;
2639:
2640: default:
2641: *targ++ = *vfile;
2642: break;
2643: }
2644: vfile++;
2645: *targ++ = '/';
2646: }
2647: while (*vfile)
2648: *targ++ = *vfile++;
2649:
2650: return vtbuf;
2651: }
2652:
2653: static char utbuf[NAM$C_MAXRSS+1];
2654:
2655: /* translate a unix path to a VMS file spec */
2656: char *
2657: sys_translate_unix (ufile)
2658: char * ufile;
2659: {
2660: int slash_seen = 0;
2661: char *p;
2662: char * targ;
2663:
2664: if (!ufile)
2665: return 0;
2666:
2667: targ = utbuf;
2668:
2669: if (*ufile == '/')
2670: {
2671: ufile++;
2672: }
2673:
2674: while (*ufile)
2675: {
2676: switch (*ufile)
2677: {
2678: case '/':
2679: if (slash_seen)
2680: if (index (&ufile[1], '/'))
2681: *targ++ = '.';
2682: else
2683: *targ++ = ']';
2684: else
2685: {
2686: *targ++ = ':';
2687: if (index (&ufile[1], '/'))
2688: *targ++ = '[';
2689: slash_seen = 1;
2690: }
2691: break;
2692:
2693: case '.':
2694: if (strncmp (ufile, "./", 2) == 0)
2695: {
2696: if (!slash_seen)
2697: {
2698: *targ++ = '[';
2699: slash_seen = 1;
2700: }
2701: ufile++; /* skip the dot */
2702: if (index (&ufile[1], '/'))
2703: *targ++ = '.';
2704: else
2705: *targ++ = ']';
2706: }
2707: else if (strncmp (ufile, "../", 3) == 0)
2708: {
2709: if (!slash_seen)
2710: {
2711: *targ++ = '[';
2712: slash_seen = 1;
2713: }
2714: *targ++ = '-';
2715: ufile += 2; /* skip the dots */
2716: if (index (&ufile[1], '/'))
2717: *targ++ = '.';
2718: else
2719: *targ++ = ']';
2720: }
2721: else
2722: *targ++ = *ufile;
2723: break;
2724:
2725: default:
2726: *targ++ = *ufile;
2727: break;
2728: }
2729: ufile++;
2730: }
2731: *targ = '\0';
2732:
2733: return utbuf;
2734: }
2735:
2736: char *
2737: getwd (pathname)
2738: char *pathname;
2739: {
2740: char *ptr;
2741: strcpy (pathname, egetenv ("PATH"));
2742:
2743: ptr = pathname;
2744: while (*ptr)
2745: {
2746: if ('a' <= *ptr && *ptr <= 'z')
2747: *ptr -= 040;
2748: ptr++;
2749: }
2750: return pathname;
2751: }
2752:
2753: getppid ()
2754: {
2755: long item_code = JPI$_OWNER;
2756: unsigned long parent_id;
2757: int status;
2758:
2759: if (((status = LIB$GETJPI (&item_code, 0, 0, &parent_id)) & 1) == 0)
2760: {
2761: errno = EVMSERR;
2762: vaxc$errno = status;
2763: return -1;
2764: }
2765: return parent_id;
2766: }
2767:
2768: #undef getuid
2769: unsigned
2770: sys_getuid ()
2771: {
2772: return (getgid () << 16) | getuid ();
2773: }
2774:
2775: int
2776: sys_read (fildes, buf, nbyte)
2777: int fildes;
2778: char *buf;
2779: unsigned int nbyte;
2780: {
2781: return read (fildes, buf, (nbyte < MAXIOSIZE ? nbyte : MAXIOSIZE));
2782: }
2783:
2784: #if 0
2785: int
2786: sys_write (fildes, buf, nbyte)
2787: int fildes;
2788: char *buf;
2789: unsigned int nbyte;
2790: {
2791: register int nwrote, rtnval = 0;
2792:
2793: while (nbyte > MAXIOSIZE && (nwrote = write (fildes, buf, MAXIOSIZE)) > 0) {
2794: nbyte -= nwrote;
2795: buf += nwrote;
2796: rtnval += nwrote;
2797: }
2798: if (nwrote < 0)
2799: return rtnval ? rtnval : -1;
2800: if ((nwrote = write (fildes, buf, nbyte)) < 0)
2801: return rtnval ? rtnval : -1;
2802: return (rtnval + nwrote);
2803: }
2804: #endif /* 0 */
2805:
2806: /*
2807: * VAX/VMS VAX C RTL really loses. It insists that records
2808: * end with a newline (carriage return) character, and if they
2809: * don't it adds one (nice of it isn't it!)
2810: *
2811: * Thus we do this stupidity below.
2812: */
2813:
2814: int
2815: sys_write (fildes, buf, nbytes)
2816: int fildes;
2817: char *buf;
2818: unsigned int nbytes;
2819: {
2820: register char *p;
2821: register char *e;
2822: int retval, sum;
2823: p = buf;
2824: sum = 0;
2825: while (nbytes > 0)
2826: {
2827: e = p + min (MAXIOSIZE, nbytes) - 1;
2828: while (*e != '\n' && e > p) e--;
2829: if (p == e) /* Ok.. so here we add a newline... sigh. */
2830: e = p + min (MAXIOSIZE, nbytes) - 1;
2831: retval = write (fildes, p, e - p + 1);
2832: if (retval != e - p + 1) return -1;
2833: p = e + 1;
2834: sum = sum + retval;
2835: nbytes -= retval;
2836: }
2837: return sum;
2838: }
2839:
2840: /* Create file NEW copying its attributes from file OLD. If
2841: OLD is 0 or does not exist, create based on the value of
2842: vms_stmlf_recfm. */
2843:
2844: int
2845: creat_copy_attrs (old, new)
2846: char *old, *new;
2847: {
2848: struct FAB fab = cc$rms_fab;
2849: struct XABPRO xabpro;
2850: char aclbuf[256]; /* Choice of size is arbitrary. See below. */
2851: extern int vms_stmlf_recfm;
2852:
2853: if (old)
2854: {
2855: fab.fab$b_fac = FAB$M_GET;
2856: fab.fab$l_fna = old;
2857: fab.fab$b_fns = strlen (old);
2858: fab.fab$l_xab = &xabpro;
2859: xabpro = cc$rms_xabpro;
2860: xabpro.xab$l_aclbuf = aclbuf;
2861: xabpro.xab$w_aclsiz = sizeof aclbuf;
2862: /* Call $OPEN to fill in the fab & xabpro fields. */
2863: if (sys$open (&fab, 0, 0) & 1)
2864: {
2865: sys$close (&fab, 0, 0);
2866: fab.fab$l_alq = 0; /* zero the allocation quantity */
2867: if (xabpro.xab$w_acllen > 0)
2868: {
2869: if (xabpro.xab$w_acllen > sizeof aclbuf)
2870: /* If the acl buffer was too short, redo open with longer one.
2871: Wouldn't need to do this if there were some system imposed
2872: limit on the size of an ACL, but I can't find any such. */
2873: {
2874: xabpro.xab$l_aclbuf = alloca (xabpro.xab$w_acllen);
2875: xabpro.xab$w_aclsiz = xabpro.xab$w_acllen;
2876: if (sys$open (&fab, 0, 0) & 1)
2877: sys$close (&fab, 0, 0);
2878: else
2879: old = 0;
2880: }
2881: }
2882: else
2883: xabpro.xab$l_aclbuf = 0;
2884: }
2885: else
2886: old = 0;
2887: }
2888: fab.fab$l_fna = new;
2889: fab.fab$b_fns = strlen (new);
2890: if (!old)
2891: {
2892: fab.fab$l_xab = 0;
2893: fab.fab$b_rfm = vms_stmlf_recfm ? FAB$C_STMLF : FAB$C_VAR;
2894: fab.fab$b_rat = FAB$M_CR;
2895: }
2896: /* Create the new file with either default attrs or attrs copied
2897: from old file. */
2898: if (!(SYS$CREATE (&fab, 0, 0) & 1))
2899: return -1;
2900: sys$close (&fab, 0, 0);
2901: /* As this is a "replacement" for creat, return a file descriptor
2902: opened for writing. */
2903: return open (new, O_WRONLY);
2904: }
2905:
2906: #ifdef creat
2907: #undef creat
2908: #include <varargs.h>
2909:
2910: sys_creat (va_alist)
2911: va_dcl
2912: {
2913: va_list list_incrementor;
2914: char *name;
2915: int mode;
2916: int rfd; /* related file descriptor */
2917: int fd; /* Our new file descriptor */
2918: int count;
2919: struct stat st_buf;
2920: char rfm[12];
2921: char rat[15];
2922: char mrs[13];
2923: char fsz[13];
2924: extern int vms_stmlf_recfm;
2925:
2926: va_count (count);
2927: va_start (list_incrementor);
2928: name = va_arg (list_incrementor, char *);
2929: mode = va_arg (list_incrementor, int);
2930: if (count > 2)
2931: rfd = va_arg (list_incrementor, int);
2932: va_end (list_incrementor);
2933: if (count > 2)
2934: {
2935: /* Use information from the related file descriptor to set record
2936: format of the newly created file. */
2937: fstat (rfd, &st_buf);
2938: switch (st_buf.st_fab_rfm)
2939: {
2940: case FAB$C_FIX:
2941: strcpy (rfm, "rfm = fix");
2942: sprintf (mrs, "mrs = %d", st_buf.st_fab_mrs);
2943: strcpy (rat, "rat = ");
2944: if (st_buf.st_fab_rat & FAB$M_CR)
2945: strcat (rat, "cr");
2946: else if (st_buf.st_fab_rat & FAB$M_FTN)
2947: strcat (rat, "ftn");
2948: else if (st_buf.st_fab_rat & FAB$M_PRN)
2949: strcat (rat, "prn");
2950: if (st_buf.st_fab_rat & FAB$M_BLK)
2951: if (st_buf.st_fab_rat & (FAB$M_CR|FAB$M_FTN|FAB$M_PRN))
2952: strcat (rat, ", blk");
2953: else
2954: strcat (rat, "blk");
2955: return creat (name, 0, rfm, rat, mrs);
2956:
2957: case FAB$C_VFC:
2958: strcpy (rfm, "rfm = vfc");
2959: sprintf (fsz, "fsz = %d", st_buf.st_fab_fsz);
2960: strcpy (rat, "rat = ");
2961: if (st_buf.st_fab_rat & FAB$M_CR)
2962: strcat (rat, "cr");
2963: else if (st_buf.st_fab_rat & FAB$M_FTN)
2964: strcat (rat, "ftn");
2965: else if (st_buf.st_fab_rat & FAB$M_PRN)
2966: strcat (rat, "prn");
2967: if (st_buf.st_fab_rat & FAB$M_BLK)
2968: if (st_buf.st_fab_rat & (FAB$M_CR|FAB$M_FTN|FAB$M_PRN))
2969: strcat (rat, ", blk");
2970: else
2971: strcat (rat, "blk");
2972: return creat (name, 0, rfm, rat, fsz);
2973:
2974: case FAB$C_STM:
2975: strcpy (rfm, "rfm = stm");
2976: break;
2977:
2978: case FAB$C_STMCR:
2979: strcpy (rfm, "rfm = stmcr");
2980: break;
2981:
2982: case FAB$C_STMLF:
2983: strcpy (rfm, "rfm = stmlf");
2984: break;
2985:
2986: case FAB$C_UDF:
2987: strcpy (rfm, "rfm = udf");
2988: break;
2989:
2990: case FAB$C_VAR:
2991: strcpy (rfm, "rfm = var");
2992: break;
2993: }
2994: strcpy (rat, "rat = ");
2995: if (st_buf.st_fab_rat & FAB$M_CR)
2996: strcat (rat, "cr");
2997: else if (st_buf.st_fab_rat & FAB$M_FTN)
2998: strcat (rat, "ftn");
2999: else if (st_buf.st_fab_rat & FAB$M_PRN)
3000: strcat (rat, "prn");
3001: if (st_buf.st_fab_rat & FAB$M_BLK)
3002: if (st_buf.st_fab_rat & (FAB$M_CR|FAB$M_FTN|FAB$M_PRN))
3003: strcat (rat, ", blk");
3004: else
3005: strcat (rat, "blk");
3006: }
3007: else
3008: {
3009: strcpy (rfm, vms_stmlf_recfm ? "rfm = stmlf" : "rfm=var");
3010: strcpy (rat, "rat=cr");
3011: }
3012: /* Until the VAX C RTL fixes the many bugs with modes, always use
3013: mode 0 to get the user's default protection. */
3014: fd = creat (name, 0, rfm, rat);
3015: if (fd < 0 && errno == EEXIST)
3016: {
3017: if (unlink (name) < 0)
3018: report_file_error ("delete", build_string (name));
3019: fd = creat (name, 0, rfm, rat);
3020: }
3021: return fd;
3022: }
3023: #endif /* creat */
3024:
3025: /* fwrite to stdout is S L O W. Speed it up by using fputc...*/
3026: sys_fwrite (ptr, size, num, fp)
3027: register char * ptr;
3028: FILE * fp;
3029: {
3030: register int tot = num * size;
3031:
3032: while (tot--)
3033: fputc (*ptr++, fp);
3034: }
3035:
3036: /*
3037: * The VMS C library routine creat() actually creates a new version of an
3038: * existing file rather than truncating the old version. There are times
3039: * when this is not the desired behavior, for instance, when writing an
3040: * auto save file (you only want one version), or when you don't have
3041: * write permission in the directory containing the file (but the file
3042: * itself is writable). Hence this routine, which is equivalent to
3043: * "close (creat (fn, 0));" on Unix if fn already exists.
3044: */
3045: int
3046: vms_truncate (fn)
3047: char *fn;
3048: {
3049: struct FAB xfab = cc$rms_fab;
3050: struct RAB xrab = cc$rms_rab;
3051: int status;
3052:
3053: xfab.fab$l_fop = FAB$M_TEF; /* free allocated but unused blocks on close */
3054: xfab.fab$b_fac = FAB$M_TRN | FAB$M_GET; /* allow truncate and get access */
3055: xfab.fab$b_shr = FAB$M_NIL; /* allow no sharing - file must be locked */
3056: xfab.fab$l_fna = fn;
3057: xfab.fab$b_fns = strlen (fn);
3058: xfab.fab$l_dna = ";0"; /* default to latest version of the file */
3059: xfab.fab$b_dns = 2;
3060: xrab.rab$l_fab = &xfab;
3061:
3062: /* This gibberish opens the file, positions to the first record, and
3063: deletes all records from there until the end of file. */
3064: if ((sys$open (&xfab) & 01) == 01)
3065: {
3066: if ((sys$connect (&xrab) & 01) == 01 &&
3067: (sys$find (&xrab) & 01) == 01 &&
3068: (sys$truncate (&xrab) & 01) == 01)
3069: status = 0;
3070: else
3071: status = -1;
3072: }
3073: else
3074: status = -1;
3075: sys$close (&xfab);
3076: return status;
3077: }
3078:
3079: /* Define this symbol to actually read SYSUAF.DAT. This requires either
3080: SYSPRV or a readable SYSUAF.DAT. */
3081:
3082: #ifdef READ_SYSUAF
3083: /*
3084: * getuaf.c
3085: *
3086: * Routine to read the VMS User Authorization File and return
3087: * a specific user's record.
3088: */
3089:
3090: static struct UAF retuaf;
3091:
3092: struct UAF *
3093: get_uaf_name(uname)
3094: char * uname;
3095: {
3096: register status;
3097: struct FAB uaf_fab;
3098: struct RAB uaf_rab;
3099:
3100: uaf_fab = cc$rms_fab;
3101: uaf_rab = cc$rms_rab;
3102: /* initialize fab fields */
3103: uaf_fab.fab$l_fna = "SYS$SYSTEM:SYSUAF.DAT";
3104: uaf_fab.fab$b_fns = 21;
3105: uaf_fab.fab$b_fac = FAB$M_GET;
3106: uaf_fab.fab$b_org = FAB$C_IDX;
3107: uaf_fab.fab$b_shr = FAB$M_GET|FAB$M_PUT|FAB$M_UPD|FAB$M_DEL;
3108: /* initialize rab fields */
3109: uaf_rab.rab$l_fab = &uaf_fab;
3110: /* open the User Authorization File */
3111: status = sys$open(&uaf_fab);
3112: if (!(status&1))
3113: {
3114: errno = EVMSERR;
3115: vaxc$errno = status;
3116: return 0;
3117: }
3118: status = sys$connect(&uaf_rab);
3119: if (!(status&1))
3120: {
3121: errno = EVMSERR;
3122: vaxc$errno = status;
3123: return 0;
3124: }
3125: /* read the requested record - index is in uname */
3126: uaf_rab.rab$l_kbf = uname;
3127: uaf_rab.rab$b_ksz = strlen (uname);
3128: uaf_rab.rab$b_rac = RAB$C_KEY;
3129: uaf_rab.rab$l_ubf = (char *)&retuaf;
3130: uaf_rab.rab$w_usz = sizeof retuaf;
3131: status = sys$get(&uaf_rab);
3132: if (!(status&1))
3133: {
3134: errno = EVMSERR;
3135: vaxc$errno = status;
3136: return 0;
3137: }
3138: /* close the User Authorization File */
3139: status = sys$disconnect(&uaf_rab);
3140: if (!(status&1))
3141: {
3142: errno = EVMSERR;
3143: vaxc$errno = status;
3144: return 0;
3145: }
3146: status = sys$close(&uaf_fab);
3147: if (!(status&1))
3148: {
3149: errno = EVMSERR;
3150: vaxc$errno = status;
3151: return 0;
3152: }
3153: return &retuaf;
3154: }
3155:
3156: struct UAF *
3157: get_uaf_uic(uic)
3158: unsigned long uic;
3159: {
3160: register status;
3161: struct FAB uaf_fab;
3162: struct RAB uaf_rab;
3163:
3164: uaf_fab = cc$rms_fab;
3165: uaf_rab = cc$rms_rab;
3166: /* initialize fab fields */
3167: uaf_fab.fab$l_fna = "SYS$SYSTEM:SYSUAF.DAT";
3168: uaf_fab.fab$b_fns = 21;
3169: uaf_fab.fab$b_fac = FAB$M_GET;
3170: uaf_fab.fab$b_org = FAB$C_IDX;
3171: uaf_fab.fab$b_shr = FAB$M_GET|FAB$M_PUT|FAB$M_UPD|FAB$M_DEL;
3172: /* initialize rab fields */
3173: uaf_rab.rab$l_fab = &uaf_fab;
3174: /* open the User Authorization File */
3175: status = sys$open(&uaf_fab);
3176: if (!(status&1))
3177: {
3178: errno = EVMSERR;
3179: vaxc$errno = status;
3180: return 0;
3181: }
3182: status = sys$connect(&uaf_rab);
3183: if (!(status&1))
3184: {
3185: errno = EVMSERR;
3186: vaxc$errno = status;
3187: return 0;
3188: }
3189: /* read the requested record - index is in uic */
3190: uaf_rab.rab$b_krf = 1; /* 1st alternate key */
3191: uaf_rab.rab$l_kbf = (char *) &uic;
3192: uaf_rab.rab$b_ksz = sizeof uic;
3193: uaf_rab.rab$b_rac = RAB$C_KEY;
3194: uaf_rab.rab$l_ubf = (char *)&retuaf;
3195: uaf_rab.rab$w_usz = sizeof retuaf;
3196: status = sys$get(&uaf_rab);
3197: if (!(status&1))
3198: {
3199: errno = EVMSERR;
3200: vaxc$errno = status;
3201: return 0;
3202: }
3203: /* close the User Authorization File */
3204: status = sys$disconnect(&uaf_rab);
3205: if (!(status&1))
3206: {
3207: errno = EVMSERR;
3208: vaxc$errno = status;
3209: return 0;
3210: }
3211: status = sys$close(&uaf_fab);
3212: if (!(status&1))
3213: {
3214: errno = EVMSERR;
3215: vaxc$errno = status;
3216: return 0;
3217: }
3218: return &retuaf;
3219: }
3220:
3221: static struct passwd retpw;
3222:
3223: struct passwd *
3224: cnv_uaf_pw (up)
3225: struct UAF * up;
3226: {
3227: char * ptr;
3228:
3229: /* copy these out first because if the username is 32 chars, the next
3230: section will overwrite the first byte of the UIC */
3231: retpw.pw_uid = up->uaf$w_mem;
3232: retpw.pw_gid = up->uaf$w_grp;
3233:
3234: /* I suppose this is not the best sytle, to possibly overwrite one
3235: byte beyond the end of the field, but what the heck... */
3236: ptr = &up->uaf$t_username[UAF$S_USERNAME];
3237: while (ptr[-1] == ' ')
3238: ptr--;
3239: *ptr = '\0';
3240: strcpy (retpw.pw_name, up->uaf$t_username);
3241:
3242: /* the rest of these are counted ascii strings */
3243: strncpy (retpw.pw_gecos, &up->uaf$t_owner[1], up->uaf$t_owner[0]);
3244: retpw.pw_gecos[up->uaf$t_owner[0]] = '\0';
3245: strncpy (retpw.pw_dir, &up->uaf$t_defdev[1], up->uaf$t_defdev[0]);
3246: retpw.pw_dir[up->uaf$t_defdev[0]] = '\0';
3247: strncat (retpw.pw_dir, &up->uaf$t_defdir[1], up->uaf$t_defdir[0]);
3248: retpw.pw_dir[up->uaf$t_defdev[0] + up->uaf$t_defdir[0]] = '\0';
3249: strncpy (retpw.pw_shell, &up->uaf$t_defcli[1], up->uaf$t_defcli[0]);
3250: retpw.pw_shell[up->uaf$t_defcli[0]] = '\0';
3251:
3252: return &retpw;
3253: }
3254: #else /* not READ_SYSUAF */
3255: static struct passwd retpw;
3256: #endif /* not READ_SYSUAF */
3257:
3258: struct passwd *
3259: getpwnam (name)
3260: char * name;
3261: {
3262: #ifdef READ_SYSUAF
3263: struct UAF *up;
3264: #else
3265: char * user;
3266: char * dir;
3267: char * full;
3268: #endif /* READ_SYSUAF */
3269: char *ptr = name;
3270:
3271: while (*ptr)
3272: {
3273: if ('a' <= *ptr && *ptr <= 'z')
3274: *ptr -= 040;
3275: ptr++;
3276: }
3277: #ifdef READ_SYSUAF
3278: if (!(up = get_uaf_name (name)))
3279: return 0;
3280: return cnv_uaf_pw (up);
3281: #else
3282: if (strcmp (name, getenv ("USER")) == 0)
3283: {
3284: retpw.pw_uid = getuid ();
3285: retpw.pw_gid = getgid ();
3286: strcpy (retpw.pw_name, name);
3287: if (full = egetenv ("FULLNAME"))
3288: strcpy (retpw.pw_gecos, full);
3289: else
3290: *retpw.pw_gecos = '\0';
3291: strcpy (retpw.pw_dir, egetenv ("HOME"));
3292: *retpw.pw_shell = '\0';
3293: return &retpw;
3294: }
3295: else
3296: return 0;
3297: #endif /* not READ_SYSUAF */
3298: }
3299:
3300: struct passwd *
3301: getpwuid (uid)
3302: unsigned long uid;
3303: {
3304: #ifdef READ_SYSUAF
3305: struct UAF * up;
3306:
3307: if (!(up = get_uaf_uic (uid)))
3308: return 0;
3309: return cnv_uaf_pw (up);
3310: #else
3311: if (uid == sys_getuid ())
3312: return getpwnam (egetenv ("USER"));
3313: else
3314: return 0;
3315: #endif /* not READ_SYSUAF */
3316: }
3317:
3318: /* return total address space available to the current process. This is
3319: the sum of the current p0 size, p1 size and free page table entries
3320: available. */
3321: vlimit ()
3322: {
3323: int item_code;
3324: unsigned long free_pages;
3325: unsigned long frep0va;
3326: unsigned long frep1va;
3327: register status;
3328:
3329: item_code = JPI$_FREPTECNT;
3330: if (((status = LIB$GETJPI (&item_code, 0, 0, &free_pages)) & 1) == 0)
3331: {
3332: errno = EVMSERR;
3333: vaxc$errno = status;
3334: return -1;
3335: }
3336: free_pages *= 512;
3337:
3338: item_code = JPI$_FREP0VA;
3339: if (((status = LIB$GETJPI (&item_code, 0, 0, &frep0va)) & 1) == 0)
3340: {
3341: errno = EVMSERR;
3342: vaxc$errno = status;
3343: return -1;
3344: }
3345: item_code = JPI$_FREP1VA;
3346: if (((status = LIB$GETJPI (&item_code, 0, 0, &frep1va)) & 1) == 0)
3347: {
3348: errno = EVMSERR;
3349: vaxc$errno = status;
3350: return -1;
3351: }
3352:
3353: return free_pages + frep0va + (0x7fffffff - frep1va);
3354: }
3355:
3356: define_logical_name (varname, string)
3357: char *varname;
3358: char *string;
3359: {
3360: struct dsc$descriptor_s strdsc =
3361: {strlen (string), DSC$K_DTYPE_T, DSC$K_CLASS_S, string};
3362: struct dsc$descriptor_s envdsc =
3363: {strlen (varname), DSC$K_DTYPE_T, DSC$K_CLASS_S, varname};
3364: struct dsc$descriptor_s lnmdsc =
3365: {7, DSC$K_DTYPE_T, DSC$K_CLASS_S, "LNM$JOB"};
3366:
3367: return LIB$SET_LOGICAL (&envdsc, &strdsc, &lnmdsc, 0, 0);
3368: }
3369:
3370: delete_logical_name (varname)
3371: char *varname;
3372: {
3373: struct dsc$descriptor_s envdsc =
3374: {strlen (varname), DSC$K_DTYPE_T, DSC$K_CLASS_S, varname};
3375: struct dsc$descriptor_s lnmdsc =
3376: {7, DSC$K_DTYPE_T, DSC$K_CLASS_S, "LNM$JOB"};
3377:
3378: return LIB$DELETE_LOGICAL (&envdsc, &lnmdsc);
3379: }
3380:
3381: ulimit()
3382: {}
3383:
3384: setpriority()
3385: {}
3386:
3387: setpgrp()
3388: {}
3389:
3390: execvp()
3391: {
3392: error ("execvp system call not implemented");
3393: }
3394:
3395: int
3396: rename (from, to)
3397: char *from, *to;
3398: {
3399: int status;
3400: struct FAB from_fab = cc$rms_fab, to_fab = cc$rms_fab;
3401: struct NAM from_nam = cc$rms_nam, to_nam = cc$rms_nam;
3402: char from_esn[NAM$C_MAXRSS];
3403: char to_esn[NAM$C_MAXRSS];
3404:
3405: from_fab.fab$l_fna = from;
3406: from_fab.fab$b_fns = strlen (from);
3407: from_fab.fab$l_nam = &from_nam;
3408: from_fab.fab$l_fop = FAB$M_NAM;
3409:
3410: from_nam.nam$l_esa = from_esn;
3411: from_nam.nam$b_ess = sizeof from_esn;
3412:
3413: to_fab.fab$l_fna = to;
3414: to_fab.fab$b_fns = strlen (to);
3415: to_fab.fab$l_nam = &to_nam;
3416: to_fab.fab$l_fop = FAB$M_NAM;
3417:
3418: to_nam.nam$l_esa = to_esn;
3419: to_nam.nam$b_ess = sizeof to_esn;
3420:
3421: status = SYS$RENAME (&from_fab, 0, 0, &to_fab);
3422:
3423: if (status & 1)
3424: return 0;
3425: else
3426: {
3427: if (status == RMS$_DEV)
3428: errno = EXDEV;
3429: else
3430: errno = EVMSERR;
3431: vaxc$errno = status;
3432: return -1;
3433: }
3434: }
3435:
3436: link (file, new)
3437: char * file, * new;
3438: {
3439: register status;
3440: struct FAB fab;
3441: struct NAM nam;
3442: unsigned short fid[3];
3443: char esa[NAM$C_MAXRSS];
3444:
3445: fab = cc$rms_fab;
3446: fab.fab$l_fop = FAB$M_OFP;
3447: fab.fab$l_fna = file;
3448: fab.fab$b_fns = strlen (file);
3449: fab.fab$l_nam = &nam;
3450:
3451: nam = cc$rms_nam;
3452: nam.nam$l_esa = esa;
3453: nam.nam$b_ess = NAM$C_MAXRSS;
3454:
3455: status = SYS$PARSE (&fab);
3456: if ((status & 1) == 0)
3457: {
3458: errno = EVMSERR;
3459: vaxc$errno = status;
3460: return -1;
3461: }
3462: status = SYS$SEARCH (&fab);
3463: if ((status & 1) == 0)
3464: {
3465: errno = EVMSERR;
3466: vaxc$errno = status;
3467: return -1;
3468: }
3469:
3470: fid[0] = nam.nam$w_fid[0];
3471: fid[1] = nam.nam$w_fid[1];
3472: fid[2] = nam.nam$w_fid[2];
3473:
3474: fab.fab$l_fna = new;
3475: fab.fab$b_fns = strlen (new);
3476:
3477: status = SYS$PARSE (&fab);
3478: if ((status & 1) == 0)
3479: {
3480: errno = EVMSERR;
3481: vaxc$errno = status;
3482: return -1;
3483: }
3484:
3485: nam.nam$w_fid[0] = fid[0];
3486: nam.nam$w_fid[1] = fid[1];
3487: nam.nam$w_fid[2] = fid[2];
3488:
3489: nam.nam$l_esa = nam.nam$l_name;
3490: nam.nam$b_esl = nam.nam$b_name + nam.nam$b_type + nam.nam$b_ver;
3491:
3492: status = SYS$ENTER (&fab);
3493: if ((status & 1) == 0)
3494: {
3495: errno = EVMSERR;
3496: vaxc$errno = status;
3497: return -1;
3498: }
3499:
3500: return 0;
3501: }
3502:
3503: croak (badfunc)
3504: char *badfunc;
3505: {
3506: printf ("%s not yet implemented\r\n", badfunc);
3507: reset_sys_modes ();
3508: exit (1);
3509: }
3510:
3511: long
3512: random ()
3513: {
3514: /* Arrange to return a range centered on zero. */
3515: return rand () - (1 << 30);
3516: }
3517:
3518: srandom (seed)
3519: {
3520: srand (seed);
3521: }
3522: #endif /* VMS */
3523:
3524: #ifdef AIX
3525:
3526: /* Get files for keyboard remapping */
3527: #define HFNKEYS 2
3528: #include <sys/hft.h>
3529: #include <sys/devinfo.h>
3530:
3531: /* Called from init_sys_modes. */
3532: hft_init ()
3533: {
3534: /* On AIX the default hft keyboard mapping uses backspace rather than delete
3535: as the rubout key's ASCII code. Here this is changed. The bug is that
3536: there's no way to determine the old mapping, so in reset_sys_modes
3537: we need to assume that the normal map had been present. Of course, this
3538: code also doesn't help if on a terminal emulator which doesn't understand
3539: HFT VTD's. */
3540: {
3541: struct hfbuf buf;
3542: struct hfkeymap keymap;
3543:
3544: buf.hf_bufp = (char *)&keymap;
3545: buf.hf_buflen = sizeof (keymap);
3546: keymap.hf_nkeys = 2;
3547: keymap.hfkey[0].hf_kpos = 15;
3548: keymap.hfkey[0].hf_kstate = HFMAPCHAR | HFSHFNONE;
3549: keymap.hfkey[0].hf_page = '<';
3550: keymap.hfkey[0].hf_char = 127;
3551: keymap.hfkey[1].hf_kpos = 15;
3552: keymap.hfkey[1].hf_kstate = HFMAPCHAR | HFSHFSHFT;
3553: keymap.hfkey[1].hf_page = '<';
3554: keymap.hfkey[1].hf_char = 127;
3555: hftctl (0, HFSKBD, &buf);
3556: }
3557: /* The HFT system on AIX doesn't optimize for scrolling, so it's really ugly
3558: at times. Here we determine if we are on an HFT by trying to get an
3559: HFT error code. If this call works, we must be on an HFT. */
3560: if (ioctl (0, HFQEIO, 0) != -1)
3561: line_ins_del_ok = char_ins_del_ok = 0;
3562: }
3563:
3564: /* Reset the rubout key to backspace. */
3565:
3566: hft_reset ()
3567: {
3568: struct hfbuf buf;
3569: struct hfkeymap keymap;
3570:
3571: buf.hf_bufp = (char *)&keymap;
3572: buf.hf_buflen = sizeof(keymap);
3573: keymap.hf_nkeys = 2;
3574: keymap.hfkey[0].hf_kpos = 15;
3575: keymap.hfkey[0].hf_kstate = HFMAPCHAR | HFSHFNONE;
3576: keymap.hfkey[0].hf_page = '<';
3577: keymap.hfkey[0].hf_char = 8;
3578: keymap.hfkey[1].hf_kpos = 15;
3579: keymap.hfkey[1].hf_kstate = HFMAPCHAR | HFSHFSHFT;
3580: keymap.hfkey[1].hf_page = '<';
3581: keymap.hfkey[1].hf_char = 8;
3582: hftctl (0, HFSKBD, &buf);
3583: }
3584:
3585: #endif /* AIX */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.