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