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