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