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