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