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