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