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