comparison src/sysdep.c @ 0:376386a54a3c r19-14

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