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