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