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