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