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