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