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