]> code.delx.au - gnu-emacs/blob - src/sysdep.c
(C_DEBUG_SWITCH): Define as empty.
[gnu-emacs] / src / sysdep.c
1 /* Interfaces to system-dependent kernel and library entries.
2 Copyright (C) 1985, 86, 87, 88, 93, 94 Free Software Foundation, Inc.
3
4 This file is part of GNU Emacs.
5
6 GNU Emacs is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
9 any later version.
10
11 GNU Emacs is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with GNU Emacs; see the file COPYING. If not, write to
18 the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
19
20
21 #include <signal.h>
22 #include <setjmp.h>
23
24 #include <config.h>
25 #include "lisp.h"
26 #include "blockinput.h"
27 #undef NULL
28
29 #define min(x,y) ((x) > (y) ? (y) : (x))
30
31 /* In this file, open, read and write refer to the system calls,
32 not our sugared interfaces sys_open, sys_read and sys_write.
33 Contrariwise, for systems where we use the system calls directly,
34 define sys_read, etc. here as aliases for them. */
35 #ifndef read
36 #define sys_read read
37 #define sys_write write
38 #endif /* `read' is not a macro */
39
40 #undef read
41 #undef write
42
43 #ifndef close
44 #define sys_close close
45 #else
46 #undef close
47 #endif
48
49 #ifndef open
50 #define sys_open open
51 #else /* `open' is a macro */
52 #undef open
53 #endif /* `open' is a macro */
54
55 /* Does anyone other than VMS need this? */
56 #ifndef fwrite
57 #define sys_fwrite fwrite
58 #else
59 #undef fwrite
60 #endif
61
62 #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 /* init_system_name sets up the string for the Lisp function
1962 system-name to return. */
1963
1964 #ifdef BSD4_1
1965 #include <whoami.h>
1966 #endif
1967
1968 extern Lisp_Object Vsystem_name;
1969
1970 #ifndef BSD4_1
1971 #ifndef VMS
1972 #ifdef HAVE_SOCKETS
1973 #include <sys/socket.h>
1974 #include <netdb.h>
1975 #endif /* HAVE_SOCKETS */
1976 #endif /* not VMS */
1977 #endif /* not BSD4_1 */
1978
1979 void
1980 init_system_name ()
1981 {
1982 #ifdef BSD4_1
1983 Vsystem_name = build_string (sysname);
1984 #else
1985 #ifdef VMS
1986 char *sp, *end;
1987 if ((sp = egetenv ("SYS$NODE")) == 0)
1988 Vsystem_name = build_string ("vax-vms");
1989 else if ((end = index (sp, ':')) == 0)
1990 Vsystem_name = build_string (sp);
1991 else
1992 Vsystem_name = make_string (sp, end - sp);
1993 #else
1994 #ifndef HAVE_GETHOSTNAME
1995 struct utsname uts;
1996 uname (&uts);
1997 Vsystem_name = build_string (uts.nodename);
1998 #else /* HAVE_GETHOSTNAME */
1999 int hostname_size = 256;
2000 char *hostname = (char *) alloca (hostname_size);
2001
2002 /* Try to get the host name; if the buffer is too short, try
2003 again. Apparently, the only indication gethostname gives of
2004 whether the buffer was large enough is the presence or absence
2005 of a '\0' in the string. Eech. */
2006 for (;;)
2007 {
2008 gethostname (hostname, hostname_size - 1);
2009 hostname[hostname_size - 1] = '\0';
2010
2011 /* Was the buffer large enough for the '\0'? */
2012 if (strlen (hostname) < hostname_size - 1)
2013 break;
2014
2015 hostname_size <<= 1;
2016 hostname = (char *) alloca (hostname_size);
2017 }
2018 #ifdef HAVE_SOCKETS
2019 /* Turn the hostname into the official, fully-qualified hostname.
2020 Don't do this if we're going to dump; this can confuse system
2021 libraries on some machines and make the dumped emacs core dump. */
2022 #ifndef CANNOT_DUMP
2023 if (initialized)
2024 #endif /* not CANNOT_DUMP */
2025 {
2026 struct hostent *hp = gethostbyname (hostname);
2027 if (hp)
2028 {
2029 char *fqdn = hp->h_name;
2030 char *p;
2031
2032 if (!index (fqdn, '.'))
2033 {
2034 /* We still don't have a fully qualified domain name.
2035 Try to find one in the list of alternate names */
2036 char **alias = hp->h_aliases;
2037 while (*alias && !index (*alias, '.'))
2038 alias++;
2039 if (*alias)
2040 fqdn = *alias;
2041 }
2042 hostname = fqdn;
2043 #if 0
2044 /* Convert the host name to lower case. */
2045 /* Using ctype.h here would introduce a possible locale
2046 dependence that is probably wrong for hostnames. */
2047 p = hostname;
2048 while (*p)
2049 {
2050 if (*p >= 'A' && *p <= 'Z')
2051 *p += 'a' - 'A';
2052 p++;
2053 }
2054 #endif
2055 }
2056 }
2057 #endif /* HAVE_SOCKETS */
2058 Vsystem_name = build_string (hostname);
2059 #endif /* HAVE_GETHOSTNAME */
2060 #endif /* VMS */
2061 #endif /* BSD4_1 */
2062 {
2063 unsigned char *p;
2064 for (p = XSTRING (Vsystem_name)->data; *p; p++)
2065 if (*p == ' ' || *p == '\t')
2066 *p = '-';
2067 }
2068 }
2069 \f
2070 #ifndef VMS
2071 #ifndef HAVE_SELECT
2072
2073 #ifdef HAVE_X_WINDOWS
2074 /* Cause explanatory error message at compile time,
2075 since the select emulation is not good enough for X. */
2076 int *x = &x_windows_lose_if_no_select_system_call;
2077 #endif
2078
2079 /* Emulate as much as select as is possible under 4.1 and needed by Gnu Emacs
2080 * Only checks read descriptors.
2081 */
2082 /* How long to wait between checking fds in select */
2083 #define SELECT_PAUSE 1
2084 int select_alarmed;
2085
2086 /* For longjmp'ing back to read_input_waiting. */
2087
2088 jmp_buf read_alarm_throw;
2089
2090 /* Nonzero if the alarm signal should throw back to read_input_waiting.
2091 The read_socket_hook function sets this to 1 while it is waiting. */
2092
2093 int read_alarm_should_throw;
2094
2095 SIGTYPE
2096 select_alarm ()
2097 {
2098 select_alarmed = 1;
2099 #ifdef BSD4_1
2100 sigrelse (SIGALRM);
2101 #else /* not BSD4_1 */
2102 signal (SIGALRM, SIG_IGN);
2103 #endif /* not BSD4_1 */
2104 if (read_alarm_should_throw)
2105 longjmp (read_alarm_throw, 1);
2106 }
2107
2108 /* Only rfds are checked. */
2109 int
2110 select (nfds, rfds, wfds, efds, timeout)
2111 int nfds;
2112 int *rfds, *wfds, *efds, *timeout;
2113 {
2114 int ravail = 0, orfds = 0, old_alarm;
2115 int timeoutval = timeout ? *timeout : 100000;
2116 int *local_timeout = &timeoutval;
2117 extern int proc_buffered_char[];
2118 #ifndef subprocesses
2119 int process_tick = 0, update_tick = 0;
2120 #else
2121 extern int process_tick, update_tick;
2122 #endif
2123 SIGTYPE (*old_trap) ();
2124 unsigned char buf;
2125
2126 if (rfds)
2127 {
2128 orfds = *rfds;
2129 *rfds = 0;
2130 }
2131 if (wfds)
2132 *wfds = 0;
2133 if (efds)
2134 *efds = 0;
2135
2136 /* If we are looking only for the terminal, with no timeout,
2137 just read it and wait -- that's more efficient. */
2138 if (orfds == 1 && *local_timeout == 100000 && process_tick == update_tick)
2139 {
2140 if (! detect_input_pending ())
2141 read_input_waiting ();
2142 *rfds = 1;
2143 return 1;
2144 }
2145
2146 /* Once a second, till the timer expires, check all the flagged read
2147 * descriptors to see if any input is available. If there is some then
2148 * set the corresponding bit in the return copy of rfds.
2149 */
2150 while (1)
2151 {
2152 register int to_check, bit, fd;
2153
2154 if (rfds)
2155 {
2156 for (to_check = nfds, bit = 1, fd = 0; --to_check >= 0; bit <<= 1, fd++)
2157 {
2158 if (orfds & bit)
2159 {
2160 int avail = 0, status = 0;
2161
2162 if (bit == 1)
2163 avail = detect_input_pending (); /* Special keyboard handler */
2164 else
2165 {
2166 #ifdef FIONREAD
2167 status = ioctl (fd, FIONREAD, &avail);
2168 #else /* no FIONREAD */
2169 #ifdef MSDOS
2170 abort (); /* I don't think we need it. */
2171 #else /* not MSDOS */
2172 /* Hoping it will return -1 if nothing available
2173 or 0 if all 0 chars requested are read. */
2174 if (proc_buffered_char[fd] >= 0)
2175 avail = 1;
2176 else
2177 {
2178 avail = read (fd, &buf, 1);
2179 if (avail > 0)
2180 proc_buffered_char[fd] = buf;
2181 }
2182 #endif /* not MSDOS */
2183 #endif /* no FIONREAD */
2184 }
2185 if (status >= 0 && avail > 0)
2186 {
2187 (*rfds) |= bit;
2188 ravail++;
2189 }
2190 }
2191 }
2192 }
2193 if (*local_timeout == 0 || ravail != 0 || process_tick != update_tick)
2194 break;
2195 old_alarm = alarm (0);
2196 old_trap = signal (SIGALRM, select_alarm);
2197 select_alarmed = 0;
2198 alarm (SELECT_PAUSE);
2199 /* Wait for a SIGALRM (or maybe a SIGTINT) */
2200 while (select_alarmed == 0 && *local_timeout != 0
2201 && process_tick == update_tick)
2202 {
2203 #ifdef MSDOS
2204 sleep_or_kbd_hit (SELECT_PAUSE, (orfds & 1) != 0);
2205 select_alarm ();
2206 #else /* not MSDOS */
2207 /* If we are interested in terminal input,
2208 wait by reading the terminal.
2209 That makes instant wakeup for terminal input at least. */
2210 if (orfds & 1)
2211 {
2212 read_input_waiting ();
2213 if (detect_input_pending ())
2214 select_alarmed = 1;
2215 }
2216 else
2217 pause ();
2218 #endif /* not MSDOS */
2219 }
2220 (*local_timeout) -= SELECT_PAUSE;
2221 /* Reset the old alarm if there was one */
2222 alarm (0);
2223 signal (SIGALRM, old_trap);
2224 if (old_alarm != 0)
2225 {
2226 /* Reset or forge an interrupt for the original handler. */
2227 old_alarm -= SELECT_PAUSE;
2228 if (old_alarm <= 0)
2229 kill (getpid (), SIGALRM); /* Fake an alarm with the orig' handler */
2230 else
2231 alarm (old_alarm);
2232 }
2233 if (*local_timeout == 0) /* Stop on timer being cleared */
2234 break;
2235 }
2236 return ravail;
2237 }
2238
2239 /* Read keyboard input into the standard buffer,
2240 waiting for at least one character. */
2241
2242 /* Make all keyboard buffers much bigger when using X windows. */
2243 #ifdef HAVE_X_WINDOWS
2244 #define BUFFER_SIZE_FACTOR 16
2245 #else
2246 #define BUFFER_SIZE_FACTOR 1
2247 #endif
2248
2249 read_input_waiting ()
2250 {
2251 struct input_event e;
2252 int nread, i;
2253 extern int quit_char;
2254
2255 if (read_socket_hook)
2256 {
2257 struct input_event buf[256];
2258
2259 read_alarm_should_throw = 0;
2260 if (! setjmp (read_alarm_throw))
2261 nread = (*read_socket_hook) (0, buf, 256, 1, 0);
2262 else
2263 nread = -1;
2264
2265 /* Scan the chars for C-g and store them in kbd_buffer. */
2266 for (i = 0; i < nread; i++)
2267 {
2268 kbd_buffer_store_event (&buf[i]);
2269 /* Don't look at input that follows a C-g too closely.
2270 This reduces lossage due to autorepeat on C-g. */
2271 if (buf[i].kind == ascii_keystroke
2272 && XINT(buf[i].code) == quit_char)
2273 break;
2274 }
2275 }
2276 else
2277 {
2278 char buf[3];
2279 nread = read (fileno (stdin), buf, 1);
2280
2281 /* Scan the chars for C-g and store them in kbd_buffer. */
2282 e.kind = ascii_keystroke;
2283 e.frame_or_window = selected_frame;
2284 e.modifiers = 0;
2285 for (i = 0; i < nread; i++)
2286 {
2287 /* Convert chars > 0177 to meta events if desired.
2288 We do this under the same conditions that read_avail_input does. */
2289 if (read_socket_hook == 0)
2290 {
2291 /* If the user says she has a meta key, then believe her. */
2292 if (meta_key == 1 && (buf[i] & 0x80))
2293 e.modifiers = meta_modifier;
2294 if (meta_key != 2)
2295 buf[i] &= ~0x80;
2296 }
2297
2298 XSET (e.code, Lisp_Int, buf[i]);
2299 kbd_buffer_store_event (&e);
2300 /* Don't look at input that follows a C-g too closely.
2301 This reduces lossage due to autorepeat on C-g. */
2302 if (buf[i] == quit_char)
2303 break;
2304 }
2305 }
2306 }
2307
2308 #endif /* not HAVE_SELECT */
2309 #endif /* not VMS */
2310 \f
2311 #ifdef BSD4_1
2312 /*
2313 * Partially emulate 4.2 open call.
2314 * open is defined as this in 4.1.
2315 *
2316 * - added by Michael Bloom @ Citicorp/TTI
2317 *
2318 */
2319
2320 int
2321 sys_open (path, oflag, mode)
2322 char *path;
2323 int oflag, mode;
2324 {
2325 if (oflag & O_CREAT)
2326 return creat (path, mode);
2327 else
2328 return open (path, oflag);
2329 }
2330
2331 init_sigio ()
2332 {
2333 if (noninteractive)
2334 return;
2335 lmode = LINTRUP | lmode;
2336 ioctl (0, TIOCLSET, &lmode);
2337 }
2338
2339 reset_sigio ()
2340 {
2341 if (noninteractive)
2342 return;
2343 lmode = ~LINTRUP & lmode;
2344 ioctl (0, TIOCLSET, &lmode);
2345 }
2346
2347 request_sigio ()
2348 {
2349 sigrelse (SIGTINT);
2350
2351 interrupts_deferred = 0;
2352 }
2353
2354 unrequest_sigio ()
2355 {
2356 sighold (SIGTINT);
2357
2358 interrupts_deferred = 1;
2359 }
2360
2361 /* still inside #ifdef BSD4_1 */
2362 #ifdef subprocesses
2363
2364 int sigheld; /* Mask of held signals */
2365
2366 sigholdx (signum)
2367 int signum;
2368 {
2369 sigheld |= sigbit (signum);
2370 sighold (signum);
2371 }
2372
2373 sigisheld (signum)
2374 int signum;
2375 {
2376 sigheld |= sigbit (signum);
2377 }
2378
2379 sigunhold (signum)
2380 int signum;
2381 {
2382 sigheld &= ~sigbit (signum);
2383 sigrelse (signum);
2384 }
2385
2386 sigfree () /* Free all held signals */
2387 {
2388 int i;
2389 for (i = 0; i < NSIG; i++)
2390 if (sigheld & sigbit (i))
2391 sigrelse (i);
2392 sigheld = 0;
2393 }
2394
2395 sigbit (i)
2396 {
2397 return 1 << (i - 1);
2398 }
2399 #endif /* subprocesses */
2400 #endif /* BSD4_1 */
2401 \f
2402 /* POSIX signals support - DJB */
2403 /* Anyone with POSIX signals should have ANSI C declarations */
2404
2405 #ifdef POSIX_SIGNALS
2406
2407 sigset_t old_mask, empty_mask, full_mask, temp_mask;
2408 static struct sigaction new_action, old_action;
2409
2410 init_signals ()
2411 {
2412 sigemptyset (&empty_mask);
2413 sigfillset (&full_mask);
2414 }
2415
2416 signal_handler_t
2417 sys_signal (int signal_number, signal_handler_t action)
2418 {
2419 #ifdef DGUX
2420 /* This gets us restartable system calls for efficiency.
2421 The "else" code will works as well. */
2422 return (berk_signal (signal_number, action));
2423 #else
2424 sigemptyset (&new_action.sa_mask);
2425 new_action.sa_handler = action;
2426 #ifdef SA_RESTART
2427 /* Emacs mostly works better with restartable system services. If this
2428 * flag exists, we probably want to turn it on here.
2429 */
2430 new_action.sa_flags = SA_RESTART;
2431 #else
2432 new_action.sa_flags = 0;
2433 #endif
2434 sigaction (signal_number, &new_action, &old_action);
2435 return (old_action.sa_handler);
2436 #endif /* DGUX */
2437 }
2438
2439 #ifndef __GNUC__
2440 /* If we're compiling with GCC, we don't need this function, since it
2441 can be written as a macro. */
2442 sigset_t
2443 sys_sigmask (int sig)
2444 {
2445 sigset_t mask;
2446 sigemptyset (&mask);
2447 sigaddset (&mask, sig);
2448 return mask;
2449 }
2450 #endif
2451
2452 int
2453 sys_sigpause (sigset_t new_mask)
2454 {
2455 /* pause emulating berk sigpause... */
2456 sigsuspend (&new_mask);
2457 return (EINTR);
2458 }
2459
2460 /* I'd like to have these guys return pointers to the mask storage in here,
2461 but there'd be trouble if the code was saving multiple masks. I'll be
2462 safe and pass the structure. It normally won't be more than 2 bytes
2463 anyhow. - DJB */
2464
2465 sigset_t
2466 sys_sigblock (sigset_t new_mask)
2467 {
2468 sigset_t old_mask;
2469 sigprocmask (SIG_BLOCK, &new_mask, &old_mask);
2470 return (old_mask);
2471 }
2472
2473 sigset_t
2474 sys_sigunblock (sigset_t new_mask)
2475 {
2476 sigset_t old_mask;
2477 sigprocmask (SIG_UNBLOCK, &new_mask, &old_mask);
2478 return (old_mask);
2479 }
2480
2481 sigset_t
2482 sys_sigsetmask (sigset_t new_mask)
2483 {
2484 sigset_t old_mask;
2485 sigprocmask (SIG_SETMASK, &new_mask, &old_mask);
2486 return (old_mask);
2487 }
2488
2489 #endif /* POSIX_SIGNALS */
2490 \f
2491 #ifndef BSTRING
2492
2493 #ifndef bzero
2494
2495 void
2496 bzero (b, length)
2497 register char *b;
2498 register int length;
2499 {
2500 #ifdef VMS
2501 short zero = 0;
2502 long max_str = 65535;
2503
2504 while (length > max_str) {
2505 (void) LIB$MOVC5 (&zero, &zero, &zero, &max_str, b);
2506 length -= max_str;
2507 b += max_str;
2508 }
2509 max_str = length;
2510 (void) LIB$MOVC5 (&zero, &zero, &zero, &max_str, b);
2511 #else
2512 while (length-- > 0)
2513 *b++ = 0;
2514 #endif /* not VMS */
2515 }
2516
2517 #endif /* no bzero */
2518
2519 #ifndef bcopy
2520 /* Saying `void' requires a declaration, above, where bcopy is used
2521 and that declaration causes pain for systems where bcopy is a macro. */
2522 bcopy (b1, b2, length)
2523 register char *b1;
2524 register char *b2;
2525 register int length;
2526 {
2527 #ifdef VMS
2528 long max_str = 65535;
2529
2530 while (length > max_str) {
2531 (void) LIB$MOVC3 (&max_str, b1, b2);
2532 length -= max_str;
2533 b1 += max_str;
2534 b2 += max_str;
2535 }
2536 max_str = length;
2537 (void) LIB$MOVC3 (&length, b1, b2);
2538 #else
2539 while (length-- > 0)
2540 *b2++ = *b1++;
2541 #endif /* not VMS */
2542 }
2543 #endif /* no bcopy */
2544
2545 #ifndef bcmp
2546 int
2547 bcmp (b1, b2, length) /* This could be a macro! */
2548 register char *b1;
2549 register char *b2;
2550 register int length;
2551 {
2552 #ifdef VMS
2553 struct dsc$descriptor_s src1 = {length, DSC$K_DTYPE_T, DSC$K_CLASS_S, b1};
2554 struct dsc$descriptor_s src2 = {length, DSC$K_DTYPE_T, DSC$K_CLASS_S, b2};
2555
2556 return STR$COMPARE (&src1, &src2);
2557 #else
2558 while (length-- > 0)
2559 if (*b1++ != *b2++)
2560 return 1;
2561
2562 return 0;
2563 #endif /* not VMS */
2564 }
2565 #endif /* no bcmp */
2566
2567 #endif /* not BSTRING */
2568 \f
2569 #ifndef HAVE_RANDOM
2570 #ifdef USG
2571 /*
2572 * The BSD random returns numbers in the range of
2573 * 0 to 2e31 - 1. The USG rand returns numbers in the
2574 * range of 0 to 2e15 - 1. This is probably not significant
2575 * in this usage.
2576 */
2577
2578 long
2579 random ()
2580 {
2581 /* Arrange to return a range centered on zero. */
2582 return (rand () << 15) + rand () - (1 << 29);
2583 }
2584
2585 srandom (arg)
2586 int arg;
2587 {
2588 srand (arg);
2589 }
2590
2591 #endif /* USG */
2592
2593 #ifdef BSD4_1
2594 long random ()
2595 {
2596 /* Arrange to return a range centered on zero. */
2597 return (rand () << 15) + rand () - (1 << 29);
2598 }
2599
2600 srandom (arg)
2601 int arg;
2602 {
2603 srand (arg);
2604 }
2605 #endif /* BSD4_1 */
2606 #endif
2607 \f
2608 #ifdef WRONG_NAME_INSQUE
2609
2610 insque (q,p)
2611 caddr_t q,p;
2612 {
2613 _insque (q,p);
2614 }
2615
2616 #endif
2617 \f
2618 #ifdef VMS
2619
2620 #ifdef getenv
2621 /* If any place else asks for the TERM variable,
2622 allow it to be overridden with the EMACS_TERM variable
2623 before attempting to translate the logical name TERM. As a last
2624 resort, ask for VAX C's special idea of the TERM variable. */
2625 #undef getenv
2626 char *
2627 sys_getenv (name)
2628 char *name;
2629 {
2630 register char *val;
2631 static char buf[256];
2632 static struct dsc$descriptor_s equiv
2633 = {sizeof (buf), DSC$K_DTYPE_T, DSC$K_CLASS_S, buf};
2634 static struct dsc$descriptor_s d_name
2635 = {0, DSC$K_DTYPE_T, DSC$K_CLASS_S, 0};
2636 short eqlen;
2637
2638 if (!strcmp (name, "TERM"))
2639 {
2640 val = (char *) getenv ("EMACS_TERM");
2641 if (val)
2642 return val;
2643 }
2644
2645 d_name.dsc$w_length = strlen (name);
2646 d_name.dsc$a_pointer = name;
2647 if (LIB$SYS_TRNLOG (&d_name, &eqlen, &equiv) == 1)
2648 {
2649 char *str = (char *) xmalloc (eqlen + 1);
2650 bcopy (buf, str, eqlen);
2651 str[eqlen] = '\0';
2652 /* This is a storage leak, but a pain to fix. With luck,
2653 no one will ever notice. */
2654 return str;
2655 }
2656 return (char *) getenv (name);
2657 }
2658 #endif /* getenv */
2659
2660 #ifdef abort
2661 /* Since VMS doesn't believe in core dumps, the only way to debug this beast is
2662 to force a call on the debugger from within the image. */
2663 #undef abort
2664 sys_abort ()
2665 {
2666 reset_sys_modes ();
2667 LIB$SIGNAL (SS$_DEBUG);
2668 }
2669 #endif /* abort */
2670 #endif /* VMS */
2671 \f
2672 #ifdef VMS
2673 #ifdef LINK_CRTL_SHARE
2674 #ifdef SHAREABLE_LIB_BUG
2675 /* Variables declared noshare and initialized in sharable libraries
2676 cannot be shared. The VMS linker incorrectly forces you to use a private
2677 version which is uninitialized... If not for this "feature", we
2678 could use the C library definition of sys_nerr and sys_errlist. */
2679 int sys_nerr = 35;
2680 char *sys_errlist[] =
2681 {
2682 "error 0",
2683 "not owner",
2684 "no such file or directory",
2685 "no such process",
2686 "interrupted system call",
2687 "i/o error",
2688 "no such device or address",
2689 "argument list too long",
2690 "exec format error",
2691 "bad file number",
2692 "no child process",
2693 "no more processes",
2694 "not enough memory",
2695 "permission denied",
2696 "bad address",
2697 "block device required",
2698 "mount devices busy",
2699 "file exists",
2700 "cross-device link",
2701 "no such device",
2702 "not a directory",
2703 "is a directory",
2704 "invalid argument",
2705 "file table overflow",
2706 "too many open files",
2707 "not a typewriter",
2708 "text file busy",
2709 "file too big",
2710 "no space left on device",
2711 "illegal seek",
2712 "read-only file system",
2713 "too many links",
2714 "broken pipe",
2715 "math argument",
2716 "result too large",
2717 "I/O stream empty",
2718 "vax/vms specific error code nontranslatable error"
2719 };
2720 #endif /* SHAREABLE_LIB_BUG */
2721 #endif /* LINK_CRTL_SHARE */
2722 #endif /* VMS */
2723
2724 #ifndef HAVE_STRERROR
2725 char *
2726 strerror (errnum)
2727 int errnum;
2728 {
2729 extern char *sys_errlist[];
2730 extern int sys_nerr;
2731
2732 if (errnum >= 0 && errnum < sys_nerr)
2733 return sys_errlist[errnum];
2734 return (char *) "Unknown error";
2735 }
2736
2737 #endif /* ! HAVE_STRERROR */
2738 \f
2739 #ifdef INTERRUPTIBLE_OPEN
2740
2741 int
2742 /* VARARGS 2 */
2743 sys_open (path, oflag, mode)
2744 char *path;
2745 int oflag, mode;
2746 {
2747 register int rtnval;
2748
2749 while ((rtnval = open (path, oflag, mode)) == -1
2750 && (errno == EINTR));
2751 return (rtnval);
2752 }
2753
2754 #endif /* INTERRUPTIBLE_OPEN */
2755
2756 #ifdef INTERRUPTIBLE_CLOSE
2757
2758 sys_close (fd)
2759 int fd;
2760 {
2761 register int rtnval;
2762
2763 while ((rtnval = close (fd)) == -1
2764 && (errno == EINTR));
2765 return rtnval;
2766 }
2767
2768 #endif /* INTERRUPTIBLE_CLOSE */
2769
2770 #ifdef INTERRUPTIBLE_IO
2771
2772 int
2773 sys_read (fildes, buf, nbyte)
2774 int fildes;
2775 char *buf;
2776 unsigned int nbyte;
2777 {
2778 register int rtnval;
2779
2780 while ((rtnval = read (fildes, buf, nbyte)) == -1
2781 && (errno == EINTR));
2782 return (rtnval);
2783 }
2784
2785 int
2786 sys_write (fildes, buf, nbyte)
2787 int fildes;
2788 char *buf;
2789 unsigned int nbyte;
2790 {
2791 register int rtnval, bytes_written;
2792
2793 bytes_written = 0;
2794
2795 while (nbyte > 0)
2796 {
2797 rtnval = write (fildes, buf, nbyte);
2798
2799 if (rtnval == -1)
2800 {
2801 if (errno == EINTR)
2802 continue;
2803 else
2804 return (bytes_written ? bytes_written : -1);
2805 }
2806
2807 buf += rtnval;
2808 nbyte -= rtnval;
2809 bytes_written += rtnval;
2810 }
2811 return (bytes_written);
2812 }
2813
2814 #endif /* INTERRUPTIBLE_IO */
2815 \f
2816 #ifndef HAVE_VFORK
2817
2818 /*
2819 * Substitute fork for vfork on USG flavors.
2820 */
2821
2822 vfork ()
2823 {
2824 return (fork ());
2825 }
2826
2827 #endif /* not HAVE_VFORK */
2828 \f
2829 #ifdef USG
2830 /*
2831 * All of the following are for USG.
2832 *
2833 * On USG systems the system calls are INTERRUPTIBLE by signals
2834 * that the user program has elected to catch. Thus the system call
2835 * must be retried in these cases. To handle this without massive
2836 * changes in the source code, we remap the standard system call names
2837 * to names for our own functions in sysdep.c that do the system call
2838 * with retries. Actually, for portability reasons, it is good
2839 * programming practice, as this example shows, to limit all actual
2840 * system calls to a single occurrence in the source. Sure, this
2841 * adds an extra level of function call overhead but it is almost
2842 * always negligible. Fred Fish, Unisoft Systems Inc.
2843 */
2844
2845 #ifndef HAVE_SYS_SIGLIST
2846 char *sys_siglist[NSIG + 1] =
2847 {
2848 #ifdef AIX
2849 /* AIX has changed the signals a bit */
2850 "bogus signal", /* 0 */
2851 "hangup", /* 1 SIGHUP */
2852 "interrupt", /* 2 SIGINT */
2853 "quit", /* 3 SIGQUIT */
2854 "illegal instruction", /* 4 SIGILL */
2855 "trace trap", /* 5 SIGTRAP */
2856 "IOT instruction", /* 6 SIGIOT */
2857 "crash likely", /* 7 SIGDANGER */
2858 "floating point exception", /* 8 SIGFPE */
2859 "kill", /* 9 SIGKILL */
2860 "bus error", /* 10 SIGBUS */
2861 "segmentation violation", /* 11 SIGSEGV */
2862 "bad argument to system call", /* 12 SIGSYS */
2863 "write on a pipe with no one to read it", /* 13 SIGPIPE */
2864 "alarm clock", /* 14 SIGALRM */
2865 "software termination signum", /* 15 SIGTERM */
2866 "user defined signal 1", /* 16 SIGUSR1 */
2867 "user defined signal 2", /* 17 SIGUSR2 */
2868 "death of a child", /* 18 SIGCLD */
2869 "power-fail restart", /* 19 SIGPWR */
2870 "bogus signal", /* 20 */
2871 "bogus signal", /* 21 */
2872 "bogus signal", /* 22 */
2873 "bogus signal", /* 23 */
2874 "bogus signal", /* 24 */
2875 "LAN I/O interrupt", /* 25 SIGAIO */
2876 "PTY I/O interrupt", /* 26 SIGPTY */
2877 "I/O intervention required", /* 27 SIGIOINT */
2878 "HFT grant", /* 28 SIGGRANT */
2879 "HFT retract", /* 29 SIGRETRACT */
2880 "HFT sound done", /* 30 SIGSOUND */
2881 "HFT input ready", /* 31 SIGMSG */
2882 #else /* not AIX */
2883 "bogus signal", /* 0 */
2884 "hangup", /* 1 SIGHUP */
2885 "interrupt", /* 2 SIGINT */
2886 "quit", /* 3 SIGQUIT */
2887 "illegal instruction", /* 4 SIGILL */
2888 "trace trap", /* 5 SIGTRAP */
2889 "IOT instruction", /* 6 SIGIOT */
2890 "EMT instruction", /* 7 SIGEMT */
2891 "floating point exception", /* 8 SIGFPE */
2892 "kill", /* 9 SIGKILL */
2893 "bus error", /* 10 SIGBUS */
2894 "segmentation violation", /* 11 SIGSEGV */
2895 "bad argument to system call", /* 12 SIGSYS */
2896 "write on a pipe with no one to read it", /* 13 SIGPIPE */
2897 "alarm clock", /* 14 SIGALRM */
2898 "software termination signum", /* 15 SIGTERM */
2899 "user defined signal 1", /* 16 SIGUSR1 */
2900 "user defined signal 2", /* 17 SIGUSR2 */
2901 "death of a child", /* 18 SIGCLD */
2902 "power-fail restart", /* 19 SIGPWR */
2903 #ifdef sun
2904 "window size change", /* 20 SIGWINCH */
2905 "urgent socket condition", /* 21 SIGURG */
2906 "pollable event occured", /* 22 SIGPOLL */
2907 "stop (cannot be caught or ignored)", /* 23 SIGSTOP */
2908 "user stop requested from tty", /* 24 SIGTSTP */
2909 "stopped process has been continued", /* 25 SIGCONT */
2910 "background tty read attempted", /* 26 SIGTTIN */
2911 "background tty write attempted", /* 27 SIGTTOU */
2912 "virtual timer expired", /* 28 SIGVTALRM */
2913 "profiling timer expired", /* 29 SIGPROF */
2914 "exceeded cpu limit", /* 30 SIGXCPU */
2915 "exceeded file size limit", /* 31 SIGXFSZ */
2916 "process's lwps are blocked", /* 32 SIGWAITING */
2917 "special signal used by thread library", /* 33 SIGLWP */
2918 #ifdef SIGFREEZE
2919 "Special Signal Used By CPR", /* 34 SIGFREEZE */
2920 #endif
2921 #ifdef SIGTHAW
2922 "Special Signal Used By CPR", /* 35 SIGTHAW */
2923 #endif
2924 #endif /* sun */
2925 #endif /* not AIX */
2926 0
2927 };
2928 #endif /* HAVE_SYS_SIGLIST */
2929
2930 /*
2931 * Warning, this function may not duplicate 4.2 action properly
2932 * under error conditions.
2933 */
2934
2935 #ifndef MAXPATHLEN
2936 /* In 4.1, param.h fails to define this. */
2937 #define MAXPATHLEN 1024
2938 #endif
2939
2940 #ifndef HAVE_GETWD
2941
2942 char *
2943 getwd (pathname)
2944 char *pathname;
2945 {
2946 char *npath, *spath;
2947 extern char *getcwd ();
2948
2949 BLOCK_INPUT; /* getcwd uses malloc */
2950 spath = npath = getcwd ((char *) 0, MAXPATHLEN);
2951 if (spath == 0)
2952 return spath;
2953 /* On Altos 3068, getcwd can return @hostname/dir, so discard
2954 up to first slash. Should be harmless on other systems. */
2955 while (*npath && *npath != '/')
2956 npath++;
2957 strcpy (pathname, npath);
2958 free (spath); /* getcwd uses malloc */
2959 UNBLOCK_INPUT;
2960 return pathname;
2961 }
2962
2963 #endif /* HAVE_GETWD */
2964
2965 /*
2966 * Emulate rename using unlink/link. Note that this is
2967 * only partially correct. Also, doesn't enforce restriction
2968 * that files be of same type (regular->regular, dir->dir, etc).
2969 */
2970
2971 #ifndef HAVE_RENAME
2972
2973 rename (from, to)
2974 const char *from;
2975 const char *to;
2976 {
2977 if (access (from, 0) == 0)
2978 {
2979 unlink (to);
2980 if (link (from, to) == 0)
2981 if (unlink (from) == 0)
2982 return (0);
2983 }
2984 return (-1);
2985 }
2986
2987 #endif
2988
2989 #ifdef MISSING_UTIMES
2990
2991 /* HPUX (among others) sets HAVE_TIMEVAL but does not implement utimes. */
2992
2993 utimes ()
2994 {
2995 }
2996 #endif
2997
2998 #ifdef IRIS_UTIME
2999
3000 /* The IRIS (3.5) has timevals, but uses sys V utime, and doesn't have the
3001 utimbuf structure defined anywhere but in the man page. */
3002
3003 struct utimbuf
3004 {
3005 long actime;
3006 long modtime;
3007 };
3008
3009 utimes (name, tvp)
3010 char *name;
3011 struct timeval tvp[];
3012 {
3013 struct utimbuf utb;
3014 utb.actime = tvp[0].tv_sec;
3015 utb.modtime = tvp[1].tv_sec;
3016 utime (name, &utb);
3017 }
3018 #endif /* IRIS_UTIME */
3019
3020
3021 #ifdef HPUX
3022 #ifndef HAVE_PERROR
3023
3024 /* HPUX curses library references perror, but as far as we know
3025 it won't be called. Anyway this definition will do for now. */
3026
3027 perror ()
3028 {
3029 }
3030
3031 #endif /* not HAVE_PERROR */
3032 #endif /* HPUX */
3033
3034 #ifndef HAVE_DUP2
3035
3036 /*
3037 * Emulate BSD dup2. First close newd if it already exists.
3038 * Then, attempt to dup oldd. If not successful, call dup2 recursively
3039 * until we are, then close the unsuccessful ones.
3040 */
3041
3042 dup2 (oldd, newd)
3043 int oldd;
3044 int newd;
3045 {
3046 register int fd, ret;
3047
3048 sys_close (newd);
3049
3050 #ifdef F_DUPFD
3051 fd = fcntl (oldd, F_DUPFD, newd);
3052 if (fd != newd)
3053 error ("can't dup2 (%i,%i) : %s", oldd, newd, strerror (errno));
3054 #else
3055 fd = dup (old);
3056 if (fd == -1)
3057 return -1;
3058 if (fd == new)
3059 return new;
3060 ret = dup2 (old,new);
3061 sys_close (fd);
3062 return ret;
3063 #endif
3064 }
3065
3066 #endif /* not HAVE_DUP2 */
3067
3068 /*
3069 * Gettimeofday. Simulate as much as possible. Only accurate
3070 * to nearest second. Emacs doesn't use tzp so ignore it for now.
3071 * Only needed when subprocesses are defined.
3072 */
3073
3074 #ifdef subprocesses
3075 #ifndef VMS
3076 #ifndef HAVE_GETTIMEOFDAY
3077 #ifdef HAVE_TIMEVAL
3078
3079 /* ARGSUSED */
3080 gettimeofday (tp, tzp)
3081 struct timeval *tp;
3082 struct timezone *tzp;
3083 {
3084 extern long time ();
3085
3086 tp->tv_sec = time ((long *)0);
3087 tp->tv_usec = 0;
3088 if (tzp != 0)
3089 tzp->tz_minuteswest = -1;
3090 }
3091
3092 #endif
3093 #endif
3094 #endif
3095 #endif /* subprocess && !HAVE_GETTIMEOFDAY && HAVE_TIMEVAL && !VMS */
3096
3097 /*
3098 * This function will go away as soon as all the stubs fixed. (fnf)
3099 */
3100
3101 croak (badfunc)
3102 char *badfunc;
3103 {
3104 printf ("%s not yet implemented\r\n", badfunc);
3105 reset_sys_modes ();
3106 exit (1);
3107 }
3108
3109 #endif /* USG */
3110 \f
3111 #ifdef DGUX
3112
3113 char *sys_siglist[NSIG + 1] =
3114 {
3115 "null signal", /* 0 SIGNULL */
3116 "hangup", /* 1 SIGHUP */
3117 "interrupt", /* 2 SIGINT */
3118 "quit", /* 3 SIGQUIT */
3119 "illegal instruction", /* 4 SIGILL */
3120 "trace trap", /* 5 SIGTRAP */
3121 "abort termination", /* 6 SIGABRT */
3122 "SIGEMT", /* 7 SIGEMT */
3123 "floating point exception", /* 8 SIGFPE */
3124 "kill", /* 9 SIGKILL */
3125 "bus error", /* 10 SIGBUS */
3126 "segmentation violation", /* 11 SIGSEGV */
3127 "bad argument to system call", /* 12 SIGSYS */
3128 "write on a pipe with no reader", /* 13 SIGPIPE */
3129 "alarm clock", /* 14 SIGALRM */
3130 "software termination signal", /* 15 SIGTERM */
3131 "user defined signal 1", /* 16 SIGUSR1 */
3132 "user defined signal 2", /* 17 SIGUSR2 */
3133 "child stopped or terminated", /* 18 SIGCLD */
3134 "power-fail restart", /* 19 SIGPWR */
3135 "window size changed", /* 20 SIGWINCH */
3136 "undefined", /* 21 */
3137 "pollable event occurred", /* 22 SIGPOLL */
3138 "sendable stop signal not from tty", /* 23 SIGSTOP */
3139 "stop signal from tty", /* 24 SIGSTP */
3140 "continue a stopped process", /* 25 SIGCONT */
3141 "attempted background tty read", /* 26 SIGTTIN */
3142 "attempted background tty write", /* 27 SIGTTOU */
3143 "undefined", /* 28 */
3144 "undefined", /* 29 */
3145 "undefined", /* 30 */
3146 "undefined", /* 31 */
3147 "undefined", /* 32 */
3148 "socket (TCP/IP) urgent data arrival", /* 33 SIGURG */
3149 "I/O is possible", /* 34 SIGIO */
3150 "exceeded cpu time limit", /* 35 SIGXCPU */
3151 "exceeded file size limit", /* 36 SIGXFSZ */
3152 "virtual time alarm", /* 37 SIGVTALRM */
3153 "profiling time alarm", /* 38 SIGPROF */
3154 "undefined", /* 39 */
3155 "file record locks revoked", /* 40 SIGLOST */
3156 "undefined", /* 41 */
3157 "undefined", /* 42 */
3158 "undefined", /* 43 */
3159 "undefined", /* 44 */
3160 "undefined", /* 45 */
3161 "undefined", /* 46 */
3162 "undefined", /* 47 */
3163 "undefined", /* 48 */
3164 "undefined", /* 49 */
3165 "undefined", /* 50 */
3166 "undefined", /* 51 */
3167 "undefined", /* 52 */
3168 "undefined", /* 53 */
3169 "undefined", /* 54 */
3170 "undefined", /* 55 */
3171 "undefined", /* 56 */
3172 "undefined", /* 57 */
3173 "undefined", /* 58 */
3174 "undefined", /* 59 */
3175 "undefined", /* 60 */
3176 "undefined", /* 61 */
3177 "undefined", /* 62 */
3178 "undefined", /* 63 */
3179 "notification message in mess. queue", /* 64 SIGDGNOTIFY */
3180 0
3181 };
3182
3183 #endif /* DGUX */
3184 \f
3185 /* Directory routines for systems that don't have them. */
3186
3187 #ifdef SYSV_SYSTEM_DIR
3188
3189 #include <dirent.h>
3190
3191 #if defined(BROKEN_CLOSEDIR) || !defined(HAVE_CLOSEDIR)
3192
3193 int
3194 closedir (dirp)
3195 register DIR *dirp; /* stream from opendir */
3196 {
3197 int rtnval;
3198
3199 rtnval = sys_close (dirp->dd_fd);
3200
3201 /* Some systems (like Solaris) allocate the buffer and the DIR all
3202 in one block. Why in the world are we freeing this ourselves
3203 anyway? */
3204 #if ! (defined (sun) && defined (USG5_4))
3205 xfree ((char *) dirp->dd_buf); /* directory block defined in <dirent.h> */
3206 #endif
3207 xfree ((char *) dirp);
3208
3209 return rtnval;
3210 }
3211 #endif /* BROKEN_CLOSEDIR or not HAVE_CLOSEDIR */
3212 #endif /* SYSV_SYSTEM_DIR */
3213
3214 #ifdef NONSYSTEM_DIR_LIBRARY
3215
3216 DIR *
3217 opendir (filename)
3218 char *filename; /* name of directory */
3219 {
3220 register DIR *dirp; /* -> malloc'ed storage */
3221 register int fd; /* file descriptor for read */
3222 struct stat sbuf; /* result of fstat */
3223
3224 fd = sys_open (filename, 0);
3225 if (fd < 0)
3226 return 0;
3227
3228 BLOCK_INPUT;
3229 if (fstat (fd, &sbuf) < 0
3230 || (sbuf.st_mode & S_IFMT) != S_IFDIR
3231 || (dirp = (DIR *) malloc (sizeof (DIR))) == 0)
3232 {
3233 sys_close (fd);
3234 UNBLOCK_INPUT;
3235 return 0; /* bad luck today */
3236 }
3237 UNBLOCK_INPUT;
3238
3239 dirp->dd_fd = fd;
3240 dirp->dd_loc = dirp->dd_size = 0; /* refill needed */
3241
3242 return dirp;
3243 }
3244
3245 void
3246 closedir (dirp)
3247 register DIR *dirp; /* stream from opendir */
3248 {
3249 sys_close (dirp->dd_fd);
3250 xfree ((char *) dirp);
3251 }
3252
3253
3254 #ifndef VMS
3255 #define DIRSIZ 14
3256 struct olddir
3257 {
3258 ino_t od_ino; /* inode */
3259 char od_name[DIRSIZ]; /* filename */
3260 };
3261 #endif /* not VMS */
3262
3263 struct direct dir_static; /* simulated directory contents */
3264
3265 /* ARGUSED */
3266 struct direct *
3267 readdir (dirp)
3268 register DIR *dirp; /* stream from opendir */
3269 {
3270 #ifndef VMS
3271 register struct olddir *dp; /* -> directory data */
3272 #else /* VMS */
3273 register struct dir$_name *dp; /* -> directory data */
3274 register struct dir$_version *dv; /* -> version data */
3275 #endif /* VMS */
3276
3277 for (; ;)
3278 {
3279 if (dirp->dd_loc >= dirp->dd_size)
3280 dirp->dd_loc = dirp->dd_size = 0;
3281
3282 if (dirp->dd_size == 0 /* refill buffer */
3283 && (dirp->dd_size = sys_read (dirp->dd_fd, dirp->dd_buf, DIRBLKSIZ)) <= 0)
3284 return 0;
3285
3286 #ifndef VMS
3287 dp = (struct olddir *) &dirp->dd_buf[dirp->dd_loc];
3288 dirp->dd_loc += sizeof (struct olddir);
3289
3290 if (dp->od_ino != 0) /* not deleted entry */
3291 {
3292 dir_static.d_ino = dp->od_ino;
3293 strncpy (dir_static.d_name, dp->od_name, DIRSIZ);
3294 dir_static.d_name[DIRSIZ] = '\0';
3295 dir_static.d_namlen = strlen (dir_static.d_name);
3296 dir_static.d_reclen = sizeof (struct direct)
3297 - MAXNAMLEN + 3
3298 + dir_static.d_namlen - dir_static.d_namlen % 4;
3299 return &dir_static; /* -> simulated structure */
3300 }
3301 #else /* VMS */
3302 dp = (struct dir$_name *) dirp->dd_buf;
3303 if (dirp->dd_loc == 0)
3304 dirp->dd_loc = (dp->dir$b_namecount&1) ? dp->dir$b_namecount + 1
3305 : dp->dir$b_namecount;
3306 dv = (struct dir$_version *)&dp->dir$t_name[dirp->dd_loc];
3307 dir_static.d_ino = dv->dir$w_fid_num;
3308 dir_static.d_namlen = dp->dir$b_namecount;
3309 dir_static.d_reclen = sizeof (struct direct)
3310 - MAXNAMLEN + 3
3311 + dir_static.d_namlen - dir_static.d_namlen % 4;
3312 strncpy (dir_static.d_name, dp->dir$t_name, dp->dir$b_namecount);
3313 dir_static.d_name[dir_static.d_namlen] = '\0';
3314 dirp->dd_loc = dirp->dd_size; /* only one record at a time */
3315 return &dir_static;
3316 #endif /* VMS */
3317 }
3318 }
3319
3320 #ifdef VMS
3321 /* readdirver is just like readdir except it returns all versions of a file
3322 as separate entries. */
3323
3324 /* ARGUSED */
3325 struct direct *
3326 readdirver (dirp)
3327 register DIR *dirp; /* stream from opendir */
3328 {
3329 register struct dir$_name *dp; /* -> directory data */
3330 register struct dir$_version *dv; /* -> version data */
3331
3332 if (dirp->dd_loc >= dirp->dd_size - sizeof (struct dir$_name))
3333 dirp->dd_loc = dirp->dd_size = 0;
3334
3335 if (dirp->dd_size == 0 /* refill buffer */
3336 && (dirp->dd_size = sys_read (dirp->dd_fd, dirp->dd_buf, DIRBLKSIZ)) <= 0)
3337 return 0;
3338
3339 dp = (struct dir$_name *) dirp->dd_buf;
3340 if (dirp->dd_loc == 0)
3341 dirp->dd_loc = (dp->dir$b_namecount & 1) ? dp->dir$b_namecount + 1
3342 : dp->dir$b_namecount;
3343 dv = (struct dir$_version *) &dp->dir$t_name[dirp->dd_loc];
3344 strncpy (dir_static.d_name, dp->dir$t_name, dp->dir$b_namecount);
3345 sprintf (&dir_static.d_name[dp->dir$b_namecount], ";%d", dv->dir$w_version);
3346 dir_static.d_namlen = strlen (dir_static.d_name);
3347 dir_static.d_ino = dv->dir$w_fid_num;
3348 dir_static.d_reclen = sizeof (struct direct) - MAXNAMLEN + 3
3349 + dir_static.d_namlen - dir_static.d_namlen % 4;
3350 dirp->dd_loc = ((char *) (++dv) - dp->dir$t_name);
3351 return &dir_static;
3352 }
3353
3354 #endif /* VMS */
3355
3356 #endif /* NONSYSTEM_DIR_LIBRARY */
3357
3358 \f
3359 /* mkdir and rmdir functions, for systems which don't have them. */
3360
3361 #ifndef HAVE_MKDIR
3362 /*
3363 * Written by Robert Rother, Mariah Corporation, August 1985.
3364 *
3365 * If you want it, it's yours. All I ask in return is that if you
3366 * figure out how to do this in a Bourne Shell script you send me
3367 * a copy.
3368 * sdcsvax!rmr or rmr@uscd
3369 *
3370 * Severely hacked over by John Gilmore to make a 4.2BSD compatible
3371 * subroutine. 11Mar86; hoptoad!gnu
3372 *
3373 * Modified by rmtodd@uokmax 6-28-87 -- when making an already existing dir,
3374 * subroutine didn't return EEXIST. It does now.
3375 */
3376
3377 /*
3378 * Make a directory.
3379 */
3380 #ifdef MKDIR_PROTOTYPE
3381 MKDIR_PROTOTYPE
3382 #else
3383 int
3384 mkdir (dpath, dmode)
3385 char *dpath;
3386 int dmode;
3387 #endif
3388 {
3389 int cpid, status, fd;
3390 struct stat statbuf;
3391
3392 if (stat (dpath, &statbuf) == 0)
3393 {
3394 errno = EEXIST; /* Stat worked, so it already exists */
3395 return -1;
3396 }
3397
3398 /* If stat fails for a reason other than non-existence, return error */
3399 if (errno != ENOENT)
3400 return -1;
3401
3402 synch_process_alive = 1;
3403 switch (cpid = fork ())
3404 {
3405
3406 case -1: /* Error in fork */
3407 return (-1); /* Errno is set already */
3408
3409 case 0: /* Child process */
3410 /*
3411 * Cheap hack to set mode of new directory. Since this
3412 * child process is going away anyway, we zap its umask.
3413 * FIXME, this won't suffice to set SUID, SGID, etc. on this
3414 * directory. Does anybody care?
3415 */
3416 status = umask (0); /* Get current umask */
3417 status = umask (status | (0777 & ~dmode)); /* Set for mkdir */
3418 fd = sys_open("/dev/null", 2);
3419 if (fd >= 0)
3420 {
3421 dup2 (fd, 0);
3422 dup2 (fd, 1);
3423 dup2 (fd, 2);
3424 }
3425 execl ("/bin/mkdir", "mkdir", dpath, (char *) 0);
3426 _exit (-1); /* Can't exec /bin/mkdir */
3427
3428 default: /* Parent process */
3429 wait_for_termination (cpid);
3430 }
3431
3432 if (synch_process_death != 0 || synch_process_retcode != 0)
3433 {
3434 errno = EIO; /* We don't know why, but */
3435 return -1; /* /bin/mkdir failed */
3436 }
3437
3438 return 0;
3439 }
3440 #endif /* not HAVE_MKDIR */
3441
3442 #ifndef HAVE_RMDIR
3443 int
3444 rmdir (dpath)
3445 char *dpath;
3446 {
3447 int cpid, status, fd;
3448 struct stat statbuf;
3449
3450 if (stat (dpath, &statbuf) != 0)
3451 {
3452 /* Stat just set errno. We don't have to */
3453 return -1;
3454 }
3455
3456 synch_process_alive = 1;
3457 switch (cpid = fork ())
3458 {
3459
3460 case -1: /* Error in fork */
3461 return (-1); /* Errno is set already */
3462
3463 case 0: /* Child process */
3464 fd = sys_open("/dev/null", 2);
3465 if (fd >= 0)
3466 {
3467 dup2 (fd, 0);
3468 dup2 (fd, 1);
3469 dup2 (fd, 2);
3470 }
3471 wait_for_termination (cpid);
3472 if (synch_process_death != 0 || synch_process_retcode != 0)
3473 return -1; /* /bin/rmdir failed */
3474 default: /* Parent process */
3475 while (cpid != wait (&status)); /* Wait for kid to finish */
3476 }
3477
3478 if (WIFSIGNALED (status) || WEXITSTATUS (status) != 0)
3479 {
3480 errno = EIO; /* We don't know why, but */
3481 return -1; /* /bin/mkdir failed */
3482 }
3483
3484 return 0;
3485 }
3486 #endif /* !HAVE_RMDIR */
3487
3488
3489 \f
3490 /* Functions for VMS */
3491 #ifdef VMS
3492 #include "vms-pwd.h"
3493 #include <acldef.h>
3494 #include <chpdef.h>
3495 #include <jpidef.h>
3496
3497 /* Return as a string the VMS error string pertaining to STATUS.
3498 Reuses the same static buffer each time it is called. */
3499
3500 char *
3501 vmserrstr (status)
3502 int status; /* VMS status code */
3503 {
3504 int bufadr[2];
3505 short len;
3506 static char buf[257];
3507
3508 bufadr[0] = sizeof buf - 1;
3509 bufadr[1] = (int) buf;
3510 if (! (SYS$GETMSG (status, &len, bufadr, 0x1, 0) & 1))
3511 return "untranslatable VMS error status";
3512 buf[len] = '\0';
3513 return buf;
3514 }
3515
3516 #ifdef access
3517 #undef access
3518
3519 /* The following is necessary because 'access' emulation by VMS C (2.0) does
3520 * not work correctly. (It also doesn't work well in version 2.3.)
3521 */
3522
3523 #ifdef VMS4_4
3524
3525 #define DESCRIPTOR(name,string) struct dsc$descriptor_s name = \
3526 { strlen (string), DSC$K_DTYPE_T, DSC$K_CLASS_S, string }
3527
3528 typedef union {
3529 struct {
3530 unsigned short s_buflen;
3531 unsigned short s_code;
3532 char *s_bufadr;
3533 unsigned short *s_retlenadr;
3534 } s;
3535 int end;
3536 } item;
3537 #define buflen s.s_buflen
3538 #define code s.s_code
3539 #define bufadr s.s_bufadr
3540 #define retlenadr s.s_retlenadr
3541
3542 #define R_OK 4 /* test for read permission */
3543 #define W_OK 2 /* test for write permission */
3544 #define X_OK 1 /* test for execute (search) permission */
3545 #define F_OK 0 /* test for presence of file */
3546
3547 int
3548 sys_access (path, mode)
3549 char *path;
3550 int mode;
3551 {
3552 static char *user = NULL;
3553 char dir_fn[512];
3554
3555 /* translate possible directory spec into .DIR file name, so brain-dead
3556 * access can treat the directory like a file. */
3557 if (directory_file_name (path, dir_fn))
3558 path = dir_fn;
3559
3560 if (mode == F_OK)
3561 return access (path, mode);
3562 if (user == NULL && (user = (char *) getenv ("USER")) == NULL)
3563 return -1;
3564 {
3565 int stat;
3566 int flags;
3567 int acces;
3568 unsigned short int dummy;
3569 item itemlst[3];
3570 static int constant = ACL$C_FILE;
3571 DESCRIPTOR (path_desc, path);
3572 DESCRIPTOR (user_desc, user);
3573
3574 flags = 0;
3575 acces = 0;
3576 if ((mode & X_OK) && ((stat = access (path, mode)) < 0 || mode == X_OK))
3577 return stat;
3578 if (mode & R_OK)
3579 acces |= CHP$M_READ;
3580 if (mode & W_OK)
3581 acces |= CHP$M_WRITE;
3582 itemlst[0].buflen = sizeof (int);
3583 itemlst[0].code = CHP$_FLAGS;
3584 itemlst[0].bufadr = (char *) &flags;
3585 itemlst[0].retlenadr = &dummy;
3586 itemlst[1].buflen = sizeof (int);
3587 itemlst[1].code = CHP$_ACCESS;
3588 itemlst[1].bufadr = (char *) &acces;
3589 itemlst[1].retlenadr = &dummy;
3590 itemlst[2].end = CHP$_END;
3591 stat = SYS$CHECK_ACCESS (&constant, &path_desc, &user_desc, itemlst);
3592 return stat == SS$_NORMAL ? 0 : -1;
3593 }
3594 }
3595
3596 #else /* not VMS4_4 */
3597
3598 #include <prvdef.h>
3599 #define ACE$M_WRITE 2
3600 #define ACE$C_KEYID 1
3601
3602 static unsigned short memid, grpid;
3603 static unsigned int uic;
3604
3605 /* Called from init_sys_modes, so it happens not very often
3606 but at least each time Emacs is loaded. */
3607 sys_access_reinit ()
3608 {
3609 uic = 0;
3610 }
3611
3612 int
3613 sys_access (filename, type)
3614 char * filename;
3615 int type;
3616 {
3617 struct FAB fab;
3618 struct XABPRO xab;
3619 int status, size, i, typecode, acl_controlled;
3620 unsigned int *aclptr, *aclend, aclbuf[60];
3621 union prvdef prvmask;
3622
3623 /* Get UIC and GRP values for protection checking. */
3624 if (uic == 0)
3625 {
3626 status = LIB$GETJPI (&JPI$_UIC, 0, 0, &uic, 0, 0);
3627 if (! (status & 1))
3628 return -1;
3629 memid = uic & 0xFFFF;
3630 grpid = uic >> 16;
3631 }
3632
3633 if (type != 2) /* not checking write access */
3634 return access (filename, type);
3635
3636 /* Check write protection. */
3637
3638 #define CHECKPRIV(bit) (prvmask.bit)
3639 #define WRITEABLE(field) (! ((xab.xab$w_pro >> field) & XAB$M_NOWRITE))
3640
3641 /* Find privilege bits */
3642 status = SYS$SETPRV (0, 0, 0, prvmask);
3643 if (! (status & 1))
3644 error ("Unable to find privileges: %s", vmserrstr (status));
3645 if (CHECKPRIV (PRV$V_BYPASS))
3646 return 0; /* BYPASS enabled */
3647 fab = cc$rms_fab;
3648 fab.fab$b_fac = FAB$M_GET;
3649 fab.fab$l_fna = filename;
3650 fab.fab$b_fns = strlen (filename);
3651 fab.fab$l_xab = &xab;
3652 xab = cc$rms_xabpro;
3653 xab.xab$l_aclbuf = aclbuf;
3654 xab.xab$w_aclsiz = sizeof (aclbuf);
3655 status = SYS$OPEN (&fab, 0, 0);
3656 if (! (status & 1))
3657 return -1;
3658 SYS$CLOSE (&fab, 0, 0);
3659 /* Check system access */
3660 if (CHECKPRIV (PRV$V_SYSPRV) && WRITEABLE (XAB$V_SYS))
3661 return 0;
3662 /* Check ACL entries, if any */
3663 acl_controlled = 0;
3664 if (xab.xab$w_acllen > 0)
3665 {
3666 aclptr = aclbuf;
3667 aclend = &aclbuf[xab.xab$w_acllen / 4];
3668 while (*aclptr && aclptr < aclend)
3669 {
3670 size = (*aclptr & 0xff) / 4;
3671 typecode = (*aclptr >> 8) & 0xff;
3672 if (typecode == ACE$C_KEYID)
3673 for (i = size - 1; i > 1; i--)
3674 if (aclptr[i] == uic)
3675 {
3676 acl_controlled = 1;
3677 if (aclptr[1] & ACE$M_WRITE)
3678 return 0; /* Write access through ACL */
3679 }
3680 aclptr = &aclptr[size];
3681 }
3682 if (acl_controlled) /* ACL specified, prohibits write access */
3683 return -1;
3684 }
3685 /* No ACL entries specified, check normal protection */
3686 if (WRITEABLE (XAB$V_WLD)) /* World writeable */
3687 return 0;
3688 if (WRITEABLE (XAB$V_GRP) &&
3689 (unsigned short) (xab.xab$l_uic >> 16) == grpid)
3690 return 0; /* Group writeable */
3691 if (WRITEABLE (XAB$V_OWN) &&
3692 (xab.xab$l_uic & 0xFFFF) == memid)
3693 return 0; /* Owner writeable */
3694
3695 return -1; /* Not writeable */
3696 }
3697 #endif /* not VMS4_4 */
3698 #endif /* access */
3699
3700 static char vtbuf[NAM$C_MAXRSS+1];
3701
3702 /* translate a vms file spec to a unix path */
3703 char *
3704 sys_translate_vms (vfile)
3705 char * vfile;
3706 {
3707 char * p;
3708 char * targ;
3709
3710 if (!vfile)
3711 return 0;
3712
3713 targ = vtbuf;
3714
3715 /* leading device or logical name is a root directory */
3716 if (p = strchr (vfile, ':'))
3717 {
3718 *targ++ = '/';
3719 while (vfile < p)
3720 *targ++ = *vfile++;
3721 vfile++;
3722 *targ++ = '/';
3723 }
3724 p = vfile;
3725 if (*p == '[' || *p == '<')
3726 {
3727 while (*++vfile != *p + 2)
3728 switch (*vfile)
3729 {
3730 case '.':
3731 if (vfile[-1] == *p)
3732 *targ++ = '.';
3733 *targ++ = '/';
3734 break;
3735
3736 case '-':
3737 *targ++ = '.';
3738 *targ++ = '.';
3739 break;
3740
3741 default:
3742 *targ++ = *vfile;
3743 break;
3744 }
3745 vfile++;
3746 *targ++ = '/';
3747 }
3748 while (*vfile)
3749 *targ++ = *vfile++;
3750
3751 return vtbuf;
3752 }
3753
3754 static char utbuf[NAM$C_MAXRSS+1];
3755
3756 /* translate a unix path to a VMS file spec */
3757 char *
3758 sys_translate_unix (ufile)
3759 char * ufile;
3760 {
3761 int slash_seen = 0;
3762 char *p;
3763 char * targ;
3764
3765 if (!ufile)
3766 return 0;
3767
3768 targ = utbuf;
3769
3770 if (*ufile == '/')
3771 {
3772 ufile++;
3773 }
3774
3775 while (*ufile)
3776 {
3777 switch (*ufile)
3778 {
3779 case '/':
3780 if (slash_seen)
3781 if (index (&ufile[1], '/'))
3782 *targ++ = '.';
3783 else
3784 *targ++ = ']';
3785 else
3786 {
3787 *targ++ = ':';
3788 if (index (&ufile[1], '/'))
3789 *targ++ = '[';
3790 slash_seen = 1;
3791 }
3792 break;
3793
3794 case '.':
3795 if (strncmp (ufile, "./", 2) == 0)
3796 {
3797 if (!slash_seen)
3798 {
3799 *targ++ = '[';
3800 slash_seen = 1;
3801 }
3802 ufile++; /* skip the dot */
3803 if (index (&ufile[1], '/'))
3804 *targ++ = '.';
3805 else
3806 *targ++ = ']';
3807 }
3808 else if (strncmp (ufile, "../", 3) == 0)
3809 {
3810 if (!slash_seen)
3811 {
3812 *targ++ = '[';
3813 slash_seen = 1;
3814 }
3815 *targ++ = '-';
3816 ufile += 2; /* skip the dots */
3817 if (index (&ufile[1], '/'))
3818 *targ++ = '.';
3819 else
3820 *targ++ = ']';
3821 }
3822 else
3823 *targ++ = *ufile;
3824 break;
3825
3826 default:
3827 *targ++ = *ufile;
3828 break;
3829 }
3830 ufile++;
3831 }
3832 *targ = '\0';
3833
3834 return utbuf;
3835 }
3836
3837 char *
3838 getwd (pathname)
3839 char *pathname;
3840 {
3841 char *ptr, *val;
3842 extern char *getcwd ();
3843
3844 #define MAXPATHLEN 1024
3845
3846 ptr = xmalloc (MAXPATHLEN);
3847 val = getcwd (ptr, MAXPATHLEN);
3848 if (val == 0)
3849 {
3850 xfree (ptr);
3851 return val;
3852 }
3853 strcpy (pathname, ptr);
3854 xfree (ptr);
3855
3856 return pathname;
3857 }
3858
3859 getppid ()
3860 {
3861 long item_code = JPI$_OWNER;
3862 unsigned long parent_id;
3863 int status;
3864
3865 if (((status = LIB$GETJPI (&item_code, 0, 0, &parent_id)) & 1) == 0)
3866 {
3867 errno = EVMSERR;
3868 vaxc$errno = status;
3869 return -1;
3870 }
3871 return parent_id;
3872 }
3873
3874 #undef getuid
3875 unsigned
3876 sys_getuid ()
3877 {
3878 return (getgid () << 16) | getuid ();
3879 }
3880
3881 int
3882 sys_read (fildes, buf, nbyte)
3883 int fildes;
3884 char *buf;
3885 unsigned int nbyte;
3886 {
3887 return read (fildes, buf, (nbyte < MAXIOSIZE ? nbyte : MAXIOSIZE));
3888 }
3889
3890 #if 0
3891 int
3892 sys_write (fildes, buf, nbyte)
3893 int fildes;
3894 char *buf;
3895 unsigned int nbyte;
3896 {
3897 register int nwrote, rtnval = 0;
3898
3899 while (nbyte > MAXIOSIZE && (nwrote = write (fildes, buf, MAXIOSIZE)) > 0) {
3900 nbyte -= nwrote;
3901 buf += nwrote;
3902 rtnval += nwrote;
3903 }
3904 if (nwrote < 0)
3905 return rtnval ? rtnval : -1;
3906 if ((nwrote = write (fildes, buf, nbyte)) < 0)
3907 return rtnval ? rtnval : -1;
3908 return (rtnval + nwrote);
3909 }
3910 #endif /* 0 */
3911
3912 /*
3913 * VAX/VMS VAX C RTL really loses. It insists that records
3914 * end with a newline (carriage return) character, and if they
3915 * don't it adds one (nice of it isn't it!)
3916 *
3917 * Thus we do this stupidity below.
3918 */
3919
3920 int
3921 sys_write (fildes, buf, nbytes)
3922 int fildes;
3923 char *buf;
3924 unsigned int nbytes;
3925 {
3926 register char *p;
3927 register char *e;
3928 int sum = 0;
3929 struct stat st;
3930
3931 fstat (fildes, &st);
3932 p = buf;
3933 while (nbytes > 0)
3934 {
3935 int len, retval;
3936
3937 /* Handle fixed-length files with carriage control. */
3938 if (st.st_fab_rfm == FAB$C_FIX
3939 && ((st.st_fab_rat & (FAB$M_FTN | FAB$M_CR)) != 0))
3940 {
3941 len = st.st_fab_mrs;
3942 retval = write (fildes, p, min (len, nbytes));
3943 if (retval != len)
3944 return -1;
3945 retval++; /* This skips the implied carriage control */
3946 }
3947 else
3948 {
3949 e = p + min (MAXIOSIZE, nbytes) - 1;
3950 while (*e != '\n' && e > p) e--;
3951 if (p == e) /* Ok.. so here we add a newline... sigh. */
3952 e = p + min (MAXIOSIZE, nbytes) - 1;
3953 len = e + 1 - p;
3954 retval = write (fildes, p, len);
3955 if (retval != len)
3956 return -1;
3957 }
3958 p += retval;
3959 sum += retval;
3960 nbytes -= retval;
3961 }
3962 return sum;
3963 }
3964
3965 /* Create file NEW copying its attributes from file OLD. If
3966 OLD is 0 or does not exist, create based on the value of
3967 vms_stmlf_recfm. */
3968
3969 /* Protection value the file should ultimately have.
3970 Set by create_copy_attrs, and use by rename_sansversions. */
3971 static unsigned short int fab_final_pro;
3972
3973 int
3974 creat_copy_attrs (old, new)
3975 char *old, *new;
3976 {
3977 struct FAB fab = cc$rms_fab;
3978 struct XABPRO xabpro;
3979 char aclbuf[256]; /* Choice of size is arbitrary. See below. */
3980 extern int vms_stmlf_recfm;
3981
3982 if (old)
3983 {
3984 fab.fab$b_fac = FAB$M_GET;
3985 fab.fab$l_fna = old;
3986 fab.fab$b_fns = strlen (old);
3987 fab.fab$l_xab = (char *) &xabpro;
3988 xabpro = cc$rms_xabpro;
3989 xabpro.xab$l_aclbuf = aclbuf;
3990 xabpro.xab$w_aclsiz = sizeof aclbuf;
3991 /* Call $OPEN to fill in the fab & xabpro fields. */
3992 if (SYS$OPEN (&fab, 0, 0) & 1)
3993 {
3994 SYS$CLOSE (&fab, 0, 0);
3995 fab.fab$l_alq = 0; /* zero the allocation quantity */
3996 if (xabpro.xab$w_acllen > 0)
3997 {
3998 if (xabpro.xab$w_acllen > sizeof aclbuf)
3999 /* If the acl buffer was too short, redo open with longer one.
4000 Wouldn't need to do this if there were some system imposed
4001 limit on the size of an ACL, but I can't find any such. */
4002 {
4003 xabpro.xab$l_aclbuf = (char *) alloca (xabpro.xab$w_acllen);
4004 xabpro.xab$w_aclsiz = xabpro.xab$w_acllen;
4005 if (SYS$OPEN (&fab, 0, 0) & 1)
4006 SYS$CLOSE (&fab, 0, 0);
4007 else
4008 old = 0;
4009 }
4010 }
4011 else
4012 xabpro.xab$l_aclbuf = 0;
4013 }
4014 else
4015 old = 0;
4016 }
4017 fab.fab$l_fna = new;
4018 fab.fab$b_fns = strlen (new);
4019 if (!old)
4020 {
4021 fab.fab$l_xab = 0;
4022 fab.fab$b_rfm = vms_stmlf_recfm ? FAB$C_STMLF : FAB$C_VAR;
4023 fab.fab$b_rat = FAB$M_CR;
4024 }
4025
4026 /* Set the file protections such that we will be able to manipulate
4027 this file. Once we are done writing and renaming it, we will set
4028 the protections back. */
4029 if (old)
4030 fab_final_pro = xabpro.xab$w_pro;
4031 else
4032 SYS$SETDFPROT (0, &fab_final_pro);
4033 xabpro.xab$w_pro &= 0xff0f; /* set O:rewd for now. This is set back later. */
4034
4035 /* Create the new file with either default attrs or attrs copied
4036 from old file. */
4037 if (!(SYS$CREATE (&fab, 0, 0) & 1))
4038 return -1;
4039 SYS$CLOSE (&fab, 0, 0);
4040 /* As this is a "replacement" for creat, return a file descriptor
4041 opened for writing. */
4042 return open (new, O_WRONLY);
4043 }
4044
4045 #ifdef creat
4046 #undef creat
4047 #include <varargs.h>
4048 #ifdef __GNUC__
4049 #ifndef va_count
4050 #define va_count(X) ((X) = *(((int *) &(va_alist)) - 1))
4051 #endif
4052 #endif
4053
4054 sys_creat (va_alist)
4055 va_dcl
4056 {
4057 va_list list_incrementer;
4058 char *name;
4059 int mode;
4060 int rfd; /* related file descriptor */
4061 int fd; /* Our new file descriptor */
4062 int count;
4063 struct stat st_buf;
4064 char rfm[12];
4065 char rat[15];
4066 char mrs[13];
4067 char fsz[13];
4068 extern int vms_stmlf_recfm;
4069
4070 va_count (count);
4071 va_start (list_incrementer);
4072 name = va_arg (list_incrementer, char *);
4073 mode = va_arg (list_incrementer, int);
4074 if (count > 2)
4075 rfd = va_arg (list_incrementer, int);
4076 va_end (list_incrementer);
4077 if (count > 2)
4078 {
4079 /* Use information from the related file descriptor to set record
4080 format of the newly created file. */
4081 fstat (rfd, &st_buf);
4082 switch (st_buf.st_fab_rfm)
4083 {
4084 case FAB$C_FIX:
4085 strcpy (rfm, "rfm = fix");
4086 sprintf (mrs, "mrs = %d", st_buf.st_fab_mrs);
4087 strcpy (rat, "rat = ");
4088 if (st_buf.st_fab_rat & FAB$M_CR)
4089 strcat (rat, "cr");
4090 else if (st_buf.st_fab_rat & FAB$M_FTN)
4091 strcat (rat, "ftn");
4092 else if (st_buf.st_fab_rat & FAB$M_PRN)
4093 strcat (rat, "prn");
4094 if (st_buf.st_fab_rat & FAB$M_BLK)
4095 if (st_buf.st_fab_rat & (FAB$M_CR|FAB$M_FTN|FAB$M_PRN))
4096 strcat (rat, ", blk");
4097 else
4098 strcat (rat, "blk");
4099 return creat (name, 0, rfm, rat, mrs);
4100
4101 case FAB$C_VFC:
4102 strcpy (rfm, "rfm = vfc");
4103 sprintf (fsz, "fsz = %d", st_buf.st_fab_fsz);
4104 strcpy (rat, "rat = ");
4105 if (st_buf.st_fab_rat & FAB$M_CR)
4106 strcat (rat, "cr");
4107 else if (st_buf.st_fab_rat & FAB$M_FTN)
4108 strcat (rat, "ftn");
4109 else if (st_buf.st_fab_rat & FAB$M_PRN)
4110 strcat (rat, "prn");
4111 if (st_buf.st_fab_rat & FAB$M_BLK)
4112 if (st_buf.st_fab_rat & (FAB$M_CR|FAB$M_FTN|FAB$M_PRN))
4113 strcat (rat, ", blk");
4114 else
4115 strcat (rat, "blk");
4116 return creat (name, 0, rfm, rat, fsz);
4117
4118 case FAB$C_STM:
4119 strcpy (rfm, "rfm = stm");
4120 break;
4121
4122 case FAB$C_STMCR:
4123 strcpy (rfm, "rfm = stmcr");
4124 break;
4125
4126 case FAB$C_STMLF:
4127 strcpy (rfm, "rfm = stmlf");
4128 break;
4129
4130 case FAB$C_UDF:
4131 strcpy (rfm, "rfm = udf");
4132 break;
4133
4134 case FAB$C_VAR:
4135 strcpy (rfm, "rfm = var");
4136 break;
4137 }
4138 strcpy (rat, "rat = ");
4139 if (st_buf.st_fab_rat & FAB$M_CR)
4140 strcat (rat, "cr");
4141 else if (st_buf.st_fab_rat & FAB$M_FTN)
4142 strcat (rat, "ftn");
4143 else if (st_buf.st_fab_rat & FAB$M_PRN)
4144 strcat (rat, "prn");
4145 if (st_buf.st_fab_rat & FAB$M_BLK)
4146 if (st_buf.st_fab_rat & (FAB$M_CR|FAB$M_FTN|FAB$M_PRN))
4147 strcat (rat, ", blk");
4148 else
4149 strcat (rat, "blk");
4150 }
4151 else
4152 {
4153 strcpy (rfm, vms_stmlf_recfm ? "rfm = stmlf" : "rfm=var");
4154 strcpy (rat, "rat=cr");
4155 }
4156 /* Until the VAX C RTL fixes the many bugs with modes, always use
4157 mode 0 to get the user's default protection. */
4158 fd = creat (name, 0, rfm, rat);
4159 if (fd < 0 && errno == EEXIST)
4160 {
4161 if (unlink (name) < 0)
4162 report_file_error ("delete", build_string (name));
4163 fd = creat (name, 0, rfm, rat);
4164 }
4165 return fd;
4166 }
4167 #endif /* creat */
4168
4169 /* fwrite to stdout is S L O W. Speed it up by using fputc...*/
4170 sys_fwrite (ptr, size, num, fp)
4171 register char * ptr;
4172 FILE * fp;
4173 {
4174 register int tot = num * size;
4175
4176 while (tot--)
4177 fputc (*ptr++, fp);
4178 }
4179
4180 /*
4181 * The VMS C library routine creat actually creates a new version of an
4182 * existing file rather than truncating the old version. There are times
4183 * when this is not the desired behavior, for instance, when writing an
4184 * auto save file (you only want one version), or when you don't have
4185 * write permission in the directory containing the file (but the file
4186 * itself is writable). Hence this routine, which is equivalent to
4187 * "close (creat (fn, 0));" on Unix if fn already exists.
4188 */
4189 int
4190 vms_truncate (fn)
4191 char *fn;
4192 {
4193 struct FAB xfab = cc$rms_fab;
4194 struct RAB xrab = cc$rms_rab;
4195 int status;
4196
4197 xfab.fab$l_fop = FAB$M_TEF; /* free allocated but unused blocks on close */
4198 xfab.fab$b_fac = FAB$M_TRN | FAB$M_GET; /* allow truncate and get access */
4199 xfab.fab$b_shr = FAB$M_NIL; /* allow no sharing - file must be locked */
4200 xfab.fab$l_fna = fn;
4201 xfab.fab$b_fns = strlen (fn);
4202 xfab.fab$l_dna = ";0"; /* default to latest version of the file */
4203 xfab.fab$b_dns = 2;
4204 xrab.rab$l_fab = &xfab;
4205
4206 /* This gibberish opens the file, positions to the first record, and
4207 deletes all records from there until the end of file. */
4208 if ((SYS$OPEN (&xfab) & 01) == 01)
4209 {
4210 if ((SYS$CONNECT (&xrab) & 01) == 01 &&
4211 (SYS$FIND (&xrab) & 01) == 01 &&
4212 (SYS$TRUNCATE (&xrab) & 01) == 01)
4213 status = 0;
4214 else
4215 status = -1;
4216 }
4217 else
4218 status = -1;
4219 SYS$CLOSE (&xfab);
4220 return status;
4221 }
4222
4223 /* Define this symbol to actually read SYSUAF.DAT. This requires either
4224 SYSPRV or a readable SYSUAF.DAT. */
4225
4226 #ifdef READ_SYSUAF
4227 /*
4228 * getuaf.c
4229 *
4230 * Routine to read the VMS User Authorization File and return
4231 * a specific user's record.
4232 */
4233
4234 static struct UAF retuaf;
4235
4236 struct UAF *
4237 get_uaf_name (uname)
4238 char * uname;
4239 {
4240 register status;
4241 struct FAB uaf_fab;
4242 struct RAB uaf_rab;
4243
4244 uaf_fab = cc$rms_fab;
4245 uaf_rab = cc$rms_rab;
4246 /* initialize fab fields */
4247 uaf_fab.fab$l_fna = "SYS$SYSTEM:SYSUAF.DAT";
4248 uaf_fab.fab$b_fns = 21;
4249 uaf_fab.fab$b_fac = FAB$M_GET;
4250 uaf_fab.fab$b_org = FAB$C_IDX;
4251 uaf_fab.fab$b_shr = FAB$M_GET|FAB$M_PUT|FAB$M_UPD|FAB$M_DEL;
4252 /* initialize rab fields */
4253 uaf_rab.rab$l_fab = &uaf_fab;
4254 /* open the User Authorization File */
4255 status = SYS$OPEN (&uaf_fab);
4256 if (!(status&1))
4257 {
4258 errno = EVMSERR;
4259 vaxc$errno = status;
4260 return 0;
4261 }
4262 status = SYS$CONNECT (&uaf_rab);
4263 if (!(status&1))
4264 {
4265 errno = EVMSERR;
4266 vaxc$errno = status;
4267 return 0;
4268 }
4269 /* read the requested record - index is in uname */
4270 uaf_rab.rab$l_kbf = uname;
4271 uaf_rab.rab$b_ksz = strlen (uname);
4272 uaf_rab.rab$b_rac = RAB$C_KEY;
4273 uaf_rab.rab$l_ubf = (char *)&retuaf;
4274 uaf_rab.rab$w_usz = sizeof retuaf;
4275 status = SYS$GET (&uaf_rab);
4276 if (!(status&1))
4277 {
4278 errno = EVMSERR;
4279 vaxc$errno = status;
4280 return 0;
4281 }
4282 /* close the User Authorization File */
4283 status = SYS$DISCONNECT (&uaf_rab);
4284 if (!(status&1))
4285 {
4286 errno = EVMSERR;
4287 vaxc$errno = status;
4288 return 0;
4289 }
4290 status = SYS$CLOSE (&uaf_fab);
4291 if (!(status&1))
4292 {
4293 errno = EVMSERR;
4294 vaxc$errno = status;
4295 return 0;
4296 }
4297 return &retuaf;
4298 }
4299
4300 struct UAF *
4301 get_uaf_uic (uic)
4302 unsigned long uic;
4303 {
4304 register status;
4305 struct FAB uaf_fab;
4306 struct RAB uaf_rab;
4307
4308 uaf_fab = cc$rms_fab;
4309 uaf_rab = cc$rms_rab;
4310 /* initialize fab fields */
4311 uaf_fab.fab$l_fna = "SYS$SYSTEM:SYSUAF.DAT";
4312 uaf_fab.fab$b_fns = 21;
4313 uaf_fab.fab$b_fac = FAB$M_GET;
4314 uaf_fab.fab$b_org = FAB$C_IDX;
4315 uaf_fab.fab$b_shr = FAB$M_GET|FAB$M_PUT|FAB$M_UPD|FAB$M_DEL;
4316 /* initialize rab fields */
4317 uaf_rab.rab$l_fab = &uaf_fab;
4318 /* open the User Authorization File */
4319 status = SYS$OPEN (&uaf_fab);
4320 if (!(status&1))
4321 {
4322 errno = EVMSERR;
4323 vaxc$errno = status;
4324 return 0;
4325 }
4326 status = SYS$CONNECT (&uaf_rab);
4327 if (!(status&1))
4328 {
4329 errno = EVMSERR;
4330 vaxc$errno = status;
4331 return 0;
4332 }
4333 /* read the requested record - index is in uic */
4334 uaf_rab.rab$b_krf = 1; /* 1st alternate key */
4335 uaf_rab.rab$l_kbf = (char *) &uic;
4336 uaf_rab.rab$b_ksz = sizeof uic;
4337 uaf_rab.rab$b_rac = RAB$C_KEY;
4338 uaf_rab.rab$l_ubf = (char *)&retuaf;
4339 uaf_rab.rab$w_usz = sizeof retuaf;
4340 status = SYS$GET (&uaf_rab);
4341 if (!(status&1))
4342 {
4343 errno = EVMSERR;
4344 vaxc$errno = status;
4345 return 0;
4346 }
4347 /* close the User Authorization File */
4348 status = SYS$DISCONNECT (&uaf_rab);
4349 if (!(status&1))
4350 {
4351 errno = EVMSERR;
4352 vaxc$errno = status;
4353 return 0;
4354 }
4355 status = SYS$CLOSE (&uaf_fab);
4356 if (!(status&1))
4357 {
4358 errno = EVMSERR;
4359 vaxc$errno = status;
4360 return 0;
4361 }
4362 return &retuaf;
4363 }
4364
4365 static struct passwd retpw;
4366
4367 struct passwd *
4368 cnv_uaf_pw (up)
4369 struct UAF * up;
4370 {
4371 char * ptr;
4372
4373 /* copy these out first because if the username is 32 chars, the next
4374 section will overwrite the first byte of the UIC */
4375 retpw.pw_uid = up->uaf$w_mem;
4376 retpw.pw_gid = up->uaf$w_grp;
4377
4378 /* I suppose this is not the best sytle, to possibly overwrite one
4379 byte beyond the end of the field, but what the heck... */
4380 ptr = &up->uaf$t_username[UAF$S_USERNAME];
4381 while (ptr[-1] == ' ')
4382 ptr--;
4383 *ptr = '\0';
4384 strcpy (retpw.pw_name, up->uaf$t_username);
4385
4386 /* the rest of these are counted ascii strings */
4387 strncpy (retpw.pw_gecos, &up->uaf$t_owner[1], up->uaf$t_owner[0]);
4388 retpw.pw_gecos[up->uaf$t_owner[0]] = '\0';
4389 strncpy (retpw.pw_dir, &up->uaf$t_defdev[1], up->uaf$t_defdev[0]);
4390 retpw.pw_dir[up->uaf$t_defdev[0]] = '\0';
4391 strncat (retpw.pw_dir, &up->uaf$t_defdir[1], up->uaf$t_defdir[0]);
4392 retpw.pw_dir[up->uaf$t_defdev[0] + up->uaf$t_defdir[0]] = '\0';
4393 strncpy (retpw.pw_shell, &up->uaf$t_defcli[1], up->uaf$t_defcli[0]);
4394 retpw.pw_shell[up->uaf$t_defcli[0]] = '\0';
4395
4396 return &retpw;
4397 }
4398 #else /* not READ_SYSUAF */
4399 static struct passwd retpw;
4400 #endif /* not READ_SYSUAF */
4401
4402 struct passwd *
4403 getpwnam (name)
4404 char * name;
4405 {
4406 #ifdef READ_SYSUAF
4407 struct UAF *up;
4408 #else
4409 char * user;
4410 char * dir;
4411 unsigned char * full;
4412 #endif /* READ_SYSUAF */
4413 char *ptr = name;
4414
4415 while (*ptr)
4416 {
4417 if ('a' <= *ptr && *ptr <= 'z')
4418 *ptr -= 040;
4419 ptr++;
4420 }
4421 #ifdef READ_SYSUAF
4422 if (!(up = get_uaf_name (name)))
4423 return 0;
4424 return cnv_uaf_pw (up);
4425 #else
4426 if (strcmp (name, getenv ("USER")) == 0)
4427 {
4428 retpw.pw_uid = getuid ();
4429 retpw.pw_gid = getgid ();
4430 strcpy (retpw.pw_name, name);
4431 if (full = egetenv ("FULLNAME"))
4432 strcpy (retpw.pw_gecos, full);
4433 else
4434 *retpw.pw_gecos = '\0';
4435 strcpy (retpw.pw_dir, egetenv ("HOME"));
4436 *retpw.pw_shell = '\0';
4437 return &retpw;
4438 }
4439 else
4440 return 0;
4441 #endif /* not READ_SYSUAF */
4442 }
4443
4444 struct passwd *
4445 getpwuid (uid)
4446 unsigned long uid;
4447 {
4448 #ifdef READ_SYSUAF
4449 struct UAF * up;
4450
4451 if (!(up = get_uaf_uic (uid)))
4452 return 0;
4453 return cnv_uaf_pw (up);
4454 #else
4455 if (uid == sys_getuid ())
4456 return getpwnam (egetenv ("USER"));
4457 else
4458 return 0;
4459 #endif /* not READ_SYSUAF */
4460 }
4461
4462 /* return total address space available to the current process. This is
4463 the sum of the current p0 size, p1 size and free page table entries
4464 available. */
4465 vlimit ()
4466 {
4467 int item_code;
4468 unsigned long free_pages;
4469 unsigned long frep0va;
4470 unsigned long frep1va;
4471 register status;
4472
4473 item_code = JPI$_FREPTECNT;
4474 if (((status = LIB$GETJPI (&item_code, 0, 0, &free_pages)) & 1) == 0)
4475 {
4476 errno = EVMSERR;
4477 vaxc$errno = status;
4478 return -1;
4479 }
4480 free_pages *= 512;
4481
4482 item_code = JPI$_FREP0VA;
4483 if (((status = LIB$GETJPI (&item_code, 0, 0, &frep0va)) & 1) == 0)
4484 {
4485 errno = EVMSERR;
4486 vaxc$errno = status;
4487 return -1;
4488 }
4489 item_code = JPI$_FREP1VA;
4490 if (((status = LIB$GETJPI (&item_code, 0, 0, &frep1va)) & 1) == 0)
4491 {
4492 errno = EVMSERR;
4493 vaxc$errno = status;
4494 return -1;
4495 }
4496
4497 return free_pages + frep0va + (0x7fffffff - frep1va);
4498 }
4499
4500 define_logical_name (varname, string)
4501 char *varname;
4502 char *string;
4503 {
4504 struct dsc$descriptor_s strdsc =
4505 {strlen (string), DSC$K_DTYPE_T, DSC$K_CLASS_S, string};
4506 struct dsc$descriptor_s envdsc =
4507 {strlen (varname), DSC$K_DTYPE_T, DSC$K_CLASS_S, varname};
4508 struct dsc$descriptor_s lnmdsc =
4509 {7, DSC$K_DTYPE_T, DSC$K_CLASS_S, "LNM$JOB"};
4510
4511 return LIB$SET_LOGICAL (&envdsc, &strdsc, &lnmdsc, 0, 0);
4512 }
4513
4514 delete_logical_name (varname)
4515 char *varname;
4516 {
4517 struct dsc$descriptor_s envdsc =
4518 {strlen (varname), DSC$K_DTYPE_T, DSC$K_CLASS_S, varname};
4519 struct dsc$descriptor_s lnmdsc =
4520 {7, DSC$K_DTYPE_T, DSC$K_CLASS_S, "LNM$JOB"};
4521
4522 return LIB$DELETE_LOGICAL (&envdsc, &lnmdsc);
4523 }
4524
4525 ulimit ()
4526 {}
4527
4528 setpgrp ()
4529 {}
4530
4531 execvp ()
4532 {
4533 error ("execvp system call not implemented");
4534 }
4535
4536 int
4537 rename (from, to)
4538 char *from, *to;
4539 {
4540 int status;
4541 struct FAB from_fab = cc$rms_fab, to_fab = cc$rms_fab;
4542 struct NAM from_nam = cc$rms_nam, to_nam = cc$rms_nam;
4543 char from_esn[NAM$C_MAXRSS];
4544 char to_esn[NAM$C_MAXRSS];
4545
4546 from_fab.fab$l_fna = from;
4547 from_fab.fab$b_fns = strlen (from);
4548 from_fab.fab$l_nam = &from_nam;
4549 from_fab.fab$l_fop = FAB$M_NAM;
4550
4551 from_nam.nam$l_esa = from_esn;
4552 from_nam.nam$b_ess = sizeof from_esn;
4553
4554 to_fab.fab$l_fna = to;
4555 to_fab.fab$b_fns = strlen (to);
4556 to_fab.fab$l_nam = &to_nam;
4557 to_fab.fab$l_fop = FAB$M_NAM;
4558
4559 to_nam.nam$l_esa = to_esn;
4560 to_nam.nam$b_ess = sizeof to_esn;
4561
4562 status = SYS$RENAME (&from_fab, 0, 0, &to_fab);
4563
4564 if (status & 1)
4565 return 0;
4566 else
4567 {
4568 if (status == RMS$_DEV)
4569 errno = EXDEV;
4570 else
4571 errno = EVMSERR;
4572 vaxc$errno = status;
4573 return -1;
4574 }
4575 }
4576
4577 /* This function renames a file like `rename', but it strips
4578 the version number from the "to" filename, such that the "to" file is
4579 will always be a new version. It also sets the file protection once it is
4580 finished. The protection that we will use is stored in fab_final_pro,
4581 and was set when we did a creat_copy_attrs to create the file that we
4582 are renaming.
4583
4584 We could use the chmod function, but Eunichs uses 3 bits per user category
4585 to describe the protection, and VMS uses 4 (write and delete are separate
4586 bits). To maintain portability, the VMS implementation of `chmod' wires
4587 the W and D bits together. */
4588
4589
4590 static struct fibdef fib; /* We need this initialized to zero */
4591 char vms_file_written[NAM$C_MAXRSS];
4592
4593 int
4594 rename_sans_version (from,to)
4595 char *from, *to;
4596 {
4597 short int chan;
4598 int stat;
4599 short int iosb[4];
4600 int status;
4601 struct FAB to_fab = cc$rms_fab;
4602 struct NAM to_nam = cc$rms_nam;
4603 struct dsc$descriptor fib_d ={sizeof (fib),0,0,(char*) &fib};
4604 struct dsc$descriptor fib_attr[2]
4605 = {{sizeof (fab_final_pro),ATR$C_FPRO,0,(char*) &fab_final_pro},{0,0,0,0}};
4606 char to_esn[NAM$C_MAXRSS];
4607
4608 $DESCRIPTOR (disk,to_esn);
4609
4610 to_fab.fab$l_fna = to;
4611 to_fab.fab$b_fns = strlen (to);
4612 to_fab.fab$l_nam = &to_nam;
4613 to_fab.fab$l_fop = FAB$M_NAM;
4614
4615 to_nam.nam$l_esa = to_esn;
4616 to_nam.nam$b_ess = sizeof to_esn;
4617
4618 status = SYS$PARSE (&to_fab, 0, 0); /* figure out the full file name */
4619
4620 if (to_nam.nam$l_fnb && NAM$M_EXP_VER)
4621 *(to_nam.nam$l_ver) = '\0';
4622
4623 stat = rename (from, to_esn);
4624 if (stat < 0)
4625 return stat;
4626
4627 strcpy (vms_file_written, to_esn);
4628
4629 to_fab.fab$l_fna = vms_file_written; /* this points to the versionless name */
4630 to_fab.fab$b_fns = strlen (vms_file_written);
4631
4632 /* Now set the file protection to the correct value */
4633 SYS$OPEN (&to_fab, 0, 0); /* This fills in the nam$w_fid fields */
4634
4635 /* Copy these fields into the fib */
4636 fib.fib$r_fid_overlay.fib$w_fid[0] = to_nam.nam$w_fid[0];
4637 fib.fib$r_fid_overlay.fib$w_fid[1] = to_nam.nam$w_fid[1];
4638 fib.fib$r_fid_overlay.fib$w_fid[2] = to_nam.nam$w_fid[2];
4639
4640 SYS$CLOSE (&to_fab, 0, 0);
4641
4642 stat = SYS$ASSIGN (&disk, &chan, 0, 0); /* open a channel to the disk */
4643 if (!stat)
4644 LIB$SIGNAL (stat);
4645 stat = SYS$QIOW (0, chan, IO$_MODIFY, iosb, 0, 0, &fib_d,
4646 0, 0, 0, &fib_attr, 0);
4647 if (!stat)
4648 LIB$SIGNAL (stat);
4649 stat = SYS$DASSGN (chan);
4650 if (!stat)
4651 LIB$SIGNAL (stat);
4652 strcpy (vms_file_written, to_esn); /* We will write this to the terminal*/
4653 return 0;
4654 }
4655
4656 link (file, new)
4657 char * file, * new;
4658 {
4659 register status;
4660 struct FAB fab;
4661 struct NAM nam;
4662 unsigned short fid[3];
4663 char esa[NAM$C_MAXRSS];
4664
4665 fab = cc$rms_fab;
4666 fab.fab$l_fop = FAB$M_OFP;
4667 fab.fab$l_fna = file;
4668 fab.fab$b_fns = strlen (file);
4669 fab.fab$l_nam = &nam;
4670
4671 nam = cc$rms_nam;
4672 nam.nam$l_esa = esa;
4673 nam.nam$b_ess = NAM$C_MAXRSS;
4674
4675 status = SYS$PARSE (&fab);
4676 if ((status & 1) == 0)
4677 {
4678 errno = EVMSERR;
4679 vaxc$errno = status;
4680 return -1;
4681 }
4682 status = SYS$SEARCH (&fab);
4683 if ((status & 1) == 0)
4684 {
4685 errno = EVMSERR;
4686 vaxc$errno = status;
4687 return -1;
4688 }
4689
4690 fid[0] = nam.nam$w_fid[0];
4691 fid[1] = nam.nam$w_fid[1];
4692 fid[2] = nam.nam$w_fid[2];
4693
4694 fab.fab$l_fna = new;
4695 fab.fab$b_fns = strlen (new);
4696
4697 status = SYS$PARSE (&fab);
4698 if ((status & 1) == 0)
4699 {
4700 errno = EVMSERR;
4701 vaxc$errno = status;
4702 return -1;
4703 }
4704
4705 nam.nam$w_fid[0] = fid[0];
4706 nam.nam$w_fid[1] = fid[1];
4707 nam.nam$w_fid[2] = fid[2];
4708
4709 nam.nam$l_esa = nam.nam$l_name;
4710 nam.nam$b_esl = nam.nam$b_name + nam.nam$b_type + nam.nam$b_ver;
4711
4712 status = SYS$ENTER (&fab);
4713 if ((status & 1) == 0)
4714 {
4715 errno = EVMSERR;
4716 vaxc$errno = status;
4717 return -1;
4718 }
4719
4720 return 0;
4721 }
4722
4723 croak (badfunc)
4724 char *badfunc;
4725 {
4726 printf ("%s not yet implemented\r\n", badfunc);
4727 reset_sys_modes ();
4728 exit (1);
4729 }
4730
4731 long
4732 random ()
4733 {
4734 /* Arrange to return a range centered on zero. */
4735 return rand () - (1 << 30);
4736 }
4737
4738 srandom (seed)
4739 {
4740 srand (seed);
4741 }
4742 #endif /* VMS */
4743 \f
4744 #ifdef AIX
4745
4746 /* Called from init_sys_modes. */
4747 hft_init ()
4748 {
4749 int junk;
4750
4751 /* If we're not on an HFT we shouldn't do any of this. We determine
4752 if we are on an HFT by trying to get an HFT error code. If this
4753 call fails, we're not on an HFT. */
4754 #ifdef IBMR2AIX
4755 if (ioctl (0, HFQERROR, &junk) < 0)
4756 return;
4757 #else /* not IBMR2AIX */
4758 if (ioctl (0, HFQEIO, 0) < 0)
4759 return;
4760 #endif /* not IBMR2AIX */
4761
4762 /* On AIX the default hft keyboard mapping uses backspace rather than delete
4763 as the rubout key's ASCII code. Here this is changed. The bug is that
4764 there's no way to determine the old mapping, so in reset_sys_modes
4765 we need to assume that the normal map had been present. Of course, this
4766 code also doesn't help if on a terminal emulator which doesn't understand
4767 HFT VTD's. */
4768 {
4769 struct hfbuf buf;
4770 struct hfkeymap keymap;
4771
4772 buf.hf_bufp = (char *)&keymap;
4773 buf.hf_buflen = sizeof (keymap);
4774 keymap.hf_nkeys = 2;
4775 keymap.hfkey[0].hf_kpos = 15;
4776 keymap.hfkey[0].hf_kstate = HFMAPCHAR | HFSHFNONE;
4777 #ifdef IBMR2AIX
4778 keymap.hfkey[0].hf_keyidh = '<';
4779 #else /* not IBMR2AIX */
4780 keymap.hfkey[0].hf_page = '<';
4781 #endif /* not IBMR2AIX */
4782 keymap.hfkey[0].hf_char = 127;
4783 keymap.hfkey[1].hf_kpos = 15;
4784 keymap.hfkey[1].hf_kstate = HFMAPCHAR | HFSHFSHFT;
4785 #ifdef IBMR2AIX
4786 keymap.hfkey[1].hf_keyidh = '<';
4787 #else /* not IBMR2AIX */
4788 keymap.hfkey[1].hf_page = '<';
4789 #endif /* not IBMR2AIX */
4790 keymap.hfkey[1].hf_char = 127;
4791 hftctl (0, HFSKBD, &buf);
4792 }
4793 /* The HFT system on AIX doesn't optimize for scrolling, so it's really ugly
4794 at times. */
4795 line_ins_del_ok = char_ins_del_ok = 0;
4796 }
4797
4798 /* Reset the rubout key to backspace. */
4799
4800 hft_reset ()
4801 {
4802 struct hfbuf buf;
4803 struct hfkeymap keymap;
4804 int junk;
4805
4806 #ifdef IBMR2AIX
4807 if (ioctl (0, HFQERROR, &junk) < 0)
4808 return;
4809 #else /* not IBMR2AIX */
4810 if (ioctl (0, HFQEIO, 0) < 0)
4811 return;
4812 #endif /* not IBMR2AIX */
4813
4814 buf.hf_bufp = (char *)&keymap;
4815 buf.hf_buflen = sizeof (keymap);
4816 keymap.hf_nkeys = 2;
4817 keymap.hfkey[0].hf_kpos = 15;
4818 keymap.hfkey[0].hf_kstate = HFMAPCHAR | HFSHFNONE;
4819 #ifdef IBMR2AIX
4820 keymap.hfkey[0].hf_keyidh = '<';
4821 #else /* not IBMR2AIX */
4822 keymap.hfkey[0].hf_page = '<';
4823 #endif /* not IBMR2AIX */
4824 keymap.hfkey[0].hf_char = 8;
4825 keymap.hfkey[1].hf_kpos = 15;
4826 keymap.hfkey[1].hf_kstate = HFMAPCHAR | HFSHFSHFT;
4827 #ifdef IBMR2AIX
4828 keymap.hfkey[1].hf_keyidh = '<';
4829 #else /* not IBMR2AIX */
4830 keymap.hfkey[1].hf_page = '<';
4831 #endif /* not IBMR2AIX */
4832 keymap.hfkey[1].hf_char = 8;
4833 hftctl (0, HFSKBD, &buf);
4834 }
4835
4836 #endif /* AIX */