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