*** empty log message ***
[emacs.git] / src / sysdep.c
blob5db1403c5397e8e5ceb63801db24bfb7357a5a12
1 /* Interfaces to system-dependent kernel and library entries.
2 Copyright (C) 1985, 86,87,88,93,94,95, 1999 Free Software Foundation, Inc.
4 This file is part of GNU Emacs.
6 GNU Emacs is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
9 any later version.
11 GNU Emacs is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with GNU Emacs; see the file COPYING. If not, write to
18 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19 Boston, MA 02111-1307, USA. */
22 #include <config.h>
23 #include <signal.h>
24 #include <setjmp.h>
26 #include "lisp.h"
27 #include "blockinput.h"
28 #undef NULL
30 #ifdef macintosh
31 #ifdef __MRC__
32 __sigfun sys_signal (int signal, __sigfun signal_func);
33 #elif __MWERKS__
34 __signal_func_ptr sys_signal (int signal, __signal_func_ptr signal_func);
35 #else
36 You lose!!!
37 #endif
38 #ifndef subprocesses
39 /* Nonzero means delete a process right away if it exits (process.c). */
40 static int delete_exited_processes;
41 #endif
42 #ifndef HAVE_X_WINDOWS
43 /* Search path for bitmap files (xfns.c). */
44 Lisp_Object Vx_bitmap_file_path;
45 #endif
46 #endif /* macintosh */
48 #define min(x,y) ((x) > (y) ? (y) : (x))
50 #ifdef WINDOWSNT
51 #define read sys_read
52 #define write sys_write
53 #include <windows.h>
54 extern int errno;
55 #endif /* not WINDOWSNT */
57 /* Does anyone other than VMS need this? */
58 #ifndef fwrite
59 #define sys_fwrite fwrite
60 #else
61 #undef fwrite
62 #endif
64 #ifndef HAVE_H_ERRNO
65 extern int h_errno;
66 #endif
68 #include <stdio.h>
69 #include <sys/types.h>
70 #include <sys/stat.h>
71 #include <errno.h>
73 /* Get _POSIX_VDISABLE, if it is available. */
74 #ifdef HAVE_UNISTD_H
75 #include <unistd.h>
76 #endif
78 /* Get SI_SRPC_DOMAIN, if it is available. */
79 #ifdef HAVE_SYS_SYSTEMINFO_H
80 #include <sys/systeminfo.h>
81 #endif
83 #ifdef MSDOS /* Demacs 1.1.2 91/10/20 Manabu Higashida, MW Aug 1993 */
84 #include <dos.h>
85 #include "dosfns.h"
86 #include "msdos.h"
87 #include <sys/param.h>
89 #if __DJGPP__ > 1
90 extern int etext;
91 extern unsigned start __asm__ ("start");
92 #endif
93 #endif
95 #ifndef errno
96 extern int errno;
97 #endif
99 #ifdef VMS
100 #include <rms.h>
101 #include <ttdef.h>
102 #include <tt2def.h>
103 #include <iodef.h>
104 #include <ssdef.h>
105 #include <descrip.h>
106 #include <fibdef.h>
107 #include <atrdef.h>
108 #include <ctype.h>
109 #include <string.h>
110 #ifdef __GNUC__
111 #include <sys/file.h>
112 #else
113 #include <file.h>
114 #endif
115 #undef F_SETFL
116 #ifndef RAB$C_BID
117 #include <rab.h>
118 #endif
119 #define MAXIOSIZE (32 * PAGESIZE) /* Don't I/O more than 32 blocks at a time */
120 #endif /* VMS */
122 #ifndef BSD4_1
123 #ifdef BSD_SYSTEM /* avoid writing defined (BSD_SYSTEM) || defined (USG)
124 because the vms compiler doesn't grok `defined' */
125 #include <fcntl.h>
126 #endif
127 #ifdef USG
128 #ifndef USG5
129 #include <fcntl.h>
130 #endif
131 #endif
132 #endif /* not 4.1 bsd */
134 #ifndef MSDOS
135 #include <sys/ioctl.h>
136 #endif
138 #include "systty.h"
139 #include "syswait.h"
141 #ifdef BROKEN_TIOCGWINSZ
142 #undef TIOCGWINSZ
143 #undef TIOCSWINSZ
144 #endif
146 #if defined (USG) || defined (DGUX)
147 #include <sys/utsname.h>
148 #include <string.h>
149 #ifndef MEMORY_IN_STRING_H
150 #include <memory.h>
151 #endif
152 #if defined (TIOCGWINSZ) || defined (ISC4_0)
153 #ifdef NEED_SIOCTL
154 #include <sys/sioctl.h>
155 #endif
156 #ifdef NEED_PTEM_H
157 #include <sys/stream.h>
158 #include <sys/ptem.h>
159 #endif
160 #endif /* TIOCGWINSZ or ISC4_0 */
161 #endif /* USG or DGUX */
163 extern int quit_char;
165 #include "frame.h"
166 #include "window.h"
167 #include "termhooks.h"
168 #include "termchar.h"
169 #include "termopts.h"
170 #include "dispextern.h"
171 #include "process.h"
173 #ifdef WINDOWSNT
174 #include <direct.h>
175 /* In process.h which conflicts with the local copy. */
176 #define _P_WAIT 0
177 int _CRTAPI1 _spawnlp (int, const char *, const char *, ...);
178 int _CRTAPI1 _getpid (void);
179 #endif
181 #ifdef NONSYSTEM_DIR_LIBRARY
182 #include "ndir.h"
183 #endif /* NONSYSTEM_DIR_LIBRARY */
185 #include "syssignal.h"
186 #include "systime.h"
187 #ifdef HAVE_UTIME_H
188 #include <utime.h>
189 #endif
191 #ifndef HAVE_UTIMES
192 #ifndef HAVE_STRUCT_UTIMBUF
193 /* We want to use utime rather than utimes, but we couldn't find the
194 structure declaration. We'll use the traditional one. */
195 struct utimbuf {
196 long actime;
197 long modtime;
199 #endif
200 #endif
202 #ifndef VFORK_RETURN_TYPE
203 #define VFORK_RETURN_TYPE int
204 #endif
206 /* LPASS8 is new in 4.3, and makes cbreak mode provide all 8 bits. */
207 #ifndef LPASS8
208 #define LPASS8 0
209 #endif
211 #ifdef BSD4_1
212 #define LNOFLSH 0100000
213 #endif
215 static int baud_convert[] =
216 #ifdef BAUD_CONVERT
217 BAUD_CONVERT;
218 #else
220 0, 50, 75, 110, 135, 150, 200, 300, 600, 1200,
221 1800, 2400, 4800, 9600, 19200, 38400
223 #endif
225 #if defined (HAVE_LIBNCURSES) && ! defined (NCURSES_OSPEED_T)
226 extern short ospeed;
227 #else
228 #if defined (HAVE_TERMIOS_H) && defined (LINUX)
229 #include <termios.h>
230 /* HJL's version of libc is said to need this on the Alpha.
231 On the other hand, DEC OSF1 on the Alpha needs ospeed to be a short. */
232 extern speed_t ospeed;
233 #else
234 extern short ospeed;
235 #endif
236 #endif
238 /* The file descriptor for Emacs's input terminal.
239 Under Unix, this is normally zero except when using X;
240 under VMS, we place the input channel number here. */
241 int input_fd;
243 void croak P_ ((char *));
245 #ifdef AIXHFT
246 void hft_init ();
247 void hft_reset ();
248 #endif
251 /* Specify a different file descriptor for further input operations. */
253 void
254 change_input_fd (fd)
255 int fd;
257 input_fd = fd;
260 /* Discard pending input on descriptor input_fd. */
262 void
263 discard_tty_input ()
265 #ifndef WINDOWSNT
266 struct emacs_tty buf;
268 if (noninteractive)
269 return;
271 /* Discarding input is not safe when the input could contain
272 replies from the X server. So don't do it. */
273 if (read_socket_hook)
274 return;
276 #ifdef VMS
277 end_kbd_input ();
278 SYS$QIOW (0, input_fd, IO$_READVBLK|IO$M_PURGE, input_iosb, 0, 0,
279 &buf.main, 0, 0, terminator_mask, 0, 0);
280 queue_kbd_input ();
281 #else /* not VMS */
282 #ifdef APOLLO
284 int zero = 0;
285 ioctl (input_fd, TIOCFLUSH, &zero);
287 #else /* not Apollo */
288 #ifdef MSDOS /* Demacs 1.1.1 91/10/16 HIRANO Satoshi */
289 while (dos_keyread () != -1)
291 #else /* not MSDOS */
292 EMACS_GET_TTY (input_fd, &buf);
293 EMACS_SET_TTY (input_fd, &buf, 0);
294 #endif /* not MSDOS */
295 #endif /* not Apollo */
296 #endif /* not VMS */
297 #endif /* not WINDOWSNT */
300 #ifdef SIGTSTP
302 /* Arrange for character C to be read as the next input from
303 the terminal. */
305 void
306 stuff_char (c)
307 char c;
309 if (read_socket_hook)
310 return;
312 /* Should perhaps error if in batch mode */
313 #ifdef TIOCSTI
314 ioctl (input_fd, TIOCSTI, &c);
315 #else /* no TIOCSTI */
316 error ("Cannot stuff terminal input characters in this version of Unix");
317 #endif /* no TIOCSTI */
320 #endif /* SIGTSTP */
322 void
323 init_baud_rate ()
325 if (noninteractive)
326 ospeed = 0;
327 else
329 #ifdef INIT_BAUD_RATE
330 INIT_BAUD_RATE ();
331 #else
332 #ifdef DOS_NT
333 ospeed = 15;
334 #else /* not DOS_NT */
335 #ifdef VMS
336 struct sensemode sg;
338 SYS$QIOW (0, input_fd, IO$_SENSEMODE, &sg, 0, 0,
339 &sg.class, 12, 0, 0, 0, 0 );
340 ospeed = sg.xmit_baud;
341 #else /* not VMS */
342 #ifdef HAVE_TERMIOS
343 struct termios sg;
345 sg.c_cflag = B9600;
346 tcgetattr (input_fd, &sg);
347 ospeed = cfgetospeed (&sg);
348 #if defined (USE_GETOBAUD) && defined (getobaud)
349 /* m88k-motorola-sysv3 needs this (ghazi@noc.rutgers.edu) 9/1/94. */
350 if (ospeed == 0)
351 ospeed = getobaud (sg.c_cflag);
352 #endif
353 #else /* neither VMS nor TERMIOS */
354 #ifdef HAVE_TERMIO
355 struct termio sg;
357 sg.c_cflag = B9600;
358 #ifdef HAVE_TCATTR
359 tcgetattr (input_fd, &sg);
360 #else
361 ioctl (input_fd, TCGETA, &sg);
362 #endif
363 ospeed = sg.c_cflag & CBAUD;
364 #else /* neither VMS nor TERMIOS nor TERMIO */
365 struct sgttyb sg;
367 sg.sg_ospeed = B9600;
368 if (ioctl (input_fd, TIOCGETP, &sg) < 0)
369 abort ();
370 ospeed = sg.sg_ospeed;
371 #endif /* not HAVE_TERMIO */
372 #endif /* not HAVE_TERMIOS */
373 #endif /* not VMS */
374 #endif /* not DOS_NT */
375 #endif /* not INIT_BAUD_RATE */
378 baud_rate = (ospeed < sizeof baud_convert / sizeof baud_convert[0]
379 ? baud_convert[ospeed] : 9600);
380 if (baud_rate == 0)
381 baud_rate = 1200;
384 /*ARGSUSED*/
385 void
386 set_exclusive_use (fd)
387 int fd;
389 #ifdef FIOCLEX
390 ioctl (fd, FIOCLEX, 0);
391 #endif
392 /* Ok to do nothing if this feature does not exist */
395 #ifndef subprocesses
397 wait_without_blocking ()
399 #ifdef BSD_SYSTEM
400 wait3 (0, WNOHANG | WUNTRACED, 0);
401 #else
402 croak ("wait_without_blocking");
403 #endif
404 synch_process_alive = 0;
407 #endif /* not subprocesses */
409 int wait_debugging; /* Set nonzero to make following function work under dbx
410 (at least for bsd). */
412 SIGTYPE
413 wait_for_termination_signal ()
416 /* Wait for subprocess with process id `pid' to terminate and
417 make sure it will get eliminated (not remain forever as a zombie) */
419 void
420 wait_for_termination (pid)
421 int pid;
423 while (1)
425 #ifdef subprocesses
426 #ifdef VMS
427 int status;
429 status = SYS$FORCEX (&pid, 0, 0);
430 break;
431 #else /* not VMS */
432 #if defined (BSD_SYSTEM) || (defined (HPUX) && !defined (HPUX_5))
433 /* Note that kill returns -1 even if the process is just a zombie now.
434 But inevitably a SIGCHLD interrupt should be generated
435 and child_sig will do wait3 and make the process go away. */
436 /* There is some indication that there is a bug involved with
437 termination of subprocesses, perhaps involving a kernel bug too,
438 but no idea what it is. Just as a hunch we signal SIGCHLD to see
439 if that causes the problem to go away or get worse. */
440 sigsetmask (sigmask (SIGCHLD));
441 if (0 > kill (pid, 0))
443 sigsetmask (SIGEMPTYMASK);
444 kill (getpid (), SIGCHLD);
445 break;
447 if (wait_debugging)
448 sleep (1);
449 else
450 sigpause (SIGEMPTYMASK);
451 #else /* not BSD_SYSTEM, and not HPUX version >= 6 */
452 #if defined (UNIPLUS)
453 if (0 > kill (pid, 0))
454 break;
455 wait (0);
456 #else /* neither BSD_SYSTEM nor UNIPLUS: random sysV */
457 #ifdef POSIX_SIGNALS /* would this work for LINUX as well? */
458 sigblock (sigmask (SIGCHLD));
459 if (0 > kill (pid, 0))
461 sigunblock (sigmask (SIGCHLD));
462 break;
464 sigpause (SIGEMPTYMASK);
465 #else /* not POSIX_SIGNALS */
466 #ifdef HAVE_SYSV_SIGPAUSE
467 sighold (SIGCHLD);
468 if (0 > kill (pid, 0))
470 sigrelse (SIGCHLD);
471 break;
473 sigpause (SIGCHLD);
474 #else /* not HAVE_SYSV_SIGPAUSE */
475 #ifdef WINDOWSNT
476 wait (0);
477 break;
478 #else /* not WINDOWSNT */
479 if (0 > kill (pid, 0))
480 break;
481 /* Using sleep instead of pause avoids timing error.
482 If the inferior dies just before the sleep,
483 we lose just one second. */
484 sleep (1);
485 #endif /* not WINDOWSNT */
486 #endif /* not HAVE_SYSV_SIGPAUSE */
487 #endif /* not POSIX_SIGNALS */
488 #endif /* not UNIPLUS */
489 #endif /* not BSD_SYSTEM, and not HPUX version >= 6 */
490 #endif /* not VMS */
491 #else /* not subprocesses */
492 #if __DJGPP__ > 1
493 break;
494 #else /* not __DJGPP__ > 1 */
495 #ifndef BSD4_1
496 if (kill (pid, 0) < 0)
497 break;
498 wait (0);
499 #else /* BSD4_1 */
500 int status;
501 status = wait (0);
502 if (status == pid || status == -1)
503 break;
504 #endif /* BSD4_1 */
505 #endif /* not __DJGPP__ > 1*/
506 #endif /* not subprocesses */
510 #ifdef subprocesses
513 * flush any pending output
514 * (may flush input as well; it does not matter the way we use it)
517 void
518 flush_pending_output (channel)
519 int channel;
521 #ifdef HAVE_TERMIOS
522 /* If we try this, we get hit with SIGTTIN, because
523 the child's tty belongs to the child's pgrp. */
524 #else
525 #ifdef TCFLSH
526 ioctl (channel, TCFLSH, 1);
527 #else
528 #ifdef TIOCFLUSH
529 int zero = 0;
530 /* 3rd arg should be ignored
531 but some 4.2 kernels actually want the address of an int
532 and nonzero means something different. */
533 ioctl (channel, TIOCFLUSH, &zero);
534 #endif
535 #endif
536 #endif
539 #ifndef VMS
540 /* Set up the terminal at the other end of a pseudo-terminal that
541 we will be controlling an inferior through.
542 It should not echo or do line-editing, since that is done
543 in Emacs. No padding needed for insertion into an Emacs buffer. */
545 void
546 child_setup_tty (out)
547 int out;
549 #ifndef DOS_NT
550 struct emacs_tty s;
552 EMACS_GET_TTY (out, &s);
554 #if defined (HAVE_TERMIO) || defined (HAVE_TERMIOS)
555 s.main.c_oflag |= OPOST; /* Enable output postprocessing */
556 s.main.c_oflag &= ~ONLCR; /* Disable map of NL to CR-NL on output */
557 #ifdef NLDLY
558 s.main.c_oflag &= ~(NLDLY|CRDLY|TABDLY|BSDLY|VTDLY|FFDLY);
559 /* No output delays */
560 #endif
561 s.main.c_lflag &= ~ECHO; /* Disable echo */
562 s.main.c_lflag |= ISIG; /* Enable signals */
563 #ifdef IUCLC
564 s.main.c_iflag &= ~IUCLC; /* Disable downcasing on input. */
565 #endif
566 #ifdef ISTRIP
567 s.main.c_iflag &= ~ISTRIP; /* don't strip 8th bit on input */
568 #endif
569 #ifdef OLCUC
570 s.main.c_oflag &= ~OLCUC; /* Disable upcasing on output. */
571 #endif
572 s.main.c_oflag &= ~TAB3; /* Disable tab expansion */
573 s.main.c_cflag = (s.main.c_cflag & ~CSIZE) | CS8; /* Don't strip 8th bit */
574 #if 0
575 /* Said to be unnecessary: */
576 s.main.c_cc[VMIN] = 1; /* minimum number of characters to accept */
577 s.main.c_cc[VTIME] = 0; /* wait forever for at least 1 character */
578 #endif
580 s.main.c_lflag |= ICANON; /* Enable erase/kill and eof processing */
581 s.main.c_cc[VEOF] = 04; /* insure that EOF is Control-D */
582 s.main.c_cc[VERASE] = CDISABLE; /* disable erase processing */
583 s.main.c_cc[VKILL] = CDISABLE; /* disable kill processing */
585 #ifdef HPUX
586 s.main.c_cflag = (s.main.c_cflag & ~CBAUD) | B9600; /* baud rate sanity */
587 #endif /* HPUX */
589 #ifdef AIX
590 /* AIX enhanced edit loses NULs, so disable it */
591 #ifndef IBMR2AIX
592 s.main.c_line = 0;
593 s.main.c_iflag &= ~ASCEDIT;
594 #endif
595 /* Also, PTY overloads NUL and BREAK.
596 don't ignore break, but don't signal either, so it looks like NUL. */
597 s.main.c_iflag &= ~IGNBRK;
598 s.main.c_iflag &= ~BRKINT;
599 /* QUIT and INTR work better as signals, so disable character forms */
600 s.main.c_cc[VINTR] = 0377;
601 #ifdef SIGNALS_VIA_CHARACTERS
602 /* the QUIT and INTR character are used in process_send_signal
603 so set them here to something useful. */
604 if (s.main.c_cc[VQUIT] == 0377)
605 s.main.c_cc[VQUIT] = '\\'&037; /* Control-\ */
606 if (s.main.c_cc[VINTR] == 0377)
607 s.main.c_cc[VINTR] = 'C'&037; /* Control-C */
608 #else /* no TIOCGPGRP or no TIOCGLTC or no TIOCGETC */
609 /* QUIT and INTR work better as signals, so disable character forms */
610 s.main.c_cc[VQUIT] = 0377;
611 s.main.c_cc[VINTR] = 0377;
612 s.main.c_lflag &= ~ISIG;
613 #endif /* no TIOCGPGRP or no TIOCGLTC or no TIOCGETC */
614 s.main.c_cc[VEOL] = 0377;
615 s.main.c_cflag = (s.main.c_cflag & ~CBAUD) | B9600; /* baud rate sanity */
616 #endif /* AIX */
618 #else /* not HAVE_TERMIO */
620 s.main.sg_flags &= ~(ECHO | CRMOD | ANYP | ALLDELAY | RAW | LCASE
621 | CBREAK | TANDEM);
622 s.main.sg_flags |= LPASS8;
623 s.main.sg_erase = 0377;
624 s.main.sg_kill = 0377;
625 s.lmode = LLITOUT | s.lmode; /* Don't strip 8th bit */
627 #endif /* not HAVE_TERMIO */
629 EMACS_SET_TTY (out, &s, 0);
631 #ifdef BSD4_1
632 if (interrupt_input)
633 reset_sigio ();
634 #endif /* BSD4_1 */
635 #ifdef RTU
637 int zero = 0;
638 ioctl (out, FIOASYNC, &zero);
640 #endif /* RTU */
641 #endif /* not DOS_NT */
643 #endif /* not VMS */
645 #endif /* subprocesses */
647 /* Record a signal code and the handler for it. */
648 struct save_signal
650 int code;
651 SIGTYPE (*handler) P_ ((int));
654 static void save_signal_handlers P_ ((struct save_signal *));
655 static void restore_signal_handlers P_ ((struct save_signal *));
657 /* Suspend the Emacs process; give terminal to its superior. */
659 void
660 sys_suspend ()
662 #ifdef VMS
663 /* "Foster" parentage allows emacs to return to a subprocess that attached
664 to the current emacs as a cheaper than starting a whole new process. This
665 is set up by KEPTEDITOR.COM. */
666 unsigned long parent_id, foster_parent_id;
667 char *fpid_string;
669 fpid_string = getenv ("EMACS_PARENT_PID");
670 if (fpid_string != NULL)
672 sscanf (fpid_string, "%x", &foster_parent_id);
673 if (foster_parent_id != 0)
674 parent_id = foster_parent_id;
675 else
676 parent_id = getppid ();
678 else
679 parent_id = getppid ();
681 xfree (fpid_string); /* On VMS, this was malloc'd */
683 if (parent_id && parent_id != 0xffffffff)
685 SIGTYPE (*oldsig)() = (int) signal (SIGINT, SIG_IGN);
686 int status = LIB$ATTACH (&parent_id) & 1;
687 signal (SIGINT, oldsig);
688 return status;
690 else
692 struct {
693 int l;
694 char *a;
695 } d_prompt;
696 d_prompt.l = sizeof ("Emacs: "); /* Our special prompt */
697 d_prompt.a = "Emacs: "; /* Just a reminder */
698 LIB$SPAWN (0, 0, 0, 0, 0, 0, 0, 0, 0, 0, &d_prompt, 0);
699 return 1;
701 return -1;
702 #else
703 #if defined (SIGTSTP) && !defined (MSDOS)
706 int pgrp = EMACS_GETPGRP (0);
707 EMACS_KILLPG (pgrp, SIGTSTP);
710 #else /* No SIGTSTP */
711 #ifdef USG_JOBCTRL /* If you don't know what this is don't mess with it */
712 ptrace (0, 0, 0, 0); /* set for ptrace - caught by csh */
713 kill (getpid (), SIGQUIT);
715 #else /* No SIGTSTP or USG_JOBCTRL */
717 /* On a system where suspending is not implemented,
718 instead fork a subshell and let it talk directly to the terminal
719 while we wait. */
720 sys_subshell ();
722 #endif /* no USG_JOBCTRL */
723 #endif /* no SIGTSTP */
724 #endif /* not VMS */
727 /* Fork a subshell. */
729 void
730 sys_subshell ()
732 #ifdef macintosh
733 error ("Can't spawn subshell");
734 #else
735 #ifndef VMS
736 #ifdef DOS_NT /* Demacs 1.1.2 91/10/20 Manabu Higashida */
737 int st;
738 char oldwd[MAXPATHLEN+1]; /* Fixed length is safe on MSDOS. */
739 #endif
740 int pid;
741 struct save_signal saved_handlers[5];
742 Lisp_Object dir;
743 unsigned char *str = 0;
744 int len;
746 saved_handlers[0].code = SIGINT;
747 saved_handlers[1].code = SIGQUIT;
748 saved_handlers[2].code = SIGTERM;
749 #ifdef SIGIO
750 saved_handlers[3].code = SIGIO;
751 saved_handlers[4].code = 0;
752 #else
753 saved_handlers[3].code = 0;
754 #endif
756 /* Mentioning current_buffer->buffer would mean including buffer.h,
757 which somehow wedges the hp compiler. So instead... */
759 dir = intern ("default-directory");
760 if (NILP (Fboundp (dir)))
761 goto xyzzy;
762 dir = Fsymbol_value (dir);
763 if (!STRINGP (dir))
764 goto xyzzy;
766 dir = expand_and_dir_to_file (Funhandled_file_name_directory (dir), Qnil);
767 str = (unsigned char *) alloca (XSTRING (dir)->size + 2);
768 len = XSTRING (dir)->size;
769 bcopy (XSTRING (dir)->data, str, len);
770 if (str[len - 1] != '/') str[len++] = '/';
771 str[len] = 0;
772 xyzzy:
774 #ifdef DOS_NT
775 pid = 0;
776 #if __DJGPP__ > 1
777 save_signal_handlers (saved_handlers);
778 synch_process_alive = 1;
779 #endif /* __DJGPP__ > 1 */
780 #else
781 pid = vfork ();
782 if (pid == -1)
783 error ("Can't spawn subshell");
784 #endif
786 if (pid == 0)
788 char *sh = 0;
790 #ifdef DOS_NT /* MW, Aug 1993 */
791 getwd (oldwd);
792 if (sh == 0)
793 sh = (char *) egetenv ("SUSPEND"); /* KFS, 1994-12-14 */
794 #endif
795 if (sh == 0)
796 sh = (char *) egetenv ("SHELL");
797 if (sh == 0)
798 sh = "sh";
800 /* Use our buffer's default directory for the subshell. */
801 if (str)
802 chdir ((char *) str);
804 #ifdef subprocesses
805 close_process_descs (); /* Close Emacs's pipes/ptys */
806 #endif
808 #ifdef SET_EMACS_PRIORITY
810 extern int emacs_priority;
812 if (emacs_priority < 0)
813 nice (-emacs_priority);
815 #endif
817 #ifdef MSDOS /* Demacs 1.1.2 91/10/20 Manabu Higashida */
818 st = system (sh);
819 chdir (oldwd);
820 #if 0 /* This is also reported if last command executed in subshell failed, KFS */
821 if (st)
822 report_file_error ("Can't execute subshell", Fcons (build_string (sh), Qnil));
823 #endif
824 #else /* not MSDOS */
825 #ifdef WINDOWSNT
826 /* Waits for process completion */
827 pid = _spawnlp (_P_WAIT, sh, sh, NULL);
828 chdir (oldwd);
829 if (pid == -1)
830 write (1, "Can't execute subshell", 22);
831 #else /* not WINDOWSNT */
832 execlp (sh, sh, 0);
833 write (1, "Can't execute subshell", 22);
834 _exit (1);
835 #endif /* not WINDOWSNT */
836 #endif /* not MSDOS */
839 /* Do this now if we did not do it before. */
840 #if !defined (MSDOS) || __DJGPP__ == 1
841 save_signal_handlers (saved_handlers);
842 synch_process_alive = 1;
843 #endif
845 #ifndef DOS_NT
846 wait_for_termination (pid);
847 #endif
848 restore_signal_handlers (saved_handlers);
849 synch_process_alive = 0;
850 #endif /* !VMS */
851 #endif /* !macintosh */
854 static void
855 save_signal_handlers (saved_handlers)
856 struct save_signal *saved_handlers;
858 while (saved_handlers->code)
860 saved_handlers->handler
861 = (SIGTYPE (*) P_ ((int))) signal (saved_handlers->code, SIG_IGN);
862 saved_handlers++;
866 static void
867 restore_signal_handlers (saved_handlers)
868 struct save_signal *saved_handlers;
870 while (saved_handlers->code)
872 signal (saved_handlers->code, saved_handlers->handler);
873 saved_handlers++;
877 #ifdef F_SETFL
879 int old_fcntl_flags;
881 void
882 init_sigio (fd)
883 int fd;
885 #ifdef FASYNC
886 old_fcntl_flags = fcntl (fd, F_GETFL, 0) & ~FASYNC;
887 fcntl (fd, F_SETFL, old_fcntl_flags | FASYNC);
888 #endif
889 interrupts_deferred = 0;
892 void
893 reset_sigio ()
895 unrequest_sigio ();
898 #ifdef FASYNC /* F_SETFL does not imply existence of FASYNC */
900 void
901 request_sigio ()
903 if (read_socket_hook)
904 return;
906 #ifdef SIGWINCH
907 sigunblock (sigmask (SIGWINCH));
908 #endif
909 fcntl (input_fd, F_SETFL, old_fcntl_flags | FASYNC);
911 interrupts_deferred = 0;
914 void
915 unrequest_sigio ()
917 if (read_socket_hook)
918 return;
920 #ifdef SIGWINCH
921 sigblock (sigmask (SIGWINCH));
922 #endif
923 fcntl (input_fd, F_SETFL, old_fcntl_flags);
924 interrupts_deferred = 1;
927 #else /* no FASYNC */
928 #ifdef STRIDE /* Stride doesn't have FASYNC - use FIOASYNC */
930 void
931 request_sigio ()
933 int on = 1;
935 if (read_socket_hook)
936 return;
938 ioctl (input_fd, FIOASYNC, &on);
939 interrupts_deferred = 0;
942 void
943 unrequest_sigio ()
945 int off = 0;
947 if (read_socket_hook)
948 return;
950 ioctl (input_fd, FIOASYNC, &off);
951 interrupts_deferred = 1;
954 #else /* not FASYNC, not STRIDE */
956 #ifdef _CX_UX
958 #include <termios.h>
960 void
961 request_sigio ()
963 int on = 1;
964 sigset_t st;
966 if (read_socket_hook)
967 return;
969 sigemptyset (&st);
970 sigaddset (&st, SIGIO);
971 ioctl (input_fd, FIOASYNC, &on);
972 interrupts_deferred = 0;
973 sigprocmask (SIG_UNBLOCK, &st, (sigset_t *)0);
976 void
977 unrequest_sigio ()
979 int off = 0;
981 if (read_socket_hook)
982 return;
984 ioctl (input_fd, FIOASYNC, &off);
985 interrupts_deferred = 1;
988 #else /* ! _CX_UX */
990 void
991 request_sigio ()
993 if (read_socket_hook)
994 return;
996 croak ("request_sigio");
999 void
1000 unrequest_sigio ()
1002 if (read_socket_hook)
1003 return;
1005 croak ("unrequest_sigio");
1008 #endif /* _CX_UX */
1009 #endif /* STRIDE */
1010 #endif /* FASYNC */
1011 #endif /* F_SETFL */
1013 /* Saving and restoring the process group of Emacs's terminal. */
1015 #ifdef BSD_PGRPS
1017 /* The process group of which Emacs was a member when it initially
1018 started.
1020 If Emacs was in its own process group (i.e. inherited_pgroup ==
1021 getpid ()), then we know we're running under a shell with job
1022 control (Emacs would never be run as part of a pipeline).
1023 Everything is fine.
1025 If Emacs was not in its own process group, then we know we're
1026 running under a shell (or a caller) that doesn't know how to
1027 separate itself from Emacs (like sh). Emacs must be in its own
1028 process group in order to receive SIGIO correctly. In this
1029 situation, we put ourselves in our own pgroup, forcibly set the
1030 tty's pgroup to our pgroup, and make sure to restore and reinstate
1031 the tty's pgroup just like any other terminal setting. If
1032 inherited_group was not the tty's pgroup, then we'll get a
1033 SIGTTmumble when we try to change the tty's pgroup, and a CONT if
1034 it goes foreground in the future, which is what should happen. */
1035 int inherited_pgroup;
1037 /* Split off the foreground process group to Emacs alone.
1038 When we are in the foreground, but not started in our own process
1039 group, redirect the TTY to point to our own process group. We need
1040 to be in our own process group to receive SIGIO properly. */
1041 void
1042 narrow_foreground_group ()
1044 int me = getpid ();
1046 setpgrp (0, inherited_pgroup);
1047 if (inherited_pgroup != me)
1048 EMACS_SET_TTY_PGRP (input_fd, &me);
1049 setpgrp (0, me);
1052 /* Set the tty to our original foreground group. */
1053 void
1054 widen_foreground_group ()
1056 if (inherited_pgroup != getpid ())
1057 EMACS_SET_TTY_PGRP (input_fd, &inherited_pgroup);
1058 setpgrp (0, inherited_pgroup);
1061 #endif /* BSD_PGRPS */
1063 /* Getting and setting emacs_tty structures. */
1065 /* Set *TC to the parameters associated with the terminal FD.
1066 Return zero if all's well, or -1 if we ran into an error we
1067 couldn't deal with. */
1069 emacs_get_tty (fd, settings)
1070 int fd;
1071 struct emacs_tty *settings;
1073 /* Retrieve the primary parameters - baud rate, character size, etcetera. */
1074 #ifdef HAVE_TCATTR
1075 /* We have those nifty POSIX tcmumbleattr functions. */
1076 bzero (&settings->main, sizeof (settings->main));
1077 if (tcgetattr (fd, &settings->main) < 0)
1078 return -1;
1080 #else
1081 #ifdef HAVE_TERMIO
1082 /* The SYSV-style interface? */
1083 if (ioctl (fd, TCGETA, &settings->main) < 0)
1084 return -1;
1086 #else
1087 #ifdef VMS
1088 /* Vehemently Monstrous System? :-) */
1089 if (! (SYS$QIOW (0, fd, IO$_SENSEMODE, settings, 0, 0,
1090 &settings->main.class, 12, 0, 0, 0, 0)
1091 & 1))
1092 return -1;
1094 #else
1095 #ifndef DOS_NT
1096 /* I give up - I hope you have the BSD ioctls. */
1097 if (ioctl (fd, TIOCGETP, &settings->main) < 0)
1098 return -1;
1099 #endif /* not DOS_NT */
1100 #endif
1101 #endif
1102 #endif
1104 /* Suivant - Do we have to get struct ltchars data? */
1105 #ifdef HAVE_LTCHARS
1106 if (ioctl (fd, TIOCGLTC, &settings->ltchars) < 0)
1107 return -1;
1108 #endif
1110 /* How about a struct tchars and a wordful of lmode bits? */
1111 #ifdef HAVE_TCHARS
1112 if (ioctl (fd, TIOCGETC, &settings->tchars) < 0
1113 || ioctl (fd, TIOCLGET, &settings->lmode) < 0)
1114 return -1;
1115 #endif
1117 /* We have survived the tempest. */
1118 return 0;
1122 /* Set the parameters of the tty on FD according to the contents of
1123 *SETTINGS. If FLUSHP is non-zero, we discard input.
1124 Return 0 if all went well, and -1 if anything failed. */
1127 emacs_set_tty (fd, settings, flushp)
1128 int fd;
1129 struct emacs_tty *settings;
1130 int flushp;
1132 /* Set the primary parameters - baud rate, character size, etcetera. */
1133 #ifdef HAVE_TCATTR
1134 int i;
1135 /* We have those nifty POSIX tcmumbleattr functions.
1136 William J. Smith <wjs@wiis.wang.com> writes:
1137 "POSIX 1003.1 defines tcsetattr to return success if it was
1138 able to perform any of the requested actions, even if some
1139 of the requested actions could not be performed.
1140 We must read settings back to ensure tty setup properly.
1141 AIX requires this to keep tty from hanging occasionally." */
1142 /* This make sure that we don't loop indefinitely in here. */
1143 for (i = 0 ; i < 10 ; i++)
1144 if (tcsetattr (fd, flushp ? TCSAFLUSH : TCSADRAIN, &settings->main) < 0)
1146 if (errno == EINTR)
1147 continue;
1148 else
1149 return -1;
1151 else
1153 struct termios new;
1155 bzero (&new, sizeof (new));
1156 /* Get the current settings, and see if they're what we asked for. */
1157 tcgetattr (fd, &new);
1158 /* We cannot use memcmp on the whole structure here because under
1159 * aix386 the termios structure has some reserved field that may
1160 * not be filled in.
1162 if ( new.c_iflag == settings->main.c_iflag
1163 && new.c_oflag == settings->main.c_oflag
1164 && new.c_cflag == settings->main.c_cflag
1165 && new.c_lflag == settings->main.c_lflag
1166 && memcmp (new.c_cc, settings->main.c_cc, NCCS) == 0)
1167 break;
1168 else
1169 continue;
1172 #else
1173 #ifdef HAVE_TERMIO
1174 /* The SYSV-style interface? */
1175 if (ioctl (fd, flushp ? TCSETAF : TCSETAW, &settings->main) < 0)
1176 return -1;
1178 #else
1179 #ifdef VMS
1180 /* Vehemently Monstrous System? :-) */
1181 if (! (SYS$QIOW (0, fd, IO$_SETMODE, &input_iosb, 0, 0,
1182 &settings->main.class, 12, 0, 0, 0, 0)
1183 & 1))
1184 return -1;
1186 #else
1187 #ifndef DOS_NT
1188 /* I give up - I hope you have the BSD ioctls. */
1189 if (ioctl (fd, (flushp) ? TIOCSETP : TIOCSETN, &settings->main) < 0)
1190 return -1;
1191 #endif /* not DOS_NT */
1193 #endif
1194 #endif
1195 #endif
1197 /* Suivant - Do we have to get struct ltchars data? */
1198 #ifdef HAVE_LTCHARS
1199 if (ioctl (fd, TIOCSLTC, &settings->ltchars) < 0)
1200 return -1;
1201 #endif
1203 /* How about a struct tchars and a wordful of lmode bits? */
1204 #ifdef HAVE_TCHARS
1205 if (ioctl (fd, TIOCSETC, &settings->tchars) < 0
1206 || ioctl (fd, TIOCLSET, &settings->lmode) < 0)
1207 return -1;
1208 #endif
1210 /* We have survived the tempest. */
1211 return 0;
1215 /* The initial tty mode bits */
1216 struct emacs_tty old_tty;
1218 /* 1 if we have been through init_sys_modes. */
1219 int term_initted;
1221 /* 1 if outer tty status has been recorded. */
1222 int old_tty_valid;
1224 #ifdef BSD4_1
1225 /* BSD 4.1 needs to keep track of the lmode bits in order to start
1226 sigio. */
1227 int lmode;
1228 #endif
1230 #ifndef F_SETOWN_BUG
1231 #ifdef F_SETOWN
1232 int old_fcntl_owner;
1233 #endif /* F_SETOWN */
1234 #endif /* F_SETOWN_BUG */
1236 /* This may also be defined in stdio,
1237 but if so, this does no harm,
1238 and using the same name avoids wasting the other one's space. */
1240 #ifdef nec_ews_svr4
1241 extern char *_sobuf ;
1242 #else
1243 #if defined (USG) || defined (DGUX)
1244 unsigned char _sobuf[BUFSIZ+8];
1245 #else
1246 char _sobuf[BUFSIZ];
1247 #endif
1248 #endif
1250 #ifdef HAVE_LTCHARS
1251 static struct ltchars new_ltchars = {-1,-1,-1,-1,-1,-1};
1252 #endif
1253 #ifdef HAVE_TCHARS
1254 static struct tchars new_tchars = {-1,-1,-1,-1,-1,-1};
1255 #endif
1257 void
1258 init_sys_modes ()
1260 struct emacs_tty tty;
1262 #ifdef macintosh
1263 Vwindow_system = intern ("mac");
1264 Vwindow_system_version = make_number (1);
1266 /* cus-start.el complains if delete-exited-processes and x-bitmap-file-path not defined */
1267 #ifndef subprocesses
1268 DEFVAR_BOOL ("delete-exited-processes", &delete_exited_processes,
1269 "*Non-nil means delete processes immediately when they exit.\n\
1270 nil means don't delete them until `list-processes' is run.");
1271 delete_exited_processes = 0;
1272 #endif
1274 #ifndef HAVE_X_WINDOWS
1275 DEFVAR_LISP ("x-bitmap-file-path", &Vx_bitmap_file_path,
1276 "List of directories to search for bitmap files for X.");
1277 Vx_bitmap_file_path = decode_env_path ((char *) 0, ".");
1278 #endif
1280 #endif /* not macintosh */
1282 #ifdef VMS
1283 #if 0
1284 static int oob_chars[2] = {0, 1 << 7}; /* catch C-g's */
1285 extern int (*interrupt_signal) ();
1286 #endif
1287 #endif
1289 Vtty_erase_char = Qnil;
1291 if (noninteractive)
1292 return;
1294 #ifdef VMS
1295 if (!input_ef)
1296 input_ef = get_kbd_event_flag ();
1297 /* LIB$GET_EF (&input_ef); */
1298 SYS$CLREF (input_ef);
1299 waiting_for_ast = 0;
1300 if (!timer_ef)
1301 timer_ef = get_timer_event_flag ();
1302 /* LIB$GET_EF (&timer_ef); */
1303 SYS$CLREF (timer_ef);
1304 #if 0
1305 if (!process_ef)
1307 LIB$GET_EF (&process_ef);
1308 SYS$CLREF (process_ef);
1310 if (input_ef / 32 != process_ef / 32)
1311 croak ("Input and process event flags in different clusters.");
1312 #endif
1313 if (input_ef / 32 != timer_ef / 32)
1314 croak ("Input and timer event flags in different clusters.");
1315 #if 0
1316 input_eflist = ((unsigned) 1 << (input_ef % 32)) |
1317 ((unsigned) 1 << (process_ef % 32));
1318 #endif
1319 timer_eflist = ((unsigned) 1 << (input_ef % 32)) |
1320 ((unsigned) 1 << (timer_ef % 32));
1321 #ifndef VMS4_4
1322 sys_access_reinit ();
1323 #endif
1324 #endif /* not VMS */
1326 #ifdef BSD_PGRPS
1327 if (! read_socket_hook && EQ (Vwindow_system, Qnil))
1328 narrow_foreground_group ();
1329 #endif
1331 #ifdef HAVE_WINDOW_SYSTEM
1332 /* Emacs' window system on MSDOG uses the `internal terminal' and therefore
1333 needs the initialization code below. */
1334 if (!read_socket_hook && EQ (Vwindow_system, Qnil))
1335 #endif
1337 EMACS_GET_TTY (input_fd, &old_tty);
1339 old_tty_valid = 1;
1341 tty = old_tty;
1343 #if defined (HAVE_TERMIO) || defined (HAVE_TERMIOS)
1344 XSETINT (Vtty_erase_char, old_tty.main.c_cc[VERASE]);
1346 #ifdef DGUX
1347 /* This allows meta to be sent on 8th bit. */
1348 tty.main.c_iflag &= ~INPCK; /* don't check input for parity */
1349 #endif
1350 tty.main.c_iflag |= (IGNBRK); /* Ignore break condition */
1351 tty.main.c_iflag &= ~ICRNL; /* Disable map of CR to NL on input */
1352 #ifdef INLCR /* I'm just being cautious,
1353 since I can't check how widespread INLCR is--rms. */
1354 tty.main.c_iflag &= ~INLCR; /* Disable map of NL to CR on input */
1355 #endif
1356 #ifdef ISTRIP
1357 tty.main.c_iflag &= ~ISTRIP; /* don't strip 8th bit on input */
1358 #endif
1359 tty.main.c_lflag &= ~ECHO; /* Disable echo */
1360 tty.main.c_lflag &= ~ICANON; /* Disable erase/kill processing */
1361 #ifdef IEXTEN
1362 tty.main.c_lflag &= ~IEXTEN; /* Disable other editing characters. */
1363 #endif
1364 tty.main.c_lflag |= ISIG; /* Enable signals */
1365 if (flow_control)
1367 tty.main.c_iflag |= IXON; /* Enable start/stop output control */
1368 #ifdef IXANY
1369 tty.main.c_iflag &= ~IXANY;
1370 #endif /* IXANY */
1372 else
1373 tty.main.c_iflag &= ~IXON; /* Disable start/stop output control */
1374 tty.main.c_oflag &= ~ONLCR; /* Disable map of NL to CR-NL
1375 on output */
1376 tty.main.c_oflag &= ~TAB3; /* Disable tab expansion */
1377 #ifdef CS8
1378 if (meta_key)
1380 tty.main.c_cflag |= CS8; /* allow 8th bit on input */
1381 tty.main.c_cflag &= ~PARENB;/* Don't check parity */
1383 #endif
1384 tty.main.c_cc[VINTR] = quit_char; /* C-g (usually) gives SIGINT */
1385 /* Set up C-g for both SIGQUIT and SIGINT.
1386 We don't know which we will get, but we handle both alike
1387 so which one it really gives us does not matter. */
1388 tty.main.c_cc[VQUIT] = quit_char;
1389 tty.main.c_cc[VMIN] = 1; /* Input should wait for at least 1 char */
1390 tty.main.c_cc[VTIME] = 0; /* no matter how long that takes. */
1391 #ifdef VSWTCH
1392 tty.main.c_cc[VSWTCH] = CDISABLE; /* Turn off shell layering use
1393 of C-z */
1394 #endif /* VSWTCH */
1396 #if defined (mips) || defined (HAVE_TCATTR)
1397 #ifdef VSUSP
1398 tty.main.c_cc[VSUSP] = CDISABLE; /* Turn off mips handling of C-z. */
1399 #endif /* VSUSP */
1400 #ifdef V_DSUSP
1401 tty.main.c_cc[V_DSUSP] = CDISABLE; /* Turn off mips handling of C-y. */
1402 #endif /* V_DSUSP */
1403 #ifdef VDSUSP /* Some systems have VDSUSP, some have V_DSUSP. */
1404 tty.main.c_cc[VDSUSP] = CDISABLE;
1405 #endif /* VDSUSP */
1406 #ifdef VLNEXT
1407 tty.main.c_cc[VLNEXT] = CDISABLE;
1408 #endif /* VLNEXT */
1409 #ifdef VREPRINT
1410 tty.main.c_cc[VREPRINT] = CDISABLE;
1411 #endif /* VREPRINT */
1412 #ifdef VWERASE
1413 tty.main.c_cc[VWERASE] = CDISABLE;
1414 #endif /* VWERASE */
1415 #ifdef VDISCARD
1416 tty.main.c_cc[VDISCARD] = CDISABLE;
1417 #endif /* VDISCARD */
1419 if (flow_control)
1421 #ifdef VSTART
1422 tty.main.c_cc[VSTART] = '\021';
1423 #endif /* VSTART */
1424 #ifdef VSTOP
1425 tty.main.c_cc[VSTOP] = '\023';
1426 #endif /* VSTOP */
1428 else
1430 #ifdef VSTART
1431 tty.main.c_cc[VSTART] = CDISABLE;
1432 #endif /* VSTART */
1433 #ifdef VSTOP
1434 tty.main.c_cc[VSTOP] = CDISABLE;
1435 #endif /* VSTOP */
1437 #endif /* mips or HAVE_TCATTR */
1439 #ifdef SET_LINE_DISCIPLINE
1440 /* Need to explicitly request TERMIODISC line discipline or
1441 Ultrix's termios does not work correctly. */
1442 tty.main.c_line = SET_LINE_DISCIPLINE;
1443 #endif
1444 #ifdef AIX
1445 #ifndef IBMR2AIX
1446 /* AIX enhanced edit loses NULs, so disable it. */
1447 tty.main.c_line = 0;
1448 tty.main.c_iflag &= ~ASCEDIT;
1449 #else
1450 tty.main.c_cc[VSTRT] = 255;
1451 tty.main.c_cc[VSTOP] = 255;
1452 tty.main.c_cc[VSUSP] = 255;
1453 tty.main.c_cc[VDSUSP] = 255;
1454 #endif /* IBMR2AIX */
1455 if (flow_control)
1457 #ifdef VSTART
1458 tty.main.c_cc[VSTART] = '\021';
1459 #endif /* VSTART */
1460 #ifdef VSTOP
1461 tty.main.c_cc[VSTOP] = '\023';
1462 #endif /* VSTOP */
1464 /* Also, PTY overloads NUL and BREAK.
1465 don't ignore break, but don't signal either, so it looks like NUL.
1466 This really serves a purpose only if running in an XTERM window
1467 or via TELNET or the like, but does no harm elsewhere. */
1468 tty.main.c_iflag &= ~IGNBRK;
1469 tty.main.c_iflag &= ~BRKINT;
1470 #endif
1471 #else /* if not HAVE_TERMIO */
1472 #ifdef VMS
1473 tty.main.tt_char |= TT$M_NOECHO;
1474 if (meta_key)
1475 tty.main.tt_char |= TT$M_EIGHTBIT;
1476 if (flow_control)
1477 tty.main.tt_char |= TT$M_TTSYNC;
1478 else
1479 tty.main.tt_char &= ~TT$M_TTSYNC;
1480 tty.main.tt2_char |= TT2$M_PASTHRU | TT2$M_XON;
1481 #else /* not VMS (BSD, that is) */
1482 #ifndef DOS_NT
1483 XSETINT (Vtty_erase_char, tty.main.sg_erase);
1484 tty.main.sg_flags &= ~(ECHO | CRMOD | XTABS);
1485 if (meta_key)
1486 tty.main.sg_flags |= ANYP;
1487 tty.main.sg_flags |= interrupt_input ? RAW : CBREAK;
1488 #endif /* not DOS_NT */
1489 #endif /* not VMS (BSD, that is) */
1490 #endif /* not HAVE_TERMIO */
1492 /* If going to use CBREAK mode, we must request C-g to interrupt
1493 and turn off start and stop chars, etc. If not going to use
1494 CBREAK mode, do this anyway so as to turn off local flow
1495 control for user coming over network on 4.2; in this case,
1496 only t_stopc and t_startc really matter. */
1497 #ifndef HAVE_TERMIO
1498 #ifdef HAVE_TCHARS
1499 /* Note: if not using CBREAK mode, it makes no difference how we
1500 set this */
1501 tty.tchars = new_tchars;
1502 tty.tchars.t_intrc = quit_char;
1503 if (flow_control)
1505 tty.tchars.t_startc = '\021';
1506 tty.tchars.t_stopc = '\023';
1509 tty.lmode = LDECCTQ | LLITOUT | LPASS8 | LNOFLSH | old_tty.lmode;
1510 #ifdef ultrix
1511 /* Under Ultrix 4.2a, leaving this out doesn't seem to hurt
1512 anything, and leaving it in breaks the meta key. Go figure. */
1513 tty.lmode &= ~LLITOUT;
1514 #endif
1516 #ifdef BSD4_1
1517 lmode = tty.lmode;
1518 #endif
1520 #endif /* HAVE_TCHARS */
1521 #endif /* not HAVE_TERMIO */
1523 #ifdef HAVE_LTCHARS
1524 tty.ltchars = new_ltchars;
1525 #endif /* HAVE_LTCHARS */
1526 #ifdef MSDOS /* Demacs 1.1.2 91/10/20 Manabu Higashida, MW Aug 1993 */
1527 if (!term_initted)
1528 internal_terminal_init ();
1529 dos_ttraw ();
1530 #endif
1532 EMACS_SET_TTY (input_fd, &tty, 0);
1534 /* This code added to insure that, if flow-control is not to be used,
1535 we have an unlocked terminal at the start. */
1537 #ifdef TCXONC
1538 if (!flow_control) ioctl (input_fd, TCXONC, 1);
1539 #endif
1540 #ifndef APOLLO
1541 #ifdef TIOCSTART
1542 if (!flow_control) ioctl (input_fd, TIOCSTART, 0);
1543 #endif
1544 #endif
1546 #if defined (HAVE_TERMIOS) || defined (HPUX9)
1547 #ifdef TCOON
1548 if (!flow_control) tcflow (input_fd, TCOON);
1549 #endif
1550 #endif
1552 #ifdef AIXHFT
1553 hft_init ();
1554 #ifdef IBMR2AIX
1556 /* IBM's HFT device usually thinks a ^J should be LF/CR. We need it
1557 to be only LF. This is the way that is done. */
1558 struct termio tty;
1560 if (ioctl (1, HFTGETID, &tty) != -1)
1561 write (1, "\033[20l", 5);
1563 #endif
1564 #endif /* AIXHFT */
1566 #ifdef VMS
1567 /* Appears to do nothing when in PASTHRU mode.
1568 SYS$QIOW (0, input_fd, IO$_SETMODE|IO$M_OUTBAND, 0, 0, 0,
1569 interrupt_signal, oob_chars, 0, 0, 0, 0);
1571 queue_kbd_input (0);
1572 #endif /* VMS */
1575 #ifdef F_SETFL
1576 #ifndef F_SETOWN_BUG
1577 #ifdef F_GETOWN /* F_SETFL does not imply existence of F_GETOWN */
1578 if (interrupt_input
1579 && ! read_socket_hook && EQ (Vwindow_system, Qnil))
1581 old_fcntl_owner = fcntl (input_fd, F_GETOWN, 0);
1582 fcntl (input_fd, F_SETOWN, getpid ());
1583 init_sigio (input_fd);
1585 #endif /* F_GETOWN */
1586 #endif /* F_SETOWN_BUG */
1587 #endif /* F_SETFL */
1589 #ifdef BSD4_1
1590 if (interrupt_input)
1591 init_sigio (input_fd);
1592 #endif
1594 #ifdef VMS /* VMS sometimes has this symbol but lacks setvbuf. */
1595 #undef _IOFBF
1596 #endif
1597 #ifdef _IOFBF
1598 /* This symbol is defined on recent USG systems.
1599 Someone says without this call USG won't really buffer the file
1600 even with a call to setbuf. */
1601 setvbuf (stdout, (char *) _sobuf, _IOFBF, sizeof _sobuf);
1602 #else
1603 setbuf (stdout, (char *) _sobuf);
1604 #endif
1605 #ifdef HAVE_WINDOW_SYSTEM
1606 /* Emacs' window system on MSDOG uses the `internal terminal' and therefore
1607 needs the initialization code below. */
1608 if (EQ (Vwindow_system, Qnil)
1609 #ifndef WINDOWSNT
1610 /* When running in tty mode on NT/Win95, we have a read_socket
1611 hook, but still need the rest of the initialization code below. */
1612 && (! read_socket_hook)
1613 #endif
1615 #endif
1616 set_terminal_modes ();
1618 if (!term_initted
1619 && FRAMEP (Vterminal_frame)
1620 && FRAME_TERMCAP_P (XFRAME (Vterminal_frame)))
1621 init_frame_faces (XFRAME (Vterminal_frame));
1623 if (term_initted && no_redraw_on_reenter)
1625 if (display_completed)
1626 direct_output_forward_char (0);
1628 else
1630 frame_garbaged = 1;
1631 if (FRAMEP (Vterminal_frame))
1632 FRAME_GARBAGED_P (XFRAME (Vterminal_frame)) = 1;
1635 term_initted = 1;
1638 /* Return nonzero if safe to use tabs in output.
1639 At the time this is called, init_sys_modes has not been done yet. */
1642 tabs_safe_p ()
1644 struct emacs_tty tty;
1646 EMACS_GET_TTY (input_fd, &tty);
1647 return EMACS_TTY_TABS_OK (&tty);
1650 /* Get terminal size from system.
1651 Store number of lines into *HEIGHTP and width into *WIDTHP.
1652 We store 0 if there's no valid information. */
1654 void
1655 get_frame_size (widthp, heightp)
1656 int *widthp, *heightp;
1659 #ifdef TIOCGWINSZ
1661 /* BSD-style. */
1662 struct winsize size;
1664 if (ioctl (input_fd, TIOCGWINSZ, &size) == -1)
1665 *widthp = *heightp = 0;
1666 else
1668 *widthp = size.ws_col;
1669 *heightp = size.ws_row;
1672 #else
1673 #ifdef TIOCGSIZE
1675 /* SunOS - style. */
1676 struct ttysize size;
1678 if (ioctl (input_fd, TIOCGSIZE, &size) == -1)
1679 *widthp = *heightp = 0;
1680 else
1682 *widthp = size.ts_cols;
1683 *heightp = size.ts_lines;
1686 #else
1687 #ifdef VMS
1689 struct sensemode tty;
1691 SYS$QIOW (0, input_fd, IO$_SENSEMODE, &tty, 0, 0,
1692 &tty.class, 12, 0, 0, 0, 0);
1693 *widthp = tty.scr_wid;
1694 *heightp = tty.scr_len;
1696 #else
1697 #ifdef MSDOS
1698 *widthp = ScreenCols ();
1699 *heightp = ScreenRows ();
1700 #else /* system doesn't know size */
1701 *widthp = 0;
1702 *heightp = 0;
1703 #endif
1705 #endif /* not VMS */
1706 #endif /* not SunOS-style */
1707 #endif /* not BSD-style */
1710 /* Set the logical window size associated with descriptor FD
1711 to HEIGHT and WIDTH. This is used mainly with ptys. */
1714 set_window_size (fd, height, width)
1715 int fd, height, width;
1717 #ifdef TIOCSWINSZ
1719 /* BSD-style. */
1720 struct winsize size;
1721 size.ws_row = height;
1722 size.ws_col = width;
1724 if (ioctl (fd, TIOCSWINSZ, &size) == -1)
1725 return 0; /* error */
1726 else
1727 return 1;
1729 #else
1730 #ifdef TIOCSSIZE
1732 /* SunOS - style. */
1733 struct ttysize size;
1734 size.ts_lines = height;
1735 size.ts_cols = width;
1737 if (ioctl (fd, TIOCGSIZE, &size) == -1)
1738 return 0;
1739 else
1740 return 1;
1741 #else
1742 return -1;
1743 #endif /* not SunOS-style */
1744 #endif /* not BSD-style */
1748 /* Prepare the terminal for exiting Emacs; move the cursor to the
1749 bottom of the frame, turn off interrupt-driven I/O, etc. */
1750 void
1751 reset_sys_modes ()
1753 struct frame *sf;
1755 if (noninteractive)
1757 fflush (stdout);
1758 return;
1760 if (!term_initted)
1761 return;
1762 #ifdef HAVE_WINDOW_SYSTEM
1763 /* Emacs' window system on MSDOG uses the `internal terminal' and therefore
1764 needs the clean-up code below. */
1765 if (!EQ (Vwindow_system, Qnil)
1766 #ifndef WINDOWSNT
1767 /* When running in tty mode on NT/Win95, we have a read_socket
1768 hook, but still need the rest of the clean-up code below. */
1769 || read_socket_hook
1770 #endif
1772 return;
1773 #endif
1774 sf = SELECTED_FRAME ();
1775 cursor_to (FRAME_HEIGHT (sf) - 1, 0);
1776 clear_end_of_line (FRAME_WIDTH (sf));
1777 /* clear_end_of_line may move the cursor */
1778 cursor_to (FRAME_HEIGHT (sf) - 1, 0);
1779 #if defined (IBMR2AIX) && defined (AIXHFT)
1781 /* HFT devices normally use ^J as a LF/CR. We forced it to
1782 do the LF only. Now, we need to reset it. */
1783 struct termio tty;
1785 if (ioctl (1, HFTGETID, &tty) != -1)
1786 write (1, "\033[20h", 5);
1788 #endif
1790 reset_terminal_modes ();
1791 fflush (stdout);
1792 #ifdef BSD_SYSTEM
1793 #ifndef BSD4_1
1794 /* Avoid possible loss of output when changing terminal modes. */
1795 fsync (fileno (stdout));
1796 #endif
1797 #endif
1799 #ifdef F_SETFL
1800 #ifndef F_SETOWN_BUG
1801 #ifdef F_SETOWN /* F_SETFL does not imply existence of F_SETOWN */
1802 if (interrupt_input)
1804 reset_sigio ();
1805 fcntl (input_fd, F_SETOWN, old_fcntl_owner);
1807 #endif /* F_SETOWN */
1808 #endif /* F_SETOWN_BUG */
1809 #ifdef O_NDELAY
1810 fcntl (input_fd, F_SETFL, fcntl (input_fd, F_GETFL, 0) & ~O_NDELAY);
1811 #endif
1812 #endif /* F_SETFL */
1813 #ifdef BSD4_1
1814 if (interrupt_input)
1815 reset_sigio ();
1816 #endif /* BSD4_1 */
1818 if (old_tty_valid)
1819 while (EMACS_SET_TTY (input_fd, &old_tty, 0) < 0 && errno == EINTR)
1822 #ifdef MSDOS /* Demacs 1.1.2 91/10/20 Manabu Higashida */
1823 dos_ttcooked ();
1824 #endif
1826 #ifdef SET_LINE_DISCIPLINE
1827 /* Ultrix's termios *ignores* any line discipline except TERMIODISC.
1828 A different old line discipline is therefore not restored, yet.
1829 Restore the old line discipline by hand. */
1830 ioctl (0, TIOCSETD, &old_tty.main.c_line);
1831 #endif
1833 #ifdef AIXHFT
1834 hft_reset ();
1835 #endif
1837 #ifdef BSD_PGRPS
1838 widen_foreground_group ();
1839 #endif
1842 #ifdef HAVE_PTYS
1844 /* Set up the proper status flags for use of a pty. */
1846 void
1847 setup_pty (fd)
1848 int fd;
1850 /* I'm told that TOICREMOTE does not mean control chars
1851 "can't be sent" but rather that they don't have
1852 input-editing or signaling effects.
1853 That should be good, because we have other ways
1854 to do those things in Emacs.
1855 However, telnet mode seems not to work on 4.2.
1856 So TIOCREMOTE is turned off now. */
1858 /* Under hp-ux, if TIOCREMOTE is turned on, some calls
1859 will hang. In particular, the "timeout" feature (which
1860 causes a read to return if there is no data available)
1861 does this. Also it is known that telnet mode will hang
1862 in such a way that Emacs must be stopped (perhaps this
1863 is the same problem).
1865 If TIOCREMOTE is turned off, then there is a bug in
1866 hp-ux which sometimes loses data. Apparently the
1867 code which blocks the master process when the internal
1868 buffer fills up does not work. Other than this,
1869 though, everything else seems to work fine.
1871 Since the latter lossage is more benign, we may as well
1872 lose that way. -- cph */
1873 #ifdef FIONBIO
1874 #ifdef SYSV_PTYS
1876 int on = 1;
1877 ioctl (fd, FIONBIO, &on);
1879 #endif
1880 #endif
1881 #ifdef IBMRTAIX
1882 /* On AIX, the parent gets SIGHUP when a pty attached child dies. So, we */
1883 /* ignore SIGHUP once we've started a child on a pty. Note that this may */
1884 /* cause EMACS not to die when it should, i.e., when its own controlling */
1885 /* tty goes away. I've complained to the AIX developers, and they may */
1886 /* change this behavior, but I'm not going to hold my breath. */
1887 signal (SIGHUP, SIG_IGN);
1888 #endif
1890 #endif /* HAVE_PTYS */
1892 #ifdef VMS
1894 /* Assigning an input channel is done at the start of Emacs execution.
1895 This is called each time Emacs is resumed, also, but does nothing
1896 because input_chain is no longer zero. */
1898 void
1899 init_vms_input ()
1901 int status;
1903 if (input_fd == 0)
1905 status = SYS$ASSIGN (&input_dsc, &input_fd, 0, 0);
1906 if (! (status & 1))
1907 LIB$STOP (status);
1911 /* Deassigning the input channel is done before exiting. */
1913 void
1914 stop_vms_input ()
1916 return SYS$DASSGN (input_fd);
1919 short input_buffer;
1921 /* Request reading one character into the keyboard buffer.
1922 This is done as soon as the buffer becomes empty. */
1924 void
1925 queue_kbd_input ()
1927 int status;
1928 extern kbd_input_ast ();
1930 waiting_for_ast = 0;
1931 stop_input = 0;
1932 status = SYS$QIO (0, input_fd, IO$_READVBLK,
1933 &input_iosb, kbd_input_ast, 1,
1934 &input_buffer, 1, 0, terminator_mask, 0, 0);
1937 int input_count;
1939 /* Ast routine that is called when keyboard input comes in
1940 in accord with the SYS$QIO above. */
1942 void
1943 kbd_input_ast ()
1945 register int c = -1;
1946 int old_errno = errno;
1947 extern EMACS_TIME *input_available_clear_time;
1949 if (waiting_for_ast)
1950 SYS$SETEF (input_ef);
1951 waiting_for_ast = 0;
1952 input_count++;
1953 #ifdef ASTDEBUG
1954 if (input_count == 25)
1955 exit (1);
1956 printf ("Ast # %d,", input_count);
1957 printf (" iosb = %x, %x, %x, %x",
1958 input_iosb.offset, input_iosb.status, input_iosb.termlen,
1959 input_iosb.term);
1960 #endif
1961 if (input_iosb.offset)
1963 c = input_buffer;
1964 #ifdef ASTDEBUG
1965 printf (", char = 0%o", c);
1966 #endif
1968 #ifdef ASTDEBUG
1969 printf ("\n");
1970 fflush (stdout);
1971 sleep (1);
1972 #endif
1973 if (! stop_input)
1974 queue_kbd_input ();
1975 if (c >= 0)
1977 struct input_event e;
1978 e.kind = ascii_keystroke;
1979 XSETINT (e.code, c);
1980 e.frame_or_window = selected_frame;
1981 kbd_buffer_store_event (&e);
1983 if (input_available_clear_time)
1984 EMACS_SET_SECS_USECS (*input_available_clear_time, 0, 0);
1985 errno = old_errno;
1988 /* Wait until there is something in kbd_buffer. */
1990 void
1991 wait_for_kbd_input ()
1993 extern int have_process_input, process_exited;
1995 /* If already something, avoid doing system calls. */
1996 if (detect_input_pending ())
1998 return;
2000 /* Clear a flag, and tell ast routine above to set it. */
2001 SYS$CLREF (input_ef);
2002 waiting_for_ast = 1;
2003 /* Check for timing error: ast happened while we were doing that. */
2004 if (!detect_input_pending ())
2006 /* No timing error: wait for flag to be set. */
2007 set_waiting_for_input (0);
2008 SYS$WFLOR (input_ef, input_eflist);
2009 clear_waiting_for_input (0);
2010 if (!detect_input_pending ())
2011 /* Check for subprocess input availability */
2013 int dsp = have_process_input || process_exited;
2015 SYS$CLREF (process_ef);
2016 if (have_process_input)
2017 process_command_input ();
2018 if (process_exited)
2019 process_exit ();
2020 if (dsp)
2022 update_mode_lines++;
2023 prepare_menu_bars ();
2024 redisplay_preserve_echo_area ();
2028 waiting_for_ast = 0;
2031 /* Get rid of any pending QIO, when we are about to suspend
2032 or when we want to throw away pending input.
2033 We wait for a positive sign that the AST routine has run
2034 and therefore there is no I/O request queued when we return.
2035 SYS$SETAST is used to avoid a timing error. */
2037 void
2038 end_kbd_input ()
2040 #ifdef ASTDEBUG
2041 printf ("At end_kbd_input.\n");
2042 fflush (stdout);
2043 sleep (1);
2044 #endif
2045 if (LIB$AST_IN_PROG ()) /* Don't wait if suspending from kbd_buffer_store_event! */
2047 SYS$CANCEL (input_fd);
2048 return;
2051 SYS$SETAST (0);
2052 /* Clear a flag, and tell ast routine above to set it. */
2053 SYS$CLREF (input_ef);
2054 waiting_for_ast = 1;
2055 stop_input = 1;
2056 SYS$CANCEL (input_fd);
2057 SYS$SETAST (1);
2058 SYS$WAITFR (input_ef);
2059 waiting_for_ast = 0;
2062 /* Wait for either input available or time interval expiry. */
2064 void
2065 input_wait_timeout (timeval)
2066 int timeval; /* Time to wait, in seconds */
2068 int time [2];
2069 static int zero = 0;
2070 static int large = -10000000;
2072 LIB$EMUL (&timeval, &large, &zero, time); /* Convert to VMS format */
2074 /* If already something, avoid doing system calls. */
2075 if (detect_input_pending ())
2077 return;
2079 /* Clear a flag, and tell ast routine above to set it. */
2080 SYS$CLREF (input_ef);
2081 waiting_for_ast = 1;
2082 /* Check for timing error: ast happened while we were doing that. */
2083 if (!detect_input_pending ())
2085 /* No timing error: wait for flag to be set. */
2086 SYS$CANTIM (1, 0);
2087 if (SYS$SETIMR (timer_ef, time, 0, 1) & 1) /* Set timer */
2088 SYS$WFLOR (timer_ef, timer_eflist); /* Wait for timer expiry or input */
2090 waiting_for_ast = 0;
2093 /* The standard `sleep' routine works some other way
2094 and it stops working if you have ever quit out of it.
2095 This one continues to work. */
2097 sys_sleep (timeval)
2098 int timeval;
2100 int time [2];
2101 static int zero = 0;
2102 static int large = -10000000;
2104 LIB$EMUL (&timeval, &large, &zero, time); /* Convert to VMS format */
2106 SYS$CANTIM (1, 0);
2107 if (SYS$SETIMR (timer_ef, time, 0, 1) & 1) /* Set timer */
2108 SYS$WAITFR (timer_ef); /* Wait for timer expiry only */
2111 void
2112 init_sigio (fd)
2113 int fd;
2115 request_sigio ();
2118 reset_sigio ()
2120 unrequest_sigio ();
2123 void
2124 request_sigio ()
2126 croak ("request sigio");
2129 void
2130 unrequest_sigio ()
2132 croak ("unrequest sigio");
2135 #endif /* VMS */
2137 /* Note that VMS compiler won't accept defined (CANNOT_DUMP). */
2138 #ifndef CANNOT_DUMP
2139 #define NEED_STARTS
2140 #endif
2142 #ifndef SYSTEM_MALLOC
2143 #ifndef NEED_STARTS
2144 #define NEED_STARTS
2145 #endif
2146 #endif
2148 #ifdef NEED_STARTS
2149 /* Some systems that cannot dump also cannot implement these. */
2152 * Return the address of the start of the text segment prior to
2153 * doing an unexec. After unexec the return value is undefined.
2154 * See crt0.c for further explanation and _start.
2158 #if !(defined (__NetBSD__) && defined (__ELF__))
2159 #ifndef HAVE_TEXT_START
2160 char *
2161 start_of_text ()
2163 #ifdef TEXT_START
2164 return ((char *) TEXT_START);
2165 #else
2166 #ifdef GOULD
2167 extern csrt ();
2168 return ((char *) csrt);
2169 #else /* not GOULD */
2170 extern int _start ();
2171 return ((char *) _start);
2172 #endif /* GOULD */
2173 #endif /* TEXT_START */
2175 #endif /* not HAVE_TEXT_START */
2176 #endif
2179 * Return the address of the start of the data segment prior to
2180 * doing an unexec. After unexec the return value is undefined.
2181 * See crt0.c for further information and definition of data_start.
2183 * Apparently, on BSD systems this is etext at startup. On
2184 * USG systems (swapping) this is highly mmu dependent and
2185 * is also dependent on whether or not the program is running
2186 * with shared text. Generally there is a (possibly large)
2187 * gap between end of text and start of data with shared text.
2189 * On Uniplus+ systems with shared text, data starts at a
2190 * fixed address. Each port (from a given oem) is generally
2191 * different, and the specific value of the start of data can
2192 * be obtained via the UniPlus+ specific "uvar" system call,
2193 * however the method outlined in crt0.c seems to be more portable.
2195 * Probably what will have to happen when a USG unexec is available,
2196 * at least on UniPlus, is temacs will have to be made unshared so
2197 * that text and data are contiguous. Then once loadup is complete,
2198 * unexec will produce a shared executable where the data can be
2199 * at the normal shared text boundary and the startofdata variable
2200 * will be patched by unexec to the correct value.
2204 char *
2205 start_of_data ()
2207 #ifdef DATA_START
2208 return ((char *) DATA_START);
2209 #else
2210 #ifdef ORDINARY_LINK
2212 * This is a hack. Since we're not linking crt0.c or pre_crt0.c,
2213 * data_start isn't defined. We take the address of environ, which
2214 * is known to live at or near the start of the system crt0.c, and
2215 * we don't sweat the handful of bytes that might lose.
2217 extern char **environ;
2219 return ((char *) &environ);
2220 #else
2221 extern int data_start;
2222 return ((char *) &data_start);
2223 #endif /* ORDINARY_LINK */
2224 #endif /* DATA_START */
2226 #endif /* NEED_STARTS (not CANNOT_DUMP or not SYSTEM_MALLOC) */
2228 #ifndef CANNOT_DUMP
2229 /* Some systems that cannot dump also cannot implement these. */
2232 * Return the address of the end of the text segment prior to
2233 * doing an unexec. After unexec the return value is undefined.
2236 char *
2237 end_of_text ()
2239 #ifdef TEXT_END
2240 return ((char *) TEXT_END);
2241 #else
2242 extern int etext;
2243 return ((char *) &etext);
2244 #endif
2248 * Return the address of the end of the data segment prior to
2249 * doing an unexec. After unexec the return value is undefined.
2252 char *
2253 end_of_data ()
2255 #ifdef DATA_END
2256 return ((char *) DATA_END);
2257 #else
2258 extern int edata;
2259 return ((char *) &edata);
2260 #endif
2263 #endif /* not CANNOT_DUMP */
2265 /* init_system_name sets up the string for the Lisp function
2266 system-name to return. */
2268 #ifdef BSD4_1
2269 #include <whoami.h>
2270 #endif
2272 extern Lisp_Object Vsystem_name;
2274 #ifndef BSD4_1
2275 #ifndef VMS
2276 #ifdef HAVE_SOCKETS
2277 #include <sys/socket.h>
2278 #include <netdb.h>
2279 #endif /* HAVE_SOCKETS */
2280 #endif /* not VMS */
2281 #endif /* not BSD4_1 */
2283 void
2284 init_system_name ()
2286 #ifdef BSD4_1
2287 Vsystem_name = build_string (sysname);
2288 #else
2289 #ifdef VMS
2290 char *sp, *end;
2291 if ((sp = egetenv ("SYS$NODE")) == 0)
2292 Vsystem_name = build_string ("vax-vms");
2293 else if ((end = index (sp, ':')) == 0)
2294 Vsystem_name = build_string (sp);
2295 else
2296 Vsystem_name = make_string (sp, end - sp);
2297 #else
2298 #ifndef HAVE_GETHOSTNAME
2299 struct utsname uts;
2300 uname (&uts);
2301 Vsystem_name = build_string (uts.nodename);
2302 #else /* HAVE_GETHOSTNAME */
2303 unsigned int hostname_size = 256;
2304 char *hostname = (char *) alloca (hostname_size);
2306 /* Try to get the host name; if the buffer is too short, try
2307 again. Apparently, the only indication gethostname gives of
2308 whether the buffer was large enough is the presence or absence
2309 of a '\0' in the string. Eech. */
2310 for (;;)
2312 gethostname (hostname, hostname_size - 1);
2313 hostname[hostname_size - 1] = '\0';
2315 /* Was the buffer large enough for the '\0'? */
2316 if (strlen (hostname) < hostname_size - 1)
2317 break;
2319 hostname_size <<= 1;
2320 hostname = (char *) alloca (hostname_size);
2322 #ifdef HAVE_SOCKETS
2323 /* Turn the hostname into the official, fully-qualified hostname.
2324 Don't do this if we're going to dump; this can confuse system
2325 libraries on some machines and make the dumped emacs core dump. */
2326 #ifndef CANNOT_DUMP
2327 if (initialized)
2328 #endif /* not CANNOT_DUMP */
2329 if (! index (hostname, '.'))
2331 struct hostent *hp;
2332 int count;
2333 for (count = 0;; count++)
2335 #ifdef TRY_AGAIN
2336 h_errno = 0;
2337 #endif
2338 hp = gethostbyname (hostname);
2339 #ifdef TRY_AGAIN
2340 if (! (hp == 0 && h_errno == TRY_AGAIN))
2341 #endif
2342 break;
2343 if (count >= 5)
2344 break;
2345 Fsleep_for (make_number (1), Qnil);
2347 if (hp)
2349 char *fqdn = (char *) hp->h_name;
2350 char *p;
2352 if (!index (fqdn, '.'))
2354 /* We still don't have a fully qualified domain name.
2355 Try to find one in the list of alternate names */
2356 char **alias = hp->h_aliases;
2357 while (*alias && !index (*alias, '.'))
2358 alias++;
2359 if (*alias)
2360 fqdn = *alias;
2362 hostname = fqdn;
2363 #if 0
2364 /* Convert the host name to lower case. */
2365 /* Using ctype.h here would introduce a possible locale
2366 dependence that is probably wrong for hostnames. */
2367 p = hostname;
2368 while (*p)
2370 if (*p >= 'A' && *p <= 'Z')
2371 *p += 'a' - 'A';
2372 p++;
2374 #endif
2377 #endif /* HAVE_SOCKETS */
2378 /* We used to try using getdomainname here,
2379 but NIIBE Yutaka <gniibe@etl.go.jp> says that
2380 getdomainname gets the NIS/YP domain which often is not the same
2381 as in Internet domain name. */
2382 #if 0 /* Turned off because sysinfo is not really likely to return the
2383 correct Internet domain. */
2384 #if (HAVE_SYSINFO && defined (SI_SRPC_DOMAIN))
2385 if (! index (hostname, '.'))
2387 /* The hostname is not fully qualified. Append the domain name. */
2389 int hostlen = strlen (hostname);
2390 int domain_size = 256;
2392 for (;;)
2394 char *domain = (char *) alloca (domain_size + 1);
2395 char *fqdn = (char *) alloca (hostlen + 1 + domain_size + 1);
2396 int sys_domain_size = sysinfo (SI_SRPC_DOMAIN, domain, domain_size);
2397 if (sys_domain_size <= 0)
2398 break;
2399 if (domain_size < sys_domain_size)
2401 domain_size = sys_domain_size;
2402 continue;
2404 strcpy (fqdn, hostname);
2405 if (domain[0] == '.')
2406 strcpy (fqdn + hostlen, domain);
2407 else if (domain[0] != 0)
2409 fqdn[hostlen] = '.';
2410 strcpy (fqdn + hostlen + 1, domain);
2412 hostname = fqdn;
2413 break;
2416 #endif /* HAVE_SYSINFO && defined (SI_SRPC_DOMAIN) */
2417 #endif /* 0 */
2418 Vsystem_name = build_string (hostname);
2419 #endif /* HAVE_GETHOSTNAME */
2420 #endif /* VMS */
2421 #endif /* BSD4_1 */
2423 unsigned char *p;
2424 for (p = XSTRING (Vsystem_name)->data; *p; p++)
2425 if (*p == ' ' || *p == '\t')
2426 *p = '-';
2430 #ifndef MSDOS
2431 #ifndef VMS
2432 #if !defined (HAVE_SELECT) || defined (BROKEN_SELECT_NON_X)
2434 #include "sysselect.h"
2435 #undef select
2437 #if defined (HAVE_X_WINDOWS) && !defined (HAVE_SELECT)
2438 /* Cause explanatory error message at compile time,
2439 since the select emulation is not good enough for X. */
2440 int *x = &x_windows_lose_if_no_select_system_call;
2441 #endif
2443 /* Emulate as much as select as is possible under 4.1 and needed by Gnu Emacs
2444 * Only checks read descriptors.
2446 /* How long to wait between checking fds in select */
2447 #define SELECT_PAUSE 1
2448 int select_alarmed;
2450 /* For longjmp'ing back to read_input_waiting. */
2452 jmp_buf read_alarm_throw;
2454 /* Nonzero if the alarm signal should throw back to read_input_waiting.
2455 The read_socket_hook function sets this to 1 while it is waiting. */
2457 int read_alarm_should_throw;
2459 SIGTYPE
2460 select_alarm ()
2462 select_alarmed = 1;
2463 #ifdef BSD4_1
2464 sigrelse (SIGALRM);
2465 #else /* not BSD4_1 */
2466 signal (SIGALRM, SIG_IGN);
2467 #endif /* not BSD4_1 */
2468 if (read_alarm_should_throw)
2469 longjmp (read_alarm_throw, 1);
2472 #ifndef WINDOWSNT
2473 /* Only rfds are checked. */
2475 sys_select (nfds, rfds, wfds, efds, timeout)
2476 int nfds;
2477 SELECT_TYPE *rfds, *wfds, *efds;
2478 EMACS_TIME *timeout;
2480 int ravail = 0;
2481 SELECT_TYPE orfds;
2482 int timeoutval;
2483 int *local_timeout;
2484 extern int proc_buffered_char[];
2485 #ifndef subprocesses
2486 int process_tick = 0, update_tick = 0;
2487 #else
2488 extern int process_tick, update_tick;
2489 #endif
2490 unsigned char buf;
2492 #if defined (HAVE_SELECT) && defined (HAVE_X_WINDOWS)
2493 /* If we're using X, then the native select will work; we only need the
2494 emulation for non-X usage. */
2495 if (!NILP (Vwindow_system))
2496 return select (nfds, rfds, wfds, efds, timeout);
2497 #endif
2498 timeoutval = timeout ? EMACS_SECS (*timeout) : 100000;
2499 local_timeout = &timeoutval;
2500 FD_ZERO (&orfds);
2501 if (rfds)
2503 orfds = *rfds;
2504 FD_ZERO (rfds);
2506 if (wfds)
2507 FD_ZERO (wfds);
2508 if (efds)
2509 FD_ZERO (efds);
2511 /* If we are looking only for the terminal, with no timeout,
2512 just read it and wait -- that's more efficient. */
2513 if (*local_timeout == 100000 && process_tick == update_tick
2514 && FD_ISSET (0, &orfds))
2516 int fd;
2517 for (fd = 1; fd < nfds; ++fd)
2518 if (FD_ISSET (fd, &orfds))
2519 goto hardway;
2520 if (! detect_input_pending ())
2521 read_input_waiting ();
2522 FD_SET (0, rfds);
2523 return 1;
2526 hardway:
2527 /* Once a second, till the timer expires, check all the flagged read
2528 * descriptors to see if any input is available. If there is some then
2529 * set the corresponding bit in the return copy of rfds.
2531 while (1)
2533 register int to_check, fd;
2535 if (rfds)
2537 for (to_check = nfds, fd = 0; --to_check >= 0; fd++)
2539 if (FD_ISSET (fd, &orfds))
2541 int avail = 0, status = 0;
2543 if (fd == 0)
2544 avail = detect_input_pending (); /* Special keyboard handler */
2545 else
2547 #ifdef FIONREAD
2548 status = ioctl (fd, FIONREAD, &avail);
2549 #else /* no FIONREAD */
2550 /* Hoping it will return -1 if nothing available
2551 or 0 if all 0 chars requested are read. */
2552 if (proc_buffered_char[fd] >= 0)
2553 avail = 1;
2554 else
2556 avail = read (fd, &buf, 1);
2557 if (avail > 0)
2558 proc_buffered_char[fd] = buf;
2560 #endif /* no FIONREAD */
2562 if (status >= 0 && avail > 0)
2564 FD_SET (fd, rfds);
2565 ravail++;
2570 if (*local_timeout == 0 || ravail != 0 || process_tick != update_tick)
2571 break;
2573 turn_on_atimers (0);
2574 signal (SIGALRM, select_alarm);
2575 select_alarmed = 0;
2576 alarm (SELECT_PAUSE);
2578 /* Wait for a SIGALRM (or maybe a SIGTINT) */
2579 while (select_alarmed == 0 && *local_timeout != 0
2580 && process_tick == update_tick)
2582 /* If we are interested in terminal input,
2583 wait by reading the terminal.
2584 That makes instant wakeup for terminal input at least. */
2585 if (FD_ISSET (0, &orfds))
2587 read_input_waiting ();
2588 if (detect_input_pending ())
2589 select_alarmed = 1;
2591 else
2592 pause ();
2594 (*local_timeout) -= SELECT_PAUSE;
2596 /* Reset the old alarm if there was one. */
2597 turn_on_atimers (1);
2599 if (*local_timeout == 0) /* Stop on timer being cleared */
2600 break;
2602 return ravail;
2604 #endif /* not WINDOWSNT */
2606 /* Read keyboard input into the standard buffer,
2607 waiting for at least one character. */
2609 /* Make all keyboard buffers much bigger when using a window system. */
2610 #ifdef HAVE_WINDOW_SYSTEM
2611 #define BUFFER_SIZE_FACTOR 16
2612 #else
2613 #define BUFFER_SIZE_FACTOR 1
2614 #endif
2616 void
2617 read_input_waiting ()
2619 struct input_event e;
2620 int nread, i;
2621 extern int quit_char;
2623 if (read_socket_hook)
2625 struct input_event buf[256];
2627 read_alarm_should_throw = 0;
2628 if (! setjmp (read_alarm_throw))
2629 nread = (*read_socket_hook) (0, buf, 256, 1);
2630 else
2631 nread = -1;
2633 /* Scan the chars for C-g and store them in kbd_buffer. */
2634 for (i = 0; i < nread; i++)
2636 kbd_buffer_store_event (&buf[i]);
2637 /* Don't look at input that follows a C-g too closely.
2638 This reduces lossage due to autorepeat on C-g. */
2639 if (buf[i].kind == ascii_keystroke
2640 && buf[i].code == quit_char)
2641 break;
2644 else
2646 char buf[3];
2647 nread = read (fileno (stdin), buf, 1);
2649 /* Scan the chars for C-g and store them in kbd_buffer. */
2650 e.kind = ascii_keystroke;
2651 e.frame_or_window = selected_frame;
2652 e.modifiers = 0;
2653 for (i = 0; i < nread; i++)
2655 /* Convert chars > 0177 to meta events if desired.
2656 We do this under the same conditions that read_avail_input does. */
2657 if (read_socket_hook == 0)
2659 /* If the user says she has a meta key, then believe her. */
2660 if (meta_key == 1 && (buf[i] & 0x80))
2661 e.modifiers = meta_modifier;
2662 if (meta_key != 2)
2663 buf[i] &= ~0x80;
2666 XSETINT (e.code, buf[i]);
2667 kbd_buffer_store_event (&e);
2668 /* Don't look at input that follows a C-g too closely.
2669 This reduces lossage due to autorepeat on C-g. */
2670 if (buf[i] == quit_char)
2671 break;
2676 #endif /* not HAVE_SELECT */
2677 #endif /* not VMS */
2678 #endif /* not MSDOS */
2680 #ifdef BSD4_1
2681 void
2682 init_sigio (fd)
2683 int fd;
2685 if (noninteractive)
2686 return;
2687 lmode = LINTRUP | lmode;
2688 ioctl (fd, TIOCLSET, &lmode);
2691 void
2692 reset_sigio ()
2694 if (noninteractive)
2695 return;
2696 lmode = ~LINTRUP & lmode;
2697 ioctl (0, TIOCLSET, &lmode);
2700 void
2701 request_sigio ()
2703 sigrelse (SIGTINT);
2705 interrupts_deferred = 0;
2708 void
2709 unrequest_sigio ()
2711 sighold (SIGTINT);
2713 interrupts_deferred = 1;
2716 /* still inside #ifdef BSD4_1 */
2717 #ifdef subprocesses
2719 int sigheld; /* Mask of held signals */
2721 void
2722 sigholdx (signum)
2723 int signum;
2725 sigheld |= sigbit (signum);
2726 sighold (signum);
2729 void
2730 sigisheld (signum)
2731 int signum;
2733 sigheld |= sigbit (signum);
2736 void
2737 sigunhold (signum)
2738 int signum;
2740 sigheld &= ~sigbit (signum);
2741 sigrelse (signum);
2744 void
2745 sigfree () /* Free all held signals */
2747 int i;
2748 for (i = 0; i < NSIG; i++)
2749 if (sigheld & sigbit (i))
2750 sigrelse (i);
2751 sigheld = 0;
2755 sigbit (i)
2757 return 1 << (i - 1);
2759 #endif /* subprocesses */
2760 #endif /* BSD4_1 */
2762 /* POSIX signals support - DJB */
2763 /* Anyone with POSIX signals should have ANSI C declarations */
2765 #ifdef POSIX_SIGNALS
2767 sigset_t empty_mask, full_mask;
2769 signal_handler_t
2770 sys_signal (int signal_number, signal_handler_t action)
2772 struct sigaction new_action, old_action;
2773 sigemptyset (&new_action.sa_mask);
2774 new_action.sa_handler = action;
2775 #ifdef SA_RESTART
2776 /* Emacs mostly works better with restartable system services. If this
2777 * flag exists, we probably want to turn it on here.
2779 new_action.sa_flags = SA_RESTART;
2780 #else
2781 new_action.sa_flags = 0;
2782 #endif
2783 sigaction (signal_number, &new_action, &old_action);
2784 return (old_action.sa_handler);
2787 #ifndef __GNUC__
2788 /* If we're compiling with GCC, we don't need this function, since it
2789 can be written as a macro. */
2790 sigset_t
2791 sys_sigmask (int sig)
2793 sigset_t mask;
2794 sigemptyset (&mask);
2795 sigaddset (&mask, sig);
2796 return mask;
2798 #endif
2800 /* I'd like to have these guys return pointers to the mask storage in here,
2801 but there'd be trouble if the code was saving multiple masks. I'll be
2802 safe and pass the structure. It normally won't be more than 2 bytes
2803 anyhow. - DJB */
2805 sigset_t
2806 sys_sigblock (sigset_t new_mask)
2808 sigset_t old_mask;
2809 sigprocmask (SIG_BLOCK, &new_mask, &old_mask);
2810 return (old_mask);
2813 sigset_t
2814 sys_sigunblock (sigset_t new_mask)
2816 sigset_t old_mask;
2817 sigprocmask (SIG_UNBLOCK, &new_mask, &old_mask);
2818 return (old_mask);
2821 sigset_t
2822 sys_sigsetmask (sigset_t new_mask)
2824 sigset_t old_mask;
2825 sigprocmask (SIG_SETMASK, &new_mask, &old_mask);
2826 return (old_mask);
2829 #endif /* POSIX_SIGNALS */
2831 #if !defined HAVE_STRSIGNAL && !defined SYS_SIGLIST_DECLARED
2832 static char *my_sys_siglist[NSIG];
2833 # ifdef sys_siglist
2834 # undef sys_siglist
2835 # endif
2836 # define sys_siglist my_sys_siglist
2837 #endif
2839 void
2840 init_signals ()
2842 #ifdef POSIX_SIGNALS
2843 sigemptyset (&empty_mask);
2844 sigfillset (&full_mask);
2845 #endif
2847 #if !defined HAVE_STRSIGNAL && !defined SYS_SIGLIST_DECLARED
2848 if (! initialized)
2850 # ifdef SIGABRT
2851 sys_siglist[SIGABRT] = "Aborted";
2852 # endif
2853 # ifdef SIGAIO
2854 sys_siglist[SIGAIO] = "LAN I/O interrupt";
2855 # endif
2856 # ifdef SIGALRM
2857 sys_siglist[SIGALRM] = "Alarm clock";
2858 # endif
2859 # ifdef SIGBUS
2860 sys_siglist[SIGBUS] = "Bus error";
2861 # endif
2862 # ifdef SIGCLD
2863 sys_siglist[SIGCLD] = "Child status changed";
2864 # endif
2865 # ifdef SIGCHLD
2866 sys_siglist[SIGCHLD] = "Child status changed";
2867 # endif
2868 # ifdef SIGCONT
2869 sys_siglist[SIGCONT] = "Continued";
2870 # endif
2871 # ifdef SIGDANGER
2872 sys_siglist[SIGDANGER] = "Swap space dangerously low";
2873 # endif
2874 # ifdef SIGDGNOTIFY
2875 sys_siglist[SIGDGNOTIFY] = "Notification message in queue";
2876 # endif
2877 # ifdef SIGEMT
2878 sys_siglist[SIGEMT] = "Emulation trap";
2879 # endif
2880 # ifdef SIGFPE
2881 sys_siglist[SIGFPE] = "Arithmetic exception";
2882 # endif
2883 # ifdef SIGFREEZE
2884 sys_siglist[SIGFREEZE] = "SIGFREEZE";
2885 # endif
2886 # ifdef SIGGRANT
2887 sys_siglist[SIGGRANT] = "Monitor mode granted";
2888 # endif
2889 # ifdef SIGHUP
2890 sys_siglist[SIGHUP] = "Hangup";
2891 # endif
2892 # ifdef SIGILL
2893 sys_siglist[SIGILL] = "Illegal instruction";
2894 # endif
2895 # ifdef SIGINT
2896 sys_siglist[SIGINT] = "Interrupt";
2897 # endif
2898 # ifdef SIGIO
2899 sys_siglist[SIGIO] = "I/O possible";
2900 # endif
2901 # ifdef SIGIOINT
2902 sys_siglist[SIGIOINT] = "I/O intervention required";
2903 # endif
2904 # ifdef SIGIOT
2905 sys_siglist[SIGIOT] = "IOT trap";
2906 # endif
2907 # ifdef SIGKILL
2908 sys_siglist[SIGKILL] = "Killed";
2909 # endif
2910 # ifdef SIGLOST
2911 sys_siglist[SIGLOST] = "Resource lost";
2912 # endif
2913 # ifdef SIGLWP
2914 sys_siglist[SIGLWP] = "SIGLWP";
2915 # endif
2916 # ifdef SIGMSG
2917 sys_siglist[SIGMSG] = "Monitor mode data available";
2918 # endif
2919 # ifdef SIGPHONE
2920 sys_siglist[SIGWIND] = "SIGPHONE";
2921 # endif
2922 # ifdef SIGPIPE
2923 sys_siglist[SIGPIPE] = "Broken pipe";
2924 # endif
2925 # ifdef SIGPOLL
2926 sys_siglist[SIGPOLL] = "Pollable event occurred";
2927 # endif
2928 # ifdef SIGPROF
2929 sys_siglist[SIGPROF] = "Profiling timer expired";
2930 # endif
2931 # ifdef SIGPTY
2932 sys_siglist[SIGPTY] = "PTY I/O interrupt";
2933 # endif
2934 # ifdef SIGPWR
2935 sys_siglist[SIGPWR] = "Power-fail restart";
2936 # endif
2937 # ifdef SIGQUIT
2938 sys_siglist[SIGQUIT] = "Quit";
2939 # endif
2940 # ifdef SIGRETRACT
2941 sys_siglist[SIGRETRACT] = "Need to relinguish monitor mode";
2942 # endif
2943 # ifdef SIGSAK
2944 sys_siglist[SIGSAK] = "Secure attention";
2945 # endif
2946 # ifdef SIGSEGV
2947 sys_siglist[SIGSEGV] = "Segmentation violation";
2948 # endif
2949 # ifdef SIGSOUND
2950 sys_siglist[SIGSOUND] = "Sound completed";
2951 # endif
2952 # ifdef SIGSTOP
2953 sys_siglist[SIGSTOP] = "Stopped (signal)";
2954 # endif
2955 # ifdef SIGSTP
2956 sys_siglist[SIGSTP] = "Stopped (user)";
2957 # endif
2958 # ifdef SIGSYS
2959 sys_siglist[SIGSYS] = "Bad argument to system call";
2960 # endif
2961 # ifdef SIGTERM
2962 sys_siglist[SIGTERM] = "Terminated";
2963 # endif
2964 # ifdef SIGTHAW
2965 sys_siglist[SIGTHAW] = "SIGTHAW";
2966 # endif
2967 # ifdef SIGTRAP
2968 sys_siglist[SIGTRAP] = "Trace/breakpoint trap";
2969 # endif
2970 # ifdef SIGTSTP
2971 sys_siglist[SIGTSTP] = "Stopped (user)";
2972 # endif
2973 # ifdef SIGTTIN
2974 sys_siglist[SIGTTIN] = "Stopped (tty input)";
2975 # endif
2976 # ifdef SIGTTOU
2977 sys_siglist[SIGTTOU] = "Stopped (tty output)";
2978 # endif
2979 # ifdef SIGURG
2980 sys_siglist[SIGURG] = "Urgent I/O condition";
2981 # endif
2982 # ifdef SIGUSR1
2983 sys_siglist[SIGUSR1] = "User defined signal 1";
2984 # endif
2985 # ifdef SIGUSR2
2986 sys_siglist[SIGUSR2] = "User defined signal 2";
2987 # endif
2988 # ifdef SIGVTALRM
2989 sys_siglist[SIGVTALRM] = "Virtual timer expired";
2990 # endif
2991 # ifdef SIGWAITING
2992 sys_siglist[SIGWAITING] = "Process's LWPs are blocked";
2993 # endif
2994 # ifdef SIGWINCH
2995 sys_siglist[SIGWINCH] = "Window size changed";
2996 # endif
2997 # ifdef SIGWIND
2998 sys_siglist[SIGWIND] = "SIGWIND";
2999 # endif
3000 # ifdef SIGXCPU
3001 sys_siglist[SIGXCPU] = "CPU time limit exceeded";
3002 # endif
3003 # ifdef SIGXFSZ
3004 sys_siglist[SIGXFSZ] = "File size limit exceeded";
3005 # endif
3007 #endif /* !defined HAVE_STRSIGNAL && !defined SYS_SIGLIST_DECLARED */
3010 #ifndef HAVE_RANDOM
3011 #ifdef random
3012 #define HAVE_RANDOM
3013 #endif
3014 #endif
3016 /* Figure out how many bits the system's random number generator uses.
3017 `random' and `lrand48' are assumed to return 31 usable bits.
3018 BSD `rand' returns a 31 bit value but the low order bits are unusable;
3019 so we'll shift it and treat it like the 15-bit USG `rand'. */
3021 #ifndef RAND_BITS
3022 # ifdef HAVE_RANDOM
3023 # define RAND_BITS 31
3024 # else /* !HAVE_RANDOM */
3025 # ifdef HAVE_LRAND48
3026 # define RAND_BITS 31
3027 # define random lrand48
3028 # else /* !HAVE_LRAND48 */
3029 # define RAND_BITS 15
3030 # if RAND_MAX == 32767
3031 # define random rand
3032 # else /* RAND_MAX != 32767 */
3033 # if RAND_MAX == 2147483647
3034 # define random() (rand () >> 16)
3035 # else /* RAND_MAX != 2147483647 */
3036 # ifdef USG
3037 # define random rand
3038 # else
3039 # define random() (rand () >> 16)
3040 # endif /* !USG */
3041 # endif /* RAND_MAX != 2147483647 */
3042 # endif /* RAND_MAX != 32767 */
3043 # endif /* !HAVE_LRAND48 */
3044 # endif /* !HAVE_RANDOM */
3045 #endif /* !RAND_BITS */
3047 void
3048 seed_random (arg)
3049 long arg;
3051 #ifdef HAVE_RANDOM
3052 srandom ((unsigned int)arg);
3053 #else
3054 # ifdef HAVE_LRAND48
3055 srand48 (arg);
3056 # else
3057 srand ((unsigned int)arg);
3058 # endif
3059 #endif
3063 * Build a full Emacs-sized word out of whatever we've got.
3064 * This suffices even for a 64-bit architecture with a 15-bit rand.
3066 long
3067 get_random ()
3069 long val = random ();
3070 #if VALBITS > RAND_BITS
3071 val = (val << RAND_BITS) ^ random ();
3072 #if VALBITS > 2*RAND_BITS
3073 val = (val << RAND_BITS) ^ random ();
3074 #if VALBITS > 3*RAND_BITS
3075 val = (val << RAND_BITS) ^ random ();
3076 #if VALBITS > 4*RAND_BITS
3077 val = (val << RAND_BITS) ^ random ();
3078 #endif /* need at least 5 */
3079 #endif /* need at least 4 */
3080 #endif /* need at least 3 */
3081 #endif /* need at least 2 */
3082 return val & ((1L << VALBITS) - 1);
3085 #ifdef WRONG_NAME_INSQUE
3087 insque (q,p)
3088 caddr_t q,p;
3090 _insque (q,p);
3093 #endif
3095 #ifdef VMS
3097 #ifdef getenv
3098 /* If any place else asks for the TERM variable,
3099 allow it to be overridden with the EMACS_TERM variable
3100 before attempting to translate the logical name TERM. As a last
3101 resort, ask for VAX C's special idea of the TERM variable. */
3102 #undef getenv
3103 char *
3104 sys_getenv (name)
3105 char *name;
3107 register char *val;
3108 static char buf[256];
3109 static struct dsc$descriptor_s equiv
3110 = {sizeof (buf), DSC$K_DTYPE_T, DSC$K_CLASS_S, buf};
3111 static struct dsc$descriptor_s d_name
3112 = {0, DSC$K_DTYPE_T, DSC$K_CLASS_S, 0};
3113 short eqlen;
3115 if (!strcmp (name, "TERM"))
3117 val = (char *) getenv ("EMACS_TERM");
3118 if (val)
3119 return val;
3122 d_name.dsc$w_length = strlen (name);
3123 d_name.dsc$a_pointer = name;
3124 if (LIB$SYS_TRNLOG (&d_name, &eqlen, &equiv) == 1)
3126 char *str = (char *) xmalloc (eqlen + 1);
3127 bcopy (buf, str, eqlen);
3128 str[eqlen] = '\0';
3129 /* This is a storage leak, but a pain to fix. With luck,
3130 no one will ever notice. */
3131 return str;
3133 return (char *) getenv (name);
3135 #endif /* getenv */
3137 #ifdef abort
3138 /* Since VMS doesn't believe in core dumps, the only way to debug this beast is
3139 to force a call on the debugger from within the image. */
3140 #undef abort
3141 sys_abort ()
3143 reset_sys_modes ();
3144 LIB$SIGNAL (SS$_DEBUG);
3146 #endif /* abort */
3147 #endif /* VMS */
3149 #ifdef VMS
3150 #ifdef LINK_CRTL_SHARE
3151 #ifdef SHARABLE_LIB_BUG
3152 /* Variables declared noshare and initialized in sharable libraries
3153 cannot be shared. The VMS linker incorrectly forces you to use a private
3154 version which is uninitialized... If not for this "feature", we
3155 could use the C library definition of sys_nerr and sys_errlist. */
3156 int sys_nerr = 35;
3157 char *sys_errlist[] =
3159 "error 0",
3160 "not owner",
3161 "no such file or directory",
3162 "no such process",
3163 "interrupted system call",
3164 "i/o error",
3165 "no such device or address",
3166 "argument list too long",
3167 "exec format error",
3168 "bad file number",
3169 "no child process",
3170 "no more processes",
3171 "not enough memory",
3172 "permission denied",
3173 "bad address",
3174 "block device required",
3175 "mount devices busy",
3176 "file exists",
3177 "cross-device link",
3178 "no such device",
3179 "not a directory",
3180 "is a directory",
3181 "invalid argument",
3182 "file table overflow",
3183 "too many open files",
3184 "not a typewriter",
3185 "text file busy",
3186 "file too big",
3187 "no space left on device",
3188 "illegal seek",
3189 "read-only file system",
3190 "too many links",
3191 "broken pipe",
3192 "math argument",
3193 "result too large",
3194 "I/O stream empty",
3195 "vax/vms specific error code nontranslatable error"
3197 #endif /* SHARABLE_LIB_BUG */
3198 #endif /* LINK_CRTL_SHARE */
3199 #endif /* VMS */
3201 #ifndef HAVE_STRERROR
3202 #ifndef WINDOWSNT
3203 char *
3204 strerror (errnum)
3205 int errnum;
3207 extern char *sys_errlist[];
3208 extern int sys_nerr;
3210 if (errnum >= 0 && errnum < sys_nerr)
3211 return sys_errlist[errnum];
3212 return (char *) "Unknown error";
3214 #endif /* not WINDOWSNT */
3215 #endif /* ! HAVE_STRERROR */
3218 emacs_open (path, oflag, mode)
3219 char *path;
3220 int oflag, mode;
3222 register int rtnval;
3224 #ifdef BSD4_1
3225 if (oflag & O_CREAT)
3226 return creat (path, mode);
3227 #endif
3229 while ((rtnval = open (path, oflag, mode)) == -1
3230 && (errno == EINTR));
3231 return (rtnval);
3235 emacs_close (fd)
3236 int fd;
3238 int did_retry = 0;
3239 register int rtnval;
3241 while ((rtnval = close (fd)) == -1
3242 && (errno == EINTR))
3243 did_retry = 1;
3245 /* If close is interrupted SunOS 4.1 may or may not have closed the
3246 file descriptor. If it did the second close will fail with
3247 errno = EBADF. That means we have succeeded. */
3248 if (rtnval == -1 && did_retry && errno == EBADF)
3249 return 0;
3251 return rtnval;
3255 emacs_read (fildes, buf, nbyte)
3256 int fildes;
3257 char *buf;
3258 unsigned int nbyte;
3260 register int rtnval;
3262 while ((rtnval = read (fildes, buf, nbyte)) == -1
3263 && (errno == EINTR));
3264 return (rtnval);
3268 emacs_write (fildes, buf, nbyte)
3269 int fildes;
3270 char *buf;
3271 unsigned int nbyte;
3273 register int rtnval, bytes_written;
3275 bytes_written = 0;
3277 while (nbyte > 0)
3279 rtnval = write (fildes, buf, nbyte);
3281 if (rtnval == -1)
3283 if (errno == EINTR)
3284 continue;
3285 else
3286 return (bytes_written ? bytes_written : -1);
3289 buf += rtnval;
3290 nbyte -= rtnval;
3291 bytes_written += rtnval;
3293 return (bytes_written);
3296 #ifdef USG
3298 * All of the following are for USG.
3300 * On USG systems the system calls are INTERRUPTIBLE by signals
3301 * that the user program has elected to catch. Thus the system call
3302 * must be retried in these cases. To handle this without massive
3303 * changes in the source code, we remap the standard system call names
3304 * to names for our own functions in sysdep.c that do the system call
3305 * with retries. Actually, for portability reasons, it is good
3306 * programming practice, as this example shows, to limit all actual
3307 * system calls to a single occurrence in the source. Sure, this
3308 * adds an extra level of function call overhead but it is almost
3309 * always negligible. Fred Fish, Unisoft Systems Inc.
3313 * Warning, this function may not duplicate 4.2 action properly
3314 * under error conditions.
3317 #ifndef MAXPATHLEN
3318 /* In 4.1, param.h fails to define this. */
3319 #define MAXPATHLEN 1024
3320 #endif
3322 #ifndef HAVE_GETWD
3324 char *
3325 getwd (pathname)
3326 char *pathname;
3328 char *npath, *spath;
3329 extern char *getcwd ();
3331 BLOCK_INPUT; /* getcwd uses malloc */
3332 spath = npath = getcwd ((char *) 0, MAXPATHLEN);
3333 if (spath == 0)
3334 return spath;
3335 /* On Altos 3068, getcwd can return @hostname/dir, so discard
3336 up to first slash. Should be harmless on other systems. */
3337 while (*npath && *npath != '/')
3338 npath++;
3339 strcpy (pathname, npath);
3340 free (spath); /* getcwd uses malloc */
3341 UNBLOCK_INPUT;
3342 return pathname;
3345 #endif /* HAVE_GETWD */
3348 * Emulate rename using unlink/link. Note that this is
3349 * only partially correct. Also, doesn't enforce restriction
3350 * that files be of same type (regular->regular, dir->dir, etc).
3353 #ifndef HAVE_RENAME
3355 rename (from, to)
3356 const char *from;
3357 const char *to;
3359 if (access (from, 0) == 0)
3361 unlink (to);
3362 if (link (from, to) == 0)
3363 if (unlink (from) == 0)
3364 return (0);
3366 return (-1);
3369 #endif
3372 #ifdef HPUX
3373 #ifndef HAVE_PERROR
3375 /* HPUX curses library references perror, but as far as we know
3376 it won't be called. Anyway this definition will do for now. */
3378 perror ()
3382 #endif /* not HAVE_PERROR */
3383 #endif /* HPUX */
3385 #ifndef HAVE_DUP2
3388 * Emulate BSD dup2. First close newd if it already exists.
3389 * Then, attempt to dup oldd. If not successful, call dup2 recursively
3390 * until we are, then close the unsuccessful ones.
3393 dup2 (oldd, newd)
3394 int oldd;
3395 int newd;
3397 register int fd, ret;
3399 emacs_close (newd);
3401 #ifdef F_DUPFD
3402 return fcntl (oldd, F_DUPFD, newd);
3403 #else
3404 fd = dup (old);
3405 if (fd == -1)
3406 return -1;
3407 if (fd == new)
3408 return new;
3409 ret = dup2 (old,new);
3410 emacs_close (fd);
3411 return ret;
3412 #endif
3415 #endif /* not HAVE_DUP2 */
3418 * Gettimeofday. Simulate as much as possible. Only accurate
3419 * to nearest second. Emacs doesn't use tzp so ignore it for now.
3420 * Only needed when subprocesses are defined.
3423 #ifdef subprocesses
3424 #ifndef VMS
3425 #ifndef HAVE_GETTIMEOFDAY
3426 #ifdef HAVE_TIMEVAL
3428 /* ARGSUSED */
3430 gettimeofday (tp, tzp)
3431 struct timeval *tp;
3432 struct timezone *tzp;
3434 extern long time ();
3436 tp->tv_sec = time ((long *)0);
3437 tp->tv_usec = 0;
3438 if (tzp != 0)
3439 tzp->tz_minuteswest = -1;
3440 return 0;
3443 #endif
3444 #endif
3445 #endif
3446 #endif /* subprocess && !HAVE_GETTIMEOFDAY && HAVE_TIMEVAL && !VMS */
3449 * This function will go away as soon as all the stubs fixed. (fnf)
3452 void
3453 croak (badfunc)
3454 char *badfunc;
3456 printf ("%s not yet implemented\r\n", badfunc);
3457 reset_sys_modes ();
3458 exit (1);
3461 #endif /* USG */
3463 /* Directory routines for systems that don't have them. */
3465 #ifdef SYSV_SYSTEM_DIR
3467 #include <dirent.h>
3469 #if defined (BROKEN_CLOSEDIR) || !defined (HAVE_CLOSEDIR)
3472 closedir (dirp)
3473 register DIR *dirp; /* stream from opendir */
3475 int rtnval;
3477 rtnval = emacs_close (dirp->dd_fd);
3479 /* Some systems (like Solaris) allocate the buffer and the DIR all
3480 in one block. Why in the world are we freeing this ourselves
3481 anyway? */
3482 #if ! (defined (sun) && defined (USG5_4))
3483 xfree ((char *) dirp->dd_buf); /* directory block defined in <dirent.h> */
3484 #endif
3485 xfree ((char *) dirp);
3487 return rtnval;
3489 #endif /* BROKEN_CLOSEDIR or not HAVE_CLOSEDIR */
3490 #endif /* SYSV_SYSTEM_DIR */
3492 #ifdef NONSYSTEM_DIR_LIBRARY
3494 DIR *
3495 opendir (filename)
3496 char *filename; /* name of directory */
3498 register DIR *dirp; /* -> malloc'ed storage */
3499 register int fd; /* file descriptor for read */
3500 struct stat sbuf; /* result of fstat */
3502 fd = emacs_open (filename, O_RDONLY, 0);
3503 if (fd < 0)
3504 return 0;
3506 BLOCK_INPUT;
3507 if (fstat (fd, &sbuf) < 0
3508 || (sbuf.st_mode & S_IFMT) != S_IFDIR
3509 || (dirp = (DIR *) malloc (sizeof (DIR))) == 0)
3511 emacs_close (fd);
3512 UNBLOCK_INPUT;
3513 return 0; /* bad luck today */
3515 UNBLOCK_INPUT;
3517 dirp->dd_fd = fd;
3518 dirp->dd_loc = dirp->dd_size = 0; /* refill needed */
3520 return dirp;
3523 void
3524 closedir (dirp)
3525 register DIR *dirp; /* stream from opendir */
3527 emacs_close (dirp->dd_fd);
3528 xfree ((char *) dirp);
3532 #ifndef VMS
3533 #define DIRSIZ 14
3534 struct olddir
3536 ino_t od_ino; /* inode */
3537 char od_name[DIRSIZ]; /* filename */
3539 #endif /* not VMS */
3541 struct direct dir_static; /* simulated directory contents */
3543 /* ARGUSED */
3544 struct direct *
3545 readdir (dirp)
3546 register DIR *dirp; /* stream from opendir */
3548 #ifndef VMS
3549 register struct olddir *dp; /* -> directory data */
3550 #else /* VMS */
3551 register struct dir$_name *dp; /* -> directory data */
3552 register struct dir$_version *dv; /* -> version data */
3553 #endif /* VMS */
3555 for (; ;)
3557 if (dirp->dd_loc >= dirp->dd_size)
3558 dirp->dd_loc = dirp->dd_size = 0;
3560 if (dirp->dd_size == 0 /* refill buffer */
3561 && (dirp->dd_size = emacs_read (dirp->dd_fd, dirp->dd_buf, DIRBLKSIZ)) <= 0)
3562 return 0;
3564 #ifndef VMS
3565 dp = (struct olddir *) &dirp->dd_buf[dirp->dd_loc];
3566 dirp->dd_loc += sizeof (struct olddir);
3568 if (dp->od_ino != 0) /* not deleted entry */
3570 dir_static.d_ino = dp->od_ino;
3571 strncpy (dir_static.d_name, dp->od_name, DIRSIZ);
3572 dir_static.d_name[DIRSIZ] = '\0';
3573 dir_static.d_namlen = strlen (dir_static.d_name);
3574 dir_static.d_reclen = sizeof (struct direct)
3575 - MAXNAMLEN + 3
3576 + dir_static.d_namlen - dir_static.d_namlen % 4;
3577 return &dir_static; /* -> simulated structure */
3579 #else /* VMS */
3580 dp = (struct dir$_name *) dirp->dd_buf;
3581 if (dirp->dd_loc == 0)
3582 dirp->dd_loc = (dp->dir$b_namecount&1) ? dp->dir$b_namecount + 1
3583 : dp->dir$b_namecount;
3584 dv = (struct dir$_version *)&dp->dir$t_name[dirp->dd_loc];
3585 dir_static.d_ino = dv->dir$w_fid_num;
3586 dir_static.d_namlen = dp->dir$b_namecount;
3587 dir_static.d_reclen = sizeof (struct direct)
3588 - MAXNAMLEN + 3
3589 + dir_static.d_namlen - dir_static.d_namlen % 4;
3590 strncpy (dir_static.d_name, dp->dir$t_name, dp->dir$b_namecount);
3591 dir_static.d_name[dir_static.d_namlen] = '\0';
3592 dirp->dd_loc = dirp->dd_size; /* only one record at a time */
3593 return &dir_static;
3594 #endif /* VMS */
3598 #ifdef VMS
3599 /* readdirver is just like readdir except it returns all versions of a file
3600 as separate entries. */
3602 /* ARGUSED */
3603 struct direct *
3604 readdirver (dirp)
3605 register DIR *dirp; /* stream from opendir */
3607 register struct dir$_name *dp; /* -> directory data */
3608 register struct dir$_version *dv; /* -> version data */
3610 if (dirp->dd_loc >= dirp->dd_size - sizeof (struct dir$_name))
3611 dirp->dd_loc = dirp->dd_size = 0;
3613 if (dirp->dd_size == 0 /* refill buffer */
3614 && (dirp->dd_size = sys_read (dirp->dd_fd, dirp->dd_buf, DIRBLKSIZ)) <= 0)
3615 return 0;
3617 dp = (struct dir$_name *) dirp->dd_buf;
3618 if (dirp->dd_loc == 0)
3619 dirp->dd_loc = (dp->dir$b_namecount & 1) ? dp->dir$b_namecount + 1
3620 : dp->dir$b_namecount;
3621 dv = (struct dir$_version *) &dp->dir$t_name[dirp->dd_loc];
3622 strncpy (dir_static.d_name, dp->dir$t_name, dp->dir$b_namecount);
3623 sprintf (&dir_static.d_name[dp->dir$b_namecount], ";%d", dv->dir$w_version);
3624 dir_static.d_namlen = strlen (dir_static.d_name);
3625 dir_static.d_ino = dv->dir$w_fid_num;
3626 dir_static.d_reclen = sizeof (struct direct) - MAXNAMLEN + 3
3627 + dir_static.d_namlen - dir_static.d_namlen % 4;
3628 dirp->dd_loc = ((char *) (++dv) - dp->dir$t_name);
3629 return &dir_static;
3632 #endif /* VMS */
3634 #endif /* NONSYSTEM_DIR_LIBRARY */
3638 set_file_times (filename, atime, mtime)
3639 char *filename;
3640 EMACS_TIME atime, mtime;
3642 #ifdef HAVE_UTIMES
3643 struct timeval tv[2];
3644 tv[0] = atime;
3645 tv[1] = mtime;
3646 return utimes (filename, tv);
3647 #else /* not HAVE_UTIMES */
3648 struct utimbuf utb;
3649 utb.actime = EMACS_SECS (atime);
3650 utb.modtime = EMACS_SECS (mtime);
3651 return utime (filename, &utb);
3652 #endif /* not HAVE_UTIMES */
3655 /* mkdir and rmdir functions, for systems which don't have them. */
3657 #ifndef HAVE_MKDIR
3659 * Written by Robert Rother, Mariah Corporation, August 1985.
3661 * If you want it, it's yours. All I ask in return is that if you
3662 * figure out how to do this in a Bourne Shell script you send me
3663 * a copy.
3664 * sdcsvax!rmr or rmr@uscd
3666 * Severely hacked over by John Gilmore to make a 4.2BSD compatible
3667 * subroutine. 11Mar86; hoptoad!gnu
3669 * Modified by rmtodd@uokmax 6-28-87 -- when making an already existing dir,
3670 * subroutine didn't return EEXIST. It does now.
3674 * Make a directory.
3676 #ifdef MKDIR_PROTOTYPE
3677 MKDIR_PROTOTYPE
3678 #else
3680 mkdir (dpath, dmode)
3681 char *dpath;
3682 int dmode;
3683 #endif
3685 int cpid, status, fd;
3686 struct stat statbuf;
3688 if (stat (dpath, &statbuf) == 0)
3690 errno = EEXIST; /* Stat worked, so it already exists */
3691 return -1;
3694 /* If stat fails for a reason other than non-existence, return error */
3695 if (errno != ENOENT)
3696 return -1;
3698 synch_process_alive = 1;
3699 switch (cpid = fork ())
3702 case -1: /* Error in fork */
3703 return (-1); /* Errno is set already */
3705 case 0: /* Child process */
3707 * Cheap hack to set mode of new directory. Since this
3708 * child process is going away anyway, we zap its umask.
3709 * FIXME, this won't suffice to set SUID, SGID, etc. on this
3710 * directory. Does anybody care?
3712 status = umask (0); /* Get current umask */
3713 status = umask (status | (0777 & ~dmode)); /* Set for mkdir */
3714 fd = emacs_open ("/dev/null", O_RDWR, 0);
3715 if (fd >= 0)
3717 dup2 (fd, 0);
3718 dup2 (fd, 1);
3719 dup2 (fd, 2);
3721 execl ("/bin/mkdir", "mkdir", dpath, (char *) 0);
3722 _exit (-1); /* Can't exec /bin/mkdir */
3724 default: /* Parent process */
3725 wait_for_termination (cpid);
3728 if (synch_process_death != 0 || synch_process_retcode != 0)
3730 errno = EIO; /* We don't know why, but */
3731 return -1; /* /bin/mkdir failed */
3734 return 0;
3736 #endif /* not HAVE_MKDIR */
3738 #ifndef HAVE_RMDIR
3740 rmdir (dpath)
3741 char *dpath;
3743 int cpid, status, fd;
3744 struct stat statbuf;
3746 if (stat (dpath, &statbuf) != 0)
3748 /* Stat just set errno. We don't have to */
3749 return -1;
3752 synch_process_alive = 1;
3753 switch (cpid = fork ())
3756 case -1: /* Error in fork */
3757 return (-1); /* Errno is set already */
3759 case 0: /* Child process */
3760 fd = emacs_open ("/dev/null", O_RDWR, 0);
3761 if (fd >= 0)
3763 dup2 (fd, 0);
3764 dup2 (fd, 1);
3765 dup2 (fd, 2);
3767 execl ("/bin/rmdir", "rmdir", dpath, (char *) 0);
3768 _exit (-1); /* Can't exec /bin/rmdir */
3770 default: /* Parent process */
3771 wait_for_termination (cpid);
3774 if (synch_process_death != 0 || synch_process_retcode != 0)
3776 errno = EIO; /* We don't know why, but */
3777 return -1; /* /bin/rmdir failed */
3780 return 0;
3782 #endif /* !HAVE_RMDIR */
3786 /* Functions for VMS */
3787 #ifdef VMS
3788 #include "vms-pwd.h"
3789 #include <acldef.h>
3790 #include <chpdef.h>
3791 #include <jpidef.h>
3793 /* Return as a string the VMS error string pertaining to STATUS.
3794 Reuses the same static buffer each time it is called. */
3796 char *
3797 vmserrstr (status)
3798 int status; /* VMS status code */
3800 int bufadr[2];
3801 short len;
3802 static char buf[257];
3804 bufadr[0] = sizeof buf - 1;
3805 bufadr[1] = (int) buf;
3806 if (! (SYS$GETMSG (status, &len, bufadr, 0x1, 0) & 1))
3807 return "untranslatable VMS error status";
3808 buf[len] = '\0';
3809 return buf;
3812 #ifdef access
3813 #undef access
3815 /* The following is necessary because 'access' emulation by VMS C (2.0) does
3816 * not work correctly. (It also doesn't work well in version 2.3.)
3819 #ifdef VMS4_4
3821 #define DESCRIPTOR(name,string) struct dsc$descriptor_s name = \
3822 { strlen (string), DSC$K_DTYPE_T, DSC$K_CLASS_S, string }
3824 typedef union {
3825 struct {
3826 unsigned short s_buflen;
3827 unsigned short s_code;
3828 char *s_bufadr;
3829 unsigned short *s_retlenadr;
3830 } s;
3831 int end;
3832 } item;
3833 #define buflen s.s_buflen
3834 #define code s.s_code
3835 #define bufadr s.s_bufadr
3836 #define retlenadr s.s_retlenadr
3838 #define R_OK 4 /* test for read permission */
3839 #define W_OK 2 /* test for write permission */
3840 #define X_OK 1 /* test for execute (search) permission */
3841 #define F_OK 0 /* test for presence of file */
3844 sys_access (path, mode)
3845 char *path;
3846 int mode;
3848 static char *user = NULL;
3849 char dir_fn[512];
3851 /* translate possible directory spec into .DIR file name, so brain-dead
3852 * access can treat the directory like a file. */
3853 if (directory_file_name (path, dir_fn))
3854 path = dir_fn;
3856 if (mode == F_OK)
3857 return access (path, mode);
3858 if (user == NULL && (user = (char *) getenv ("USER")) == NULL)
3859 return -1;
3861 int stat;
3862 int flags;
3863 int acces;
3864 unsigned short int dummy;
3865 item itemlst[3];
3866 static int constant = ACL$C_FILE;
3867 DESCRIPTOR (path_desc, path);
3868 DESCRIPTOR (user_desc, user);
3870 flags = 0;
3871 acces = 0;
3872 if ((mode & X_OK) && ((stat = access (path, mode)) < 0 || mode == X_OK))
3873 return stat;
3874 if (mode & R_OK)
3875 acces |= CHP$M_READ;
3876 if (mode & W_OK)
3877 acces |= CHP$M_WRITE;
3878 itemlst[0].buflen = sizeof (int);
3879 itemlst[0].code = CHP$_FLAGS;
3880 itemlst[0].bufadr = (char *) &flags;
3881 itemlst[0].retlenadr = &dummy;
3882 itemlst[1].buflen = sizeof (int);
3883 itemlst[1].code = CHP$_ACCESS;
3884 itemlst[1].bufadr = (char *) &acces;
3885 itemlst[1].retlenadr = &dummy;
3886 itemlst[2].end = CHP$_END;
3887 stat = SYS$CHECK_ACCESS (&constant, &path_desc, &user_desc, itemlst);
3888 return stat == SS$_NORMAL ? 0 : -1;
3892 #else /* not VMS4_4 */
3894 #include <prvdef.h>
3895 #define ACE$M_WRITE 2
3896 #define ACE$C_KEYID 1
3898 static unsigned short memid, grpid;
3899 static unsigned int uic;
3901 /* Called from init_sys_modes, so it happens not very often
3902 but at least each time Emacs is loaded. */
3903 void
3904 sys_access_reinit ()
3906 uic = 0;
3910 sys_access (filename, type)
3911 char * filename;
3912 int type;
3914 struct FAB fab;
3915 struct XABPRO xab;
3916 int status, size, i, typecode, acl_controlled;
3917 unsigned int *aclptr, *aclend, aclbuf[60];
3918 union prvdef prvmask;
3920 /* Get UIC and GRP values for protection checking. */
3921 if (uic == 0)
3923 status = LIB$GETJPI (&JPI$_UIC, 0, 0, &uic, 0, 0);
3924 if (! (status & 1))
3925 return -1;
3926 memid = uic & 0xFFFF;
3927 grpid = uic >> 16;
3930 if (type != 2) /* not checking write access */
3931 return access (filename, type);
3933 /* Check write protection. */
3935 #define CHECKPRIV(bit) (prvmask.bit)
3936 #define WRITABLE(field) (! ((xab.xab$w_pro >> field) & XAB$M_NOWRITE))
3938 /* Find privilege bits */
3939 status = SYS$SETPRV (0, 0, 0, prvmask);
3940 if (! (status & 1))
3941 error ("Unable to find privileges: %s", vmserrstr (status));
3942 if (CHECKPRIV (PRV$V_BYPASS))
3943 return 0; /* BYPASS enabled */
3944 fab = cc$rms_fab;
3945 fab.fab$b_fac = FAB$M_GET;
3946 fab.fab$l_fna = filename;
3947 fab.fab$b_fns = strlen (filename);
3948 fab.fab$l_xab = &xab;
3949 xab = cc$rms_xabpro;
3950 xab.xab$l_aclbuf = aclbuf;
3951 xab.xab$w_aclsiz = sizeof (aclbuf);
3952 status = SYS$OPEN (&fab, 0, 0);
3953 if (! (status & 1))
3954 return -1;
3955 SYS$CLOSE (&fab, 0, 0);
3956 /* Check system access */
3957 if (CHECKPRIV (PRV$V_SYSPRV) && WRITABLE (XAB$V_SYS))
3958 return 0;
3959 /* Check ACL entries, if any */
3960 acl_controlled = 0;
3961 if (xab.xab$w_acllen > 0)
3963 aclptr = aclbuf;
3964 aclend = &aclbuf[xab.xab$w_acllen / 4];
3965 while (*aclptr && aclptr < aclend)
3967 size = (*aclptr & 0xff) / 4;
3968 typecode = (*aclptr >> 8) & 0xff;
3969 if (typecode == ACE$C_KEYID)
3970 for (i = size - 1; i > 1; i--)
3971 if (aclptr[i] == uic)
3973 acl_controlled = 1;
3974 if (aclptr[1] & ACE$M_WRITE)
3975 return 0; /* Write access through ACL */
3977 aclptr = &aclptr[size];
3979 if (acl_controlled) /* ACL specified, prohibits write access */
3980 return -1;
3982 /* No ACL entries specified, check normal protection */
3983 if (WRITABLE (XAB$V_WLD)) /* World writable */
3984 return 0;
3985 if (WRITABLE (XAB$V_GRP) &&
3986 (unsigned short) (xab.xab$l_uic >> 16) == grpid)
3987 return 0; /* Group writable */
3988 if (WRITABLE (XAB$V_OWN) &&
3989 (xab.xab$l_uic & 0xFFFF) == memid)
3990 return 0; /* Owner writable */
3992 return -1; /* Not writable */
3994 #endif /* not VMS4_4 */
3995 #endif /* access */
3997 static char vtbuf[NAM$C_MAXRSS+1];
3999 /* translate a vms file spec to a unix path */
4000 char *
4001 sys_translate_vms (vfile)
4002 char * vfile;
4004 char * p;
4005 char * targ;
4007 if (!vfile)
4008 return 0;
4010 targ = vtbuf;
4012 /* leading device or logical name is a root directory */
4013 if (p = strchr (vfile, ':'))
4015 *targ++ = '/';
4016 while (vfile < p)
4017 *targ++ = *vfile++;
4018 vfile++;
4019 *targ++ = '/';
4021 p = vfile;
4022 if (*p == '[' || *p == '<')
4024 while (*++vfile != *p + 2)
4025 switch (*vfile)
4027 case '.':
4028 if (vfile[-1] == *p)
4029 *targ++ = '.';
4030 *targ++ = '/';
4031 break;
4033 case '-':
4034 *targ++ = '.';
4035 *targ++ = '.';
4036 break;
4038 default:
4039 *targ++ = *vfile;
4040 break;
4042 vfile++;
4043 *targ++ = '/';
4045 while (*vfile)
4046 *targ++ = *vfile++;
4048 return vtbuf;
4051 static char utbuf[NAM$C_MAXRSS+1];
4053 /* translate a unix path to a VMS file spec */
4054 char *
4055 sys_translate_unix (ufile)
4056 char * ufile;
4058 int slash_seen = 0;
4059 char *p;
4060 char * targ;
4062 if (!ufile)
4063 return 0;
4065 targ = utbuf;
4067 if (*ufile == '/')
4069 ufile++;
4072 while (*ufile)
4074 switch (*ufile)
4076 case '/':
4077 if (slash_seen)
4078 if (index (&ufile[1], '/'))
4079 *targ++ = '.';
4080 else
4081 *targ++ = ']';
4082 else
4084 *targ++ = ':';
4085 if (index (&ufile[1], '/'))
4086 *targ++ = '[';
4087 slash_seen = 1;
4089 break;
4091 case '.':
4092 if (strncmp (ufile, "./", 2) == 0)
4094 if (!slash_seen)
4096 *targ++ = '[';
4097 slash_seen = 1;
4099 ufile++; /* skip the dot */
4100 if (index (&ufile[1], '/'))
4101 *targ++ = '.';
4102 else
4103 *targ++ = ']';
4105 else if (strncmp (ufile, "../", 3) == 0)
4107 if (!slash_seen)
4109 *targ++ = '[';
4110 slash_seen = 1;
4112 *targ++ = '-';
4113 ufile += 2; /* skip the dots */
4114 if (index (&ufile[1], '/'))
4115 *targ++ = '.';
4116 else
4117 *targ++ = ']';
4119 else
4120 *targ++ = *ufile;
4121 break;
4123 default:
4124 *targ++ = *ufile;
4125 break;
4127 ufile++;
4129 *targ = '\0';
4131 return utbuf;
4134 char *
4135 getwd (pathname)
4136 char *pathname;
4138 char *ptr, *val;
4139 extern char *getcwd ();
4141 #define MAXPATHLEN 1024
4143 ptr = xmalloc (MAXPATHLEN);
4144 val = getcwd (ptr, MAXPATHLEN);
4145 if (val == 0)
4147 xfree (ptr);
4148 return val;
4150 strcpy (pathname, ptr);
4151 xfree (ptr);
4153 return pathname;
4157 getppid ()
4159 long item_code = JPI$_OWNER;
4160 unsigned long parent_id;
4161 int status;
4163 if (((status = LIB$GETJPI (&item_code, 0, 0, &parent_id)) & 1) == 0)
4165 errno = EVMSERR;
4166 vaxc$errno = status;
4167 return -1;
4169 return parent_id;
4172 #undef getuid
4173 unsigned
4174 sys_getuid ()
4176 return (getgid () << 16) | getuid ();
4179 #undef read
4181 sys_read (fildes, buf, nbyte)
4182 int fildes;
4183 char *buf;
4184 unsigned int nbyte;
4186 return read (fildes, buf, (nbyte < MAXIOSIZE ? nbyte : MAXIOSIZE));
4189 #if 0
4191 sys_write (fildes, buf, nbyte)
4192 int fildes;
4193 char *buf;
4194 unsigned int nbyte;
4196 register int nwrote, rtnval = 0;
4198 while (nbyte > MAXIOSIZE && (nwrote = write (fildes, buf, MAXIOSIZE)) > 0) {
4199 nbyte -= nwrote;
4200 buf += nwrote;
4201 rtnval += nwrote;
4203 if (nwrote < 0)
4204 return rtnval ? rtnval : -1;
4205 if ((nwrote = write (fildes, buf, nbyte)) < 0)
4206 return rtnval ? rtnval : -1;
4207 return (rtnval + nwrote);
4209 #endif /* 0 */
4212 * VAX/VMS VAX C RTL really loses. It insists that records
4213 * end with a newline (carriage return) character, and if they
4214 * don't it adds one (nice of it isn't it!)
4216 * Thus we do this stupidity below.
4219 #undef write
4221 sys_write (fildes, buf, nbytes)
4222 int fildes;
4223 char *buf;
4224 unsigned int nbytes;
4226 register char *p;
4227 register char *e;
4228 int sum = 0;
4229 struct stat st;
4231 fstat (fildes, &st);
4232 p = buf;
4233 while (nbytes > 0)
4235 int len, retval;
4237 /* Handle fixed-length files with carriage control. */
4238 if (st.st_fab_rfm == FAB$C_FIX
4239 && ((st.st_fab_rat & (FAB$M_FTN | FAB$M_CR)) != 0))
4241 len = st.st_fab_mrs;
4242 retval = write (fildes, p, min (len, nbytes));
4243 if (retval != len)
4244 return -1;
4245 retval++; /* This skips the implied carriage control */
4247 else
4249 e = p + min (MAXIOSIZE, nbytes) - 1;
4250 while (*e != '\n' && e > p) e--;
4251 if (p == e) /* Ok.. so here we add a newline... sigh. */
4252 e = p + min (MAXIOSIZE, nbytes) - 1;
4253 len = e + 1 - p;
4254 retval = write (fildes, p, len);
4255 if (retval != len)
4256 return -1;
4258 p += retval;
4259 sum += retval;
4260 nbytes -= retval;
4262 return sum;
4265 /* Create file NEW copying its attributes from file OLD. If
4266 OLD is 0 or does not exist, create based on the value of
4267 vms_stmlf_recfm. */
4269 /* Protection value the file should ultimately have.
4270 Set by create_copy_attrs, and use by rename_sansversions. */
4271 static unsigned short int fab_final_pro;
4274 creat_copy_attrs (old, new)
4275 char *old, *new;
4277 struct FAB fab = cc$rms_fab;
4278 struct XABPRO xabpro;
4279 char aclbuf[256]; /* Choice of size is arbitrary. See below. */
4280 extern int vms_stmlf_recfm;
4282 if (old)
4284 fab.fab$b_fac = FAB$M_GET;
4285 fab.fab$l_fna = old;
4286 fab.fab$b_fns = strlen (old);
4287 fab.fab$l_xab = (char *) &xabpro;
4288 xabpro = cc$rms_xabpro;
4289 xabpro.xab$l_aclbuf = aclbuf;
4290 xabpro.xab$w_aclsiz = sizeof aclbuf;
4291 /* Call $OPEN to fill in the fab & xabpro fields. */
4292 if (SYS$OPEN (&fab, 0, 0) & 1)
4294 SYS$CLOSE (&fab, 0, 0);
4295 fab.fab$l_alq = 0; /* zero the allocation quantity */
4296 if (xabpro.xab$w_acllen > 0)
4298 if (xabpro.xab$w_acllen > sizeof aclbuf)
4299 /* If the acl buffer was too short, redo open with longer one.
4300 Wouldn't need to do this if there were some system imposed
4301 limit on the size of an ACL, but I can't find any such. */
4303 xabpro.xab$l_aclbuf = (char *) alloca (xabpro.xab$w_acllen);
4304 xabpro.xab$w_aclsiz = xabpro.xab$w_acllen;
4305 if (SYS$OPEN (&fab, 0, 0) & 1)
4306 SYS$CLOSE (&fab, 0, 0);
4307 else
4308 old = 0;
4311 else
4312 xabpro.xab$l_aclbuf = 0;
4314 else
4315 old = 0;
4317 fab.fab$l_fna = new;
4318 fab.fab$b_fns = strlen (new);
4319 if (!old)
4321 fab.fab$l_xab = 0;
4322 fab.fab$b_rfm = vms_stmlf_recfm ? FAB$C_STMLF : FAB$C_VAR;
4323 fab.fab$b_rat = FAB$M_CR;
4326 /* Set the file protections such that we will be able to manipulate
4327 this file. Once we are done writing and renaming it, we will set
4328 the protections back. */
4329 if (old)
4330 fab_final_pro = xabpro.xab$w_pro;
4331 else
4332 SYS$SETDFPROT (0, &fab_final_pro);
4333 xabpro.xab$w_pro &= 0xff0f; /* set O:rewd for now. This is set back later. */
4335 /* Create the new file with either default attrs or attrs copied
4336 from old file. */
4337 if (!(SYS$CREATE (&fab, 0, 0) & 1))
4338 return -1;
4339 SYS$CLOSE (&fab, 0, 0);
4340 /* As this is a "replacement" for creat, return a file descriptor
4341 opened for writing. */
4342 return open (new, O_WRONLY);
4345 #ifdef creat
4346 #undef creat
4347 #include <varargs.h>
4348 #ifdef __GNUC__
4349 #ifndef va_count
4350 #define va_count(X) ((X) = *(((int *) &(va_alist)) - 1))
4351 #endif
4352 #endif
4355 sys_creat (va_alist)
4356 va_dcl
4358 va_list list_incrementer;
4359 char *name;
4360 int mode;
4361 int rfd; /* related file descriptor */
4362 int fd; /* Our new file descriptor */
4363 int count;
4364 struct stat st_buf;
4365 char rfm[12];
4366 char rat[15];
4367 char mrs[13];
4368 char fsz[13];
4369 extern int vms_stmlf_recfm;
4371 va_count (count);
4372 va_start (list_incrementer);
4373 name = va_arg (list_incrementer, char *);
4374 mode = va_arg (list_incrementer, int);
4375 if (count > 2)
4376 rfd = va_arg (list_incrementer, int);
4377 va_end (list_incrementer);
4378 if (count > 2)
4380 /* Use information from the related file descriptor to set record
4381 format of the newly created file. */
4382 fstat (rfd, &st_buf);
4383 switch (st_buf.st_fab_rfm)
4385 case FAB$C_FIX:
4386 strcpy (rfm, "rfm = fix");
4387 sprintf (mrs, "mrs = %d", st_buf.st_fab_mrs);
4388 strcpy (rat, "rat = ");
4389 if (st_buf.st_fab_rat & FAB$M_CR)
4390 strcat (rat, "cr");
4391 else if (st_buf.st_fab_rat & FAB$M_FTN)
4392 strcat (rat, "ftn");
4393 else if (st_buf.st_fab_rat & FAB$M_PRN)
4394 strcat (rat, "prn");
4395 if (st_buf.st_fab_rat & FAB$M_BLK)
4396 if (st_buf.st_fab_rat & (FAB$M_CR|FAB$M_FTN|FAB$M_PRN))
4397 strcat (rat, ", blk");
4398 else
4399 strcat (rat, "blk");
4400 return creat (name, 0, rfm, rat, mrs);
4402 case FAB$C_VFC:
4403 strcpy (rfm, "rfm = vfc");
4404 sprintf (fsz, "fsz = %d", st_buf.st_fab_fsz);
4405 strcpy (rat, "rat = ");
4406 if (st_buf.st_fab_rat & FAB$M_CR)
4407 strcat (rat, "cr");
4408 else if (st_buf.st_fab_rat & FAB$M_FTN)
4409 strcat (rat, "ftn");
4410 else if (st_buf.st_fab_rat & FAB$M_PRN)
4411 strcat (rat, "prn");
4412 if (st_buf.st_fab_rat & FAB$M_BLK)
4413 if (st_buf.st_fab_rat & (FAB$M_CR|FAB$M_FTN|FAB$M_PRN))
4414 strcat (rat, ", blk");
4415 else
4416 strcat (rat, "blk");
4417 return creat (name, 0, rfm, rat, fsz);
4419 case FAB$C_STM:
4420 strcpy (rfm, "rfm = stm");
4421 break;
4423 case FAB$C_STMCR:
4424 strcpy (rfm, "rfm = stmcr");
4425 break;
4427 case FAB$C_STMLF:
4428 strcpy (rfm, "rfm = stmlf");
4429 break;
4431 case FAB$C_UDF:
4432 strcpy (rfm, "rfm = udf");
4433 break;
4435 case FAB$C_VAR:
4436 strcpy (rfm, "rfm = var");
4437 break;
4439 strcpy (rat, "rat = ");
4440 if (st_buf.st_fab_rat & FAB$M_CR)
4441 strcat (rat, "cr");
4442 else if (st_buf.st_fab_rat & FAB$M_FTN)
4443 strcat (rat, "ftn");
4444 else if (st_buf.st_fab_rat & FAB$M_PRN)
4445 strcat (rat, "prn");
4446 if (st_buf.st_fab_rat & FAB$M_BLK)
4447 if (st_buf.st_fab_rat & (FAB$M_CR|FAB$M_FTN|FAB$M_PRN))
4448 strcat (rat, ", blk");
4449 else
4450 strcat (rat, "blk");
4452 else
4454 strcpy (rfm, vms_stmlf_recfm ? "rfm = stmlf" : "rfm=var");
4455 strcpy (rat, "rat=cr");
4457 /* Until the VAX C RTL fixes the many bugs with modes, always use
4458 mode 0 to get the user's default protection. */
4459 fd = creat (name, 0, rfm, rat);
4460 if (fd < 0 && errno == EEXIST)
4462 if (unlink (name) < 0)
4463 report_file_error ("delete", build_string (name));
4464 fd = creat (name, 0, rfm, rat);
4466 return fd;
4468 #endif /* creat */
4470 /* fwrite to stdout is S L O W. Speed it up by using fputc...*/
4472 sys_fwrite (ptr, size, num, fp)
4473 register char * ptr;
4474 FILE * fp;
4476 register int tot = num * size;
4478 while (tot--)
4479 fputc (*ptr++, fp);
4480 return num;
4484 * The VMS C library routine creat actually creates a new version of an
4485 * existing file rather than truncating the old version. There are times
4486 * when this is not the desired behavior, for instance, when writing an
4487 * auto save file (you only want one version), or when you don't have
4488 * write permission in the directory containing the file (but the file
4489 * itself is writable). Hence this routine, which is equivalent to
4490 * "close (creat (fn, 0));" on Unix if fn already exists.
4493 vms_truncate (fn)
4494 char *fn;
4496 struct FAB xfab = cc$rms_fab;
4497 struct RAB xrab = cc$rms_rab;
4498 int status;
4500 xfab.fab$l_fop = FAB$M_TEF; /* free allocated but unused blocks on close */
4501 xfab.fab$b_fac = FAB$M_TRN | FAB$M_GET; /* allow truncate and get access */
4502 xfab.fab$b_shr = FAB$M_NIL; /* allow no sharing - file must be locked */
4503 xfab.fab$l_fna = fn;
4504 xfab.fab$b_fns = strlen (fn);
4505 xfab.fab$l_dna = ";0"; /* default to latest version of the file */
4506 xfab.fab$b_dns = 2;
4507 xrab.rab$l_fab = &xfab;
4509 /* This gibberish opens the file, positions to the first record, and
4510 deletes all records from there until the end of file. */
4511 if ((SYS$OPEN (&xfab) & 01) == 01)
4513 if ((SYS$CONNECT (&xrab) & 01) == 01 &&
4514 (SYS$FIND (&xrab) & 01) == 01 &&
4515 (SYS$TRUNCATE (&xrab) & 01) == 01)
4516 status = 0;
4517 else
4518 status = -1;
4520 else
4521 status = -1;
4522 SYS$CLOSE (&xfab);
4523 return status;
4526 /* Define this symbol to actually read SYSUAF.DAT. This requires either
4527 SYSPRV or a readable SYSUAF.DAT. */
4529 #ifdef READ_SYSUAF
4531 * getuaf.c
4533 * Routine to read the VMS User Authorization File and return
4534 * a specific user's record.
4537 static struct UAF retuaf;
4539 struct UAF *
4540 get_uaf_name (uname)
4541 char * uname;
4543 register status;
4544 struct FAB uaf_fab;
4545 struct RAB uaf_rab;
4547 uaf_fab = cc$rms_fab;
4548 uaf_rab = cc$rms_rab;
4549 /* initialize fab fields */
4550 uaf_fab.fab$l_fna = "SYS$SYSTEM:SYSUAF.DAT";
4551 uaf_fab.fab$b_fns = 21;
4552 uaf_fab.fab$b_fac = FAB$M_GET;
4553 uaf_fab.fab$b_org = FAB$C_IDX;
4554 uaf_fab.fab$b_shr = FAB$M_GET|FAB$M_PUT|FAB$M_UPD|FAB$M_DEL;
4555 /* initialize rab fields */
4556 uaf_rab.rab$l_fab = &uaf_fab;
4557 /* open the User Authorization File */
4558 status = SYS$OPEN (&uaf_fab);
4559 if (!(status&1))
4561 errno = EVMSERR;
4562 vaxc$errno = status;
4563 return 0;
4565 status = SYS$CONNECT (&uaf_rab);
4566 if (!(status&1))
4568 errno = EVMSERR;
4569 vaxc$errno = status;
4570 return 0;
4572 /* read the requested record - index is in uname */
4573 uaf_rab.rab$l_kbf = uname;
4574 uaf_rab.rab$b_ksz = strlen (uname);
4575 uaf_rab.rab$b_rac = RAB$C_KEY;
4576 uaf_rab.rab$l_ubf = (char *)&retuaf;
4577 uaf_rab.rab$w_usz = sizeof retuaf;
4578 status = SYS$GET (&uaf_rab);
4579 if (!(status&1))
4581 errno = EVMSERR;
4582 vaxc$errno = status;
4583 return 0;
4585 /* close the User Authorization File */
4586 status = SYS$DISCONNECT (&uaf_rab);
4587 if (!(status&1))
4589 errno = EVMSERR;
4590 vaxc$errno = status;
4591 return 0;
4593 status = SYS$CLOSE (&uaf_fab);
4594 if (!(status&1))
4596 errno = EVMSERR;
4597 vaxc$errno = status;
4598 return 0;
4600 return &retuaf;
4603 struct UAF *
4604 get_uaf_uic (uic)
4605 unsigned long uic;
4607 register status;
4608 struct FAB uaf_fab;
4609 struct RAB uaf_rab;
4611 uaf_fab = cc$rms_fab;
4612 uaf_rab = cc$rms_rab;
4613 /* initialize fab fields */
4614 uaf_fab.fab$l_fna = "SYS$SYSTEM:SYSUAF.DAT";
4615 uaf_fab.fab$b_fns = 21;
4616 uaf_fab.fab$b_fac = FAB$M_GET;
4617 uaf_fab.fab$b_org = FAB$C_IDX;
4618 uaf_fab.fab$b_shr = FAB$M_GET|FAB$M_PUT|FAB$M_UPD|FAB$M_DEL;
4619 /* initialize rab fields */
4620 uaf_rab.rab$l_fab = &uaf_fab;
4621 /* open the User Authorization File */
4622 status = SYS$OPEN (&uaf_fab);
4623 if (!(status&1))
4625 errno = EVMSERR;
4626 vaxc$errno = status;
4627 return 0;
4629 status = SYS$CONNECT (&uaf_rab);
4630 if (!(status&1))
4632 errno = EVMSERR;
4633 vaxc$errno = status;
4634 return 0;
4636 /* read the requested record - index is in uic */
4637 uaf_rab.rab$b_krf = 1; /* 1st alternate key */
4638 uaf_rab.rab$l_kbf = (char *) &uic;
4639 uaf_rab.rab$b_ksz = sizeof uic;
4640 uaf_rab.rab$b_rac = RAB$C_KEY;
4641 uaf_rab.rab$l_ubf = (char *)&retuaf;
4642 uaf_rab.rab$w_usz = sizeof retuaf;
4643 status = SYS$GET (&uaf_rab);
4644 if (!(status&1))
4646 errno = EVMSERR;
4647 vaxc$errno = status;
4648 return 0;
4650 /* close the User Authorization File */
4651 status = SYS$DISCONNECT (&uaf_rab);
4652 if (!(status&1))
4654 errno = EVMSERR;
4655 vaxc$errno = status;
4656 return 0;
4658 status = SYS$CLOSE (&uaf_fab);
4659 if (!(status&1))
4661 errno = EVMSERR;
4662 vaxc$errno = status;
4663 return 0;
4665 return &retuaf;
4668 static struct passwd retpw;
4670 struct passwd *
4671 cnv_uaf_pw (up)
4672 struct UAF * up;
4674 char * ptr;
4676 /* copy these out first because if the username is 32 chars, the next
4677 section will overwrite the first byte of the UIC */
4678 retpw.pw_uid = up->uaf$w_mem;
4679 retpw.pw_gid = up->uaf$w_grp;
4681 /* I suppose this is not the best style, to possibly overwrite one
4682 byte beyond the end of the field, but what the heck... */
4683 ptr = &up->uaf$t_username[UAF$S_USERNAME];
4684 while (ptr[-1] == ' ')
4685 ptr--;
4686 *ptr = '\0';
4687 strcpy (retpw.pw_name, up->uaf$t_username);
4689 /* the rest of these are counted ascii strings */
4690 strncpy (retpw.pw_gecos, &up->uaf$t_owner[1], up->uaf$t_owner[0]);
4691 retpw.pw_gecos[up->uaf$t_owner[0]] = '\0';
4692 strncpy (retpw.pw_dir, &up->uaf$t_defdev[1], up->uaf$t_defdev[0]);
4693 retpw.pw_dir[up->uaf$t_defdev[0]] = '\0';
4694 strncat (retpw.pw_dir, &up->uaf$t_defdir[1], up->uaf$t_defdir[0]);
4695 retpw.pw_dir[up->uaf$t_defdev[0] + up->uaf$t_defdir[0]] = '\0';
4696 strncpy (retpw.pw_shell, &up->uaf$t_defcli[1], up->uaf$t_defcli[0]);
4697 retpw.pw_shell[up->uaf$t_defcli[0]] = '\0';
4699 return &retpw;
4701 #else /* not READ_SYSUAF */
4702 static struct passwd retpw;
4703 #endif /* not READ_SYSUAF */
4705 struct passwd *
4706 getpwnam (name)
4707 char * name;
4709 #ifdef READ_SYSUAF
4710 struct UAF *up;
4711 #else
4712 char * user;
4713 char * dir;
4714 unsigned char * full;
4715 #endif /* READ_SYSUAF */
4716 char *ptr = name;
4718 while (*ptr)
4720 if ('a' <= *ptr && *ptr <= 'z')
4721 *ptr -= 040;
4722 ptr++;
4724 #ifdef READ_SYSUAF
4725 if (!(up = get_uaf_name (name)))
4726 return 0;
4727 return cnv_uaf_pw (up);
4728 #else
4729 if (strcmp (name, getenv ("USER")) == 0)
4731 retpw.pw_uid = getuid ();
4732 retpw.pw_gid = getgid ();
4733 strcpy (retpw.pw_name, name);
4734 if (full = egetenv ("FULLNAME"))
4735 strcpy (retpw.pw_gecos, full);
4736 else
4737 *retpw.pw_gecos = '\0';
4738 strcpy (retpw.pw_dir, egetenv ("HOME"));
4739 *retpw.pw_shell = '\0';
4740 return &retpw;
4742 else
4743 return 0;
4744 #endif /* not READ_SYSUAF */
4747 struct passwd *
4748 getpwuid (uid)
4749 unsigned long uid;
4751 #ifdef READ_SYSUAF
4752 struct UAF * up;
4754 if (!(up = get_uaf_uic (uid)))
4755 return 0;
4756 return cnv_uaf_pw (up);
4757 #else
4758 if (uid == sys_getuid ())
4759 return getpwnam (egetenv ("USER"));
4760 else
4761 return 0;
4762 #endif /* not READ_SYSUAF */
4765 /* return total address space available to the current process. This is
4766 the sum of the current p0 size, p1 size and free page table entries
4767 available. */
4769 vlimit ()
4771 int item_code;
4772 unsigned long free_pages;
4773 unsigned long frep0va;
4774 unsigned long frep1va;
4775 register status;
4777 item_code = JPI$_FREPTECNT;
4778 if (((status = LIB$GETJPI (&item_code, 0, 0, &free_pages)) & 1) == 0)
4780 errno = EVMSERR;
4781 vaxc$errno = status;
4782 return -1;
4784 free_pages *= 512;
4786 item_code = JPI$_FREP0VA;
4787 if (((status = LIB$GETJPI (&item_code, 0, 0, &frep0va)) & 1) == 0)
4789 errno = EVMSERR;
4790 vaxc$errno = status;
4791 return -1;
4793 item_code = JPI$_FREP1VA;
4794 if (((status = LIB$GETJPI (&item_code, 0, 0, &frep1va)) & 1) == 0)
4796 errno = EVMSERR;
4797 vaxc$errno = status;
4798 return -1;
4801 return free_pages + frep0va + (0x7fffffff - frep1va);
4805 define_logical_name (varname, string)
4806 char *varname;
4807 char *string;
4809 struct dsc$descriptor_s strdsc =
4810 {strlen (string), DSC$K_DTYPE_T, DSC$K_CLASS_S, string};
4811 struct dsc$descriptor_s envdsc =
4812 {strlen (varname), DSC$K_DTYPE_T, DSC$K_CLASS_S, varname};
4813 struct dsc$descriptor_s lnmdsc =
4814 {7, DSC$K_DTYPE_T, DSC$K_CLASS_S, "LNM$JOB"};
4816 return LIB$SET_LOGICAL (&envdsc, &strdsc, &lnmdsc, 0, 0);
4820 delete_logical_name (varname)
4821 char *varname;
4823 struct dsc$descriptor_s envdsc =
4824 {strlen (varname), DSC$K_DTYPE_T, DSC$K_CLASS_S, varname};
4825 struct dsc$descriptor_s lnmdsc =
4826 {7, DSC$K_DTYPE_T, DSC$K_CLASS_S, "LNM$JOB"};
4828 return LIB$DELETE_LOGICAL (&envdsc, &lnmdsc);
4832 ulimit ()
4834 return 0;
4838 setpgrp ()
4840 return 0;
4844 execvp ()
4846 error ("execvp system call not implemented");
4847 return -1;
4851 rename (from, to)
4852 char *from, *to;
4854 int status;
4855 struct FAB from_fab = cc$rms_fab, to_fab = cc$rms_fab;
4856 struct NAM from_nam = cc$rms_nam, to_nam = cc$rms_nam;
4857 char from_esn[NAM$C_MAXRSS];
4858 char to_esn[NAM$C_MAXRSS];
4860 from_fab.fab$l_fna = from;
4861 from_fab.fab$b_fns = strlen (from);
4862 from_fab.fab$l_nam = &from_nam;
4863 from_fab.fab$l_fop = FAB$M_NAM;
4865 from_nam.nam$l_esa = from_esn;
4866 from_nam.nam$b_ess = sizeof from_esn;
4868 to_fab.fab$l_fna = to;
4869 to_fab.fab$b_fns = strlen (to);
4870 to_fab.fab$l_nam = &to_nam;
4871 to_fab.fab$l_fop = FAB$M_NAM;
4873 to_nam.nam$l_esa = to_esn;
4874 to_nam.nam$b_ess = sizeof to_esn;
4876 status = SYS$RENAME (&from_fab, 0, 0, &to_fab);
4878 if (status & 1)
4879 return 0;
4880 else
4882 if (status == RMS$_DEV)
4883 errno = EXDEV;
4884 else
4885 errno = EVMSERR;
4886 vaxc$errno = status;
4887 return -1;
4891 /* This function renames a file like `rename', but it strips
4892 the version number from the "to" filename, such that the "to" file is
4893 will always be a new version. It also sets the file protection once it is
4894 finished. The protection that we will use is stored in fab_final_pro,
4895 and was set when we did a creat_copy_attrs to create the file that we
4896 are renaming.
4898 We could use the chmod function, but Eunichs uses 3 bits per user category
4899 to describe the protection, and VMS uses 4 (write and delete are separate
4900 bits). To maintain portability, the VMS implementation of `chmod' wires
4901 the W and D bits together. */
4904 static struct fibdef fib; /* We need this initialized to zero */
4905 char vms_file_written[NAM$C_MAXRSS];
4908 rename_sans_version (from,to)
4909 char *from, *to;
4911 short int chan;
4912 int stat;
4913 short int iosb[4];
4914 int status;
4915 struct FAB to_fab = cc$rms_fab;
4916 struct NAM to_nam = cc$rms_nam;
4917 struct dsc$descriptor fib_d ={sizeof (fib),0,0,(char*) &fib};
4918 struct dsc$descriptor fib_attr[2]
4919 = {{sizeof (fab_final_pro),ATR$C_FPRO,0,(char*) &fab_final_pro},{0,0,0,0}};
4920 char to_esn[NAM$C_MAXRSS];
4922 $DESCRIPTOR (disk,to_esn);
4924 to_fab.fab$l_fna = to;
4925 to_fab.fab$b_fns = strlen (to);
4926 to_fab.fab$l_nam = &to_nam;
4927 to_fab.fab$l_fop = FAB$M_NAM;
4929 to_nam.nam$l_esa = to_esn;
4930 to_nam.nam$b_ess = sizeof to_esn;
4932 status = SYS$PARSE (&to_fab, 0, 0); /* figure out the full file name */
4934 if (to_nam.nam$l_fnb && NAM$M_EXP_VER)
4935 *(to_nam.nam$l_ver) = '\0';
4937 stat = rename (from, to_esn);
4938 if (stat < 0)
4939 return stat;
4941 strcpy (vms_file_written, to_esn);
4943 to_fab.fab$l_fna = vms_file_written; /* this points to the versionless name */
4944 to_fab.fab$b_fns = strlen (vms_file_written);
4946 /* Now set the file protection to the correct value */
4947 SYS$OPEN (&to_fab, 0, 0); /* This fills in the nam$w_fid fields */
4949 /* Copy these fields into the fib */
4950 fib.fib$r_fid_overlay.fib$w_fid[0] = to_nam.nam$w_fid[0];
4951 fib.fib$r_fid_overlay.fib$w_fid[1] = to_nam.nam$w_fid[1];
4952 fib.fib$r_fid_overlay.fib$w_fid[2] = to_nam.nam$w_fid[2];
4954 SYS$CLOSE (&to_fab, 0, 0);
4956 stat = SYS$ASSIGN (&disk, &chan, 0, 0); /* open a channel to the disk */
4957 if (!stat)
4958 LIB$SIGNAL (stat);
4959 stat = SYS$QIOW (0, chan, IO$_MODIFY, iosb, 0, 0, &fib_d,
4960 0, 0, 0, &fib_attr, 0);
4961 if (!stat)
4962 LIB$SIGNAL (stat);
4963 stat = SYS$DASSGN (chan);
4964 if (!stat)
4965 LIB$SIGNAL (stat);
4966 strcpy (vms_file_written, to_esn); /* We will write this to the terminal*/
4967 return 0;
4971 link (file, new)
4972 char * file, * new;
4974 register status;
4975 struct FAB fab;
4976 struct NAM nam;
4977 unsigned short fid[3];
4978 char esa[NAM$C_MAXRSS];
4980 fab = cc$rms_fab;
4981 fab.fab$l_fop = FAB$M_OFP;
4982 fab.fab$l_fna = file;
4983 fab.fab$b_fns = strlen (file);
4984 fab.fab$l_nam = &nam;
4986 nam = cc$rms_nam;
4987 nam.nam$l_esa = esa;
4988 nam.nam$b_ess = NAM$C_MAXRSS;
4990 status = SYS$PARSE (&fab);
4991 if ((status & 1) == 0)
4993 errno = EVMSERR;
4994 vaxc$errno = status;
4995 return -1;
4997 status = SYS$SEARCH (&fab);
4998 if ((status & 1) == 0)
5000 errno = EVMSERR;
5001 vaxc$errno = status;
5002 return -1;
5005 fid[0] = nam.nam$w_fid[0];
5006 fid[1] = nam.nam$w_fid[1];
5007 fid[2] = nam.nam$w_fid[2];
5009 fab.fab$l_fna = new;
5010 fab.fab$b_fns = strlen (new);
5012 status = SYS$PARSE (&fab);
5013 if ((status & 1) == 0)
5015 errno = EVMSERR;
5016 vaxc$errno = status;
5017 return -1;
5020 nam.nam$w_fid[0] = fid[0];
5021 nam.nam$w_fid[1] = fid[1];
5022 nam.nam$w_fid[2] = fid[2];
5024 nam.nam$l_esa = nam.nam$l_name;
5025 nam.nam$b_esl = nam.nam$b_name + nam.nam$b_type + nam.nam$b_ver;
5027 status = SYS$ENTER (&fab);
5028 if ((status & 1) == 0)
5030 errno = EVMSERR;
5031 vaxc$errno = status;
5032 return -1;
5035 return 0;
5038 void
5039 croak (badfunc)
5040 char *badfunc;
5042 printf ("%s not yet implemented\r\n", badfunc);
5043 reset_sys_modes ();
5044 exit (1);
5047 long
5048 random ()
5050 /* Arrange to return a range centered on zero. */
5051 return rand () - (1 << 30);
5054 void
5055 srandom (seed)
5057 srand (seed);
5059 #endif /* VMS */
5061 #ifdef AIXHFT
5063 /* Called from init_sys_modes. */
5064 void
5065 hft_init ()
5067 int junk;
5069 /* If we're not on an HFT we shouldn't do any of this. We determine
5070 if we are on an HFT by trying to get an HFT error code. If this
5071 call fails, we're not on an HFT. */
5072 #ifdef IBMR2AIX
5073 if (ioctl (0, HFQERROR, &junk) < 0)
5074 return;
5075 #else /* not IBMR2AIX */
5076 if (ioctl (0, HFQEIO, 0) < 0)
5077 return;
5078 #endif /* not IBMR2AIX */
5080 /* On AIX the default hft keyboard mapping uses backspace rather than delete
5081 as the rubout key's ASCII code. Here this is changed. The bug is that
5082 there's no way to determine the old mapping, so in reset_sys_modes
5083 we need to assume that the normal map had been present. Of course, this
5084 code also doesn't help if on a terminal emulator which doesn't understand
5085 HFT VTD's. */
5087 struct hfbuf buf;
5088 struct hfkeymap keymap;
5090 buf.hf_bufp = (char *)&keymap;
5091 buf.hf_buflen = sizeof (keymap);
5092 keymap.hf_nkeys = 2;
5093 keymap.hfkey[0].hf_kpos = 15;
5094 keymap.hfkey[0].hf_kstate = HFMAPCHAR | HFSHFNONE;
5095 #ifdef IBMR2AIX
5096 keymap.hfkey[0].hf_keyidh = '<';
5097 #else /* not IBMR2AIX */
5098 keymap.hfkey[0].hf_page = '<';
5099 #endif /* not IBMR2AIX */
5100 keymap.hfkey[0].hf_char = 127;
5101 keymap.hfkey[1].hf_kpos = 15;
5102 keymap.hfkey[1].hf_kstate = HFMAPCHAR | HFSHFSHFT;
5103 #ifdef IBMR2AIX
5104 keymap.hfkey[1].hf_keyidh = '<';
5105 #else /* not IBMR2AIX */
5106 keymap.hfkey[1].hf_page = '<';
5107 #endif /* not IBMR2AIX */
5108 keymap.hfkey[1].hf_char = 127;
5109 hftctl (0, HFSKBD, &buf);
5111 /* The HFT system on AIX doesn't optimize for scrolling, so it's really ugly
5112 at times. */
5113 line_ins_del_ok = char_ins_del_ok = 0;
5116 /* Reset the rubout key to backspace. */
5118 void
5119 hft_reset ()
5121 struct hfbuf buf;
5122 struct hfkeymap keymap;
5123 int junk;
5125 #ifdef IBMR2AIX
5126 if (ioctl (0, HFQERROR, &junk) < 0)
5127 return;
5128 #else /* not IBMR2AIX */
5129 if (ioctl (0, HFQEIO, 0) < 0)
5130 return;
5131 #endif /* not IBMR2AIX */
5133 buf.hf_bufp = (char *)&keymap;
5134 buf.hf_buflen = sizeof (keymap);
5135 keymap.hf_nkeys = 2;
5136 keymap.hfkey[0].hf_kpos = 15;
5137 keymap.hfkey[0].hf_kstate = HFMAPCHAR | HFSHFNONE;
5138 #ifdef IBMR2AIX
5139 keymap.hfkey[0].hf_keyidh = '<';
5140 #else /* not IBMR2AIX */
5141 keymap.hfkey[0].hf_page = '<';
5142 #endif /* not IBMR2AIX */
5143 keymap.hfkey[0].hf_char = 8;
5144 keymap.hfkey[1].hf_kpos = 15;
5145 keymap.hfkey[1].hf_kstate = HFMAPCHAR | HFSHFSHFT;
5146 #ifdef IBMR2AIX
5147 keymap.hfkey[1].hf_keyidh = '<';
5148 #else /* not IBMR2AIX */
5149 keymap.hfkey[1].hf_page = '<';
5150 #endif /* not IBMR2AIX */
5151 keymap.hfkey[1].hf_char = 8;
5152 hftctl (0, HFSKBD, &buf);
5155 #endif /* AIXHFT */
5157 #ifdef USE_DL_STUBS
5159 /* These are included on Sunos 4.1 when we do not use shared libraries.
5160 X11 libraries may refer to these functions but (we hope) do not
5161 actually call them. */
5163 void *
5164 dlopen ()
5166 return 0;
5169 void *
5170 dlsym ()
5172 return 0;
5176 dlclose ()
5178 return -1;
5181 #endif /* USE_DL_STUBS */
5183 #ifndef BSTRING
5185 #ifndef bzero
5187 void
5188 bzero (b, length)
5189 register char *b;
5190 register int length;
5192 #ifdef VMS
5193 short zero = 0;
5194 long max_str = 65535;
5196 while (length > max_str) {
5197 (void) LIB$MOVC5 (&zero, &zero, &zero, &max_str, b);
5198 length -= max_str;
5199 b += max_str;
5201 max_str = length;
5202 (void) LIB$MOVC5 (&zero, &zero, &zero, &max_str, b);
5203 #else
5204 while (length-- > 0)
5205 *b++ = 0;
5206 #endif /* not VMS */
5209 #endif /* no bzero */
5210 #endif /* BSTRING */
5212 #if (!defined (BSTRING) && !defined (bcopy)) || defined (NEED_BCOPY)
5213 #undef bcopy
5215 /* Saying `void' requires a declaration, above, where bcopy is used
5216 and that declaration causes pain for systems where bcopy is a macro. */
5217 bcopy (b1, b2, length)
5218 register char *b1;
5219 register char *b2;
5220 register int length;
5222 #ifdef VMS
5223 long max_str = 65535;
5225 while (length > max_str) {
5226 (void) LIB$MOVC3 (&max_str, b1, b2);
5227 length -= max_str;
5228 b1 += max_str;
5229 b2 += max_str;
5231 max_str = length;
5232 (void) LIB$MOVC3 (&length, b1, b2);
5233 #else
5234 while (length-- > 0)
5235 *b2++ = *b1++;
5236 #endif /* not VMS */
5238 #endif /* (!defined (BSTRING) && !defined (bcopy)) || defined (NEED_BCOPY) */
5240 #ifndef BSTRING
5241 #ifndef bcmp
5243 bcmp (b1, b2, length) /* This could be a macro! */
5244 register char *b1;
5245 register char *b2;
5246 register int length;
5248 #ifdef VMS
5249 struct dsc$descriptor_s src1 = {length, DSC$K_DTYPE_T, DSC$K_CLASS_S, b1};
5250 struct dsc$descriptor_s src2 = {length, DSC$K_DTYPE_T, DSC$K_CLASS_S, b2};
5252 return STR$COMPARE (&src1, &src2);
5253 #else
5254 while (length-- > 0)
5255 if (*b1++ != *b2++)
5256 return 1;
5258 return 0;
5259 #endif /* not VMS */
5261 #endif /* no bcmp */
5262 #endif /* not BSTRING */
5264 #ifndef HAVE_STRSIGNAL
5265 char *
5266 strsignal (code)
5267 int code;
5269 char *signame = 0;
5271 if (0 <= code && code < NSIG)
5273 #ifdef VMS
5274 signame = sys_errlist[code];
5275 #else
5276 /* Cast to suppress warning if the table has const char *. */
5277 signame = (char *) sys_siglist[code];
5278 #endif
5281 return signame;
5283 #endif /* HAVE_STRSIGNAL */
5285 /* All the Macintosh stuffs go here */
5287 #ifdef macintosh
5289 #include <Files.h>
5290 #include <MacTypes.h>
5291 #include <TextUtils.h>
5292 #include <Folders.h>
5294 #include <dirent.h>
5295 #include <sys/stat.h>
5296 #include <string.h>
5297 #include <pwd.h>
5298 #include <sys/param.h>
5300 /* Convert a Mac pathname to Unix form. A Mac full pathname is one
5301 that does not begin with a ':' and contains at least one ':'. A Mac
5302 full pathname causes an '/' to be prepended to the Unix pathname.
5303 The algorithm for the rest of the pathname is as follows:
5304 For each segment between two ':',
5305 if it is non-null, copy as is and then add a '/' at the end,
5306 otherwise, insert a "../" into the Unix pathname.
5307 Returns 1 if successful; 0 if fails. */
5310 Mac2UnixPathname (const char *mfn, char *ufn, int ufnbuflen)
5312 const char *p, *q, *pe;
5314 strcpy (ufn, "");
5316 if (*mfn == '\0')
5317 return 1;
5319 p = strchr (mfn, ':');
5320 if (p != 0 && p != mfn) /* full pathname */
5321 strcat (ufn, "/");
5323 p = mfn;
5324 if (*p == ':')
5325 p++;
5327 pe = mfn + strlen (mfn);
5328 while (p < pe)
5330 q = strchr (p, ':');
5331 if (q)
5333 if (q == p)
5334 { /* two consecutive ':' */
5335 if (strlen (ufn) + 3 >= ufnbuflen)
5336 return 0;
5337 strcat (ufn, "../");
5339 else
5341 if (strlen (ufn) + (q - p) + 1 >= ufnbuflen)
5342 return 0;
5343 strncat (ufn, p, q - p);
5344 strcat (ufn, "/");
5346 p = q + 1;
5348 else
5350 if (strlen (ufn) + (pe - p) >= ufnbuflen)
5351 return 0;
5352 strncat (ufn, p, pe - p); /* no separator for last one */
5353 p = pe;
5357 return 1;
5360 extern char *GetTempDirName ();
5362 /* Convert a Unix pathname to Mac form. Approximately reverse of the
5363 above in algorithm. */
5365 Unix2MacPathname (const char *ufn, char *mfn, int mfnbuflen)
5367 const char *p, *q, *pe;
5368 char expandedPathname[MAXPATHLEN+1];
5370 strcpy (mfn, "");
5372 if (*ufn == '\0')
5373 return 1;
5375 p = ufn;
5377 /* Check for and handle volume names. Last comparison: strangely
5378 somewhere `/.emacs' is passed. A temporary fix for now. */
5379 if (*p == '/' && strchr (p+1, '/') == NULL && strcmp (p, "/.emacs") != 0)
5381 if (strlen (p) + 1 > mfnbuflen)
5382 return 0;
5383 strcpy (mfn, p+1);
5384 strcat (mfn, ":");
5385 return 1;
5388 if (strncmp (p, "~emacs/", 7) == 0)
5389 { /* expand to emacs dir found by InitEmacsPasswdDir */
5390 struct passwd *pw = getpwnam ("emacs");
5391 p += 7;
5392 if (strlen (pw->pw_dir) + strlen (p) > MAXPATHLEN)
5393 return 0;
5394 strcpy (expandedPathname, pw->pw_dir);
5395 strcat (expandedPathname, p);
5396 p = expandedPathname;
5397 /* Now p points to the pathname with emacs dir prefix. */
5399 else if (strncmp (p, "/tmp/", 5) == 0)
5401 char *t = GetTempDirName ();
5402 p += 5;
5403 if (strlen (t) + strlen (p) > MAXPATHLEN)
5404 return 0;
5405 strcpy (expandedPathname, t);
5406 strcat (expandedPathname, p);
5407 p = expandedPathname;
5408 /* Now p points to the pathname with emacs dir prefix. */
5410 else if (*p != '/') /* relative pathname */
5411 strcat (mfn, ":");
5413 if (*p == '/')
5414 p++;
5416 pe = p + strlen (p);
5417 while (p < pe)
5419 q = strchr (p, '/');
5420 if (q)
5422 if (q - p == 2 && *p == '.' && *(p+1) == '.')
5424 if (strlen (mfn) + 1 >= mfnbuflen)
5425 return 0;
5426 strcat (mfn, ":");
5428 else
5430 if (strlen (mfn) + (q - p) + 1 >= mfnbuflen)
5431 return 0;
5432 strncat (mfn, p, q - p);
5433 strcat (mfn, ":");
5435 p = q + 1;
5437 else
5439 if (strlen (mfn) + (pe - p) >= mfnbuflen)
5440 return 0;
5441 strncat (mfn, p, pe - p);
5442 p = pe;
5446 return 1;
5449 /* The following functions with "sys_" prefix are stubs to Unix
5450 functions that have already been implemented by CW or MPW. The
5451 calls to them in Emacs source course are #define'd to call the sys_
5452 versions by the header files s-mac.h. In these stubs pathnames are
5453 converted between their Unix and Mac forms. */
5454 /* Unix Epoch is Jan 1, 1970 while Mac Epoch is Jan 1, 1904: 66 years
5455 + 17 leap days */
5456 #define MAC_UNIX_EPOCH_DIFF ((365L * 66 + 17) * 24 * 60 * 60)
5458 /* CW Epoch is Jan 1, 1900 (aaarghhhhh!); remember, 1900 is not a leap
5459 year! */
5460 #define CW_UNIX_EPOCH_DIFF ((365L * 70 + 17) * 24 * 60 * 60)
5462 /* Define our own stat function for both MrC and CW. The reason for
5463 doing this: "stat" is both the name of a struct and function name:
5464 we can't #define stat to something else to
5465 redirect Emacs's calls to our own version that converts Unix style
5466 filenames to Mac style filename because all sorts of compilation
5467 errors will be generated if stat is #define'd to be something else. */
5470 stat (const char *path, struct stat *buf)
5472 char MacPathname[MAXPATHLEN+1];
5473 CInfoPBRec cipb;
5475 if (Unix2MacPathname (path, MacPathname, MAXPATHLEN+1) == 0)
5476 return -1;
5478 c2pstr (MacPathname);
5479 cipb.hFileInfo.ioNamePtr = MacPathname;
5480 cipb.hFileInfo.ioVRefNum = 0;
5481 cipb.hFileInfo.ioDirID = 0;
5482 cipb.hFileInfo.ioFDirIndex = 0; /* set to 0 to get information about specific dir or file */
5484 errno = PBGetCatInfo (&cipb, false);
5485 if (errno == -43) /* -43: fnfErr defined in Errors.h */
5486 errno = ENOENT;
5487 if (errno != noErr)
5488 return -1;
5490 if (cipb.hFileInfo.ioFlAttrib & 0x10)
5491 { /* bit 4 = 1 for directories */
5492 buf->st_mode = S_IFDIR | S_IREAD | S_IEXEC;
5493 if (!(cipb.hFileInfo.ioFlAttrib & 0x1)) /* bit 1 = 1 for locked files/directories */
5494 buf->st_mode |= S_IWRITE;
5495 buf->st_ino = cipb.dirInfo.ioDrDirID;
5496 buf->st_dev = cipb.dirInfo.ioVRefNum;
5497 buf->st_size = cipb.dirInfo.ioDrNmFls; /* size of dir = number of files and dirs */
5498 buf->st_atime = buf->st_mtime = cipb.dirInfo.ioDrMdDat - MAC_UNIX_EPOCH_DIFF;
5499 buf->st_ctime = cipb.dirInfo.ioDrCrDat - MAC_UNIX_EPOCH_DIFF;
5501 else
5503 buf->st_mode = S_IFREG | S_IREAD;
5504 if (!(cipb.hFileInfo.ioFlAttrib & 0x1)) /* bit 1 = 1 for locked files/directories */
5505 buf->st_mode |= S_IWRITE;
5506 if (cipb.hFileInfo.ioFlFndrInfo.fdType == 'APPL')
5507 buf->st_mode |= S_IEXEC;
5508 buf->st_ino = cipb.hFileInfo.ioDirID;
5509 buf->st_dev = cipb.hFileInfo.ioVRefNum;
5510 buf->st_size = cipb.hFileInfo.ioFlLgLen;
5511 buf->st_atime = buf->st_mtime = cipb.hFileInfo.ioFlMdDat - MAC_UNIX_EPOCH_DIFF;
5512 buf->st_ctime = cipb.hFileInfo.ioFlCrDat - MAC_UNIX_EPOCH_DIFF;
5514 buf->st_nlink = 1;
5515 buf->st_uid = getuid ();
5516 buf->st_gid = getgid ();
5517 buf->st_rdev = 0;
5519 return 0;
5522 #if __MRC__
5524 /* CW defines fstat in stat.mac.c while MPW does not provide this
5525 function. Without the information of how to get from a file
5526 descriptor in MPW StdCLib to a Mac OS file spec, it should be hard
5527 to implement this function. Fortunately, there is only one place
5528 where this function is called in our configuration: in fileio.c,
5529 where only the st_dev and st_ino fields are used to determine
5530 whether two fildes point to different i-nodes to prevent copying
5531 a file onto itself equal. What we have here probably needs
5532 improvement. */
5534 fstat (int fildes, struct stat *buf)
5536 buf->st_dev = 0;
5537 buf->st_ino = fildes;
5538 return 0; /* success */
5541 #endif /* __MRC__ */
5543 /* From Think Reference code example */
5545 mkdir (const char *dirname, int mode)
5547 #pragma unused (mode)
5549 HFileParam hfpb;
5550 char MacPathname[MAXPATHLEN+1];
5552 if (Unix2MacPathname (dirname, MacPathname, MAXPATHLEN+1) == 0)
5553 return -1;
5555 c2pstr (MacPathname);
5556 hfpb.ioNamePtr = MacPathname;
5557 hfpb.ioVRefNum = 0; /*ignored unless name is invalid */
5558 hfpb.ioDirID = 0; /*parent is the root */
5560 /* Just return the Mac OSErr code for now. */
5561 errno = PBDirCreate ((HParmBlkPtr) &hfpb, false);
5562 return errno == noErr ? 0 : -1;
5566 rmdir (const char *dirname)
5568 HFileParam hfpb;
5569 char MacPathname[MAXPATHLEN+1];
5571 if (Unix2MacPathname (dirname, MacPathname, MAXPATHLEN+1) == 0)
5572 return -1;
5574 c2pstr (MacPathname);
5575 hfpb.ioNamePtr = MacPathname;
5576 hfpb.ioVRefNum = 0; /*ignored unless name is invalid */
5577 hfpb.ioDirID = 0; /*parent is the root */
5579 errno = PBHDelete ((HParmBlkPtr) &hfpb, false);
5580 return errno == noErr ? 0 : -1;
5583 #ifdef __MRC__
5585 /* No implementation yet. */
5587 execvp (const char *path, ...)
5589 return -1;
5592 #endif /* __MRC__ */
5595 utime (const char *path, const struct utimbuf *times)
5597 char MacPathname[MAXPATHLEN+1];
5598 CInfoPBRec cipb;
5600 if (Unix2MacPathname (path, MacPathname, MAXPATHLEN+1) == 0)
5601 return -1;
5603 c2pstr (MacPathname);
5604 cipb.hFileInfo.ioNamePtr = MacPathname;
5605 cipb.hFileInfo.ioVRefNum = 0;
5606 cipb.hFileInfo.ioDirID = 0;
5607 /* Set to 0 to get information about specific dir or file. */
5608 cipb.hFileInfo.ioFDirIndex = 0;
5610 errno = PBGetCatInfo (&cipb, false);
5611 if (errno != noErr)
5612 return -1;
5614 if (cipb.hFileInfo.ioFlAttrib & 0x10)
5615 { /* bit 4 = 1 for directories */
5616 if (times)
5617 cipb.dirInfo.ioDrMdDat = times->modtime + MAC_UNIX_EPOCH_DIFF;
5618 else
5619 GetDateTime (&cipb.dirInfo.ioDrMdDat);
5621 else
5623 if (times)
5624 cipb.hFileInfo.ioFlMdDat = times->modtime + MAC_UNIX_EPOCH_DIFF;
5625 else
5626 GetDateTime (&cipb.hFileInfo.ioFlMdDat);
5629 errno = PBSetCatInfo (&cipb, false);
5630 return errno == noErr ? 0 : -1;
5633 #define F_OK 0
5634 #define X_OK 1
5635 #define W_OK 2
5637 /* Like stat, but test for access mode in hfpb.ioFlAttrib. */
5639 access (const char *path, int mode)
5641 char MacPathname[MAXPATHLEN+1];
5642 CInfoPBRec cipb;
5644 if (Unix2MacPathname (path, MacPathname, MAXPATHLEN+1) == 0)
5645 return -1;
5647 c2pstr (MacPathname);
5648 cipb.hFileInfo.ioNamePtr = MacPathname;
5649 cipb.hFileInfo.ioVRefNum = 0;
5650 cipb.hFileInfo.ioDirID = 0;
5651 cipb.hFileInfo.ioFDirIndex = 0; /* set to 0 to get information about specific dir or file */
5653 errno = PBGetCatInfo (&cipb, false);
5654 if (errno != noErr)
5655 return -1;
5657 if (mode == F_OK) /* got this far, file exists */
5658 return 0;
5660 if (mode & X_OK)
5661 if (cipb.hFileInfo.ioFlAttrib & 0x10) /* path refers to a directory */
5662 return 0;
5663 else
5665 if (cipb.hFileInfo.ioFlFndrInfo.fdType == 'APPL')
5666 return 0;
5667 else
5668 return -1;
5671 if (mode & W_OK)
5672 return (cipb.hFileInfo.ioFlAttrib & 0x1) ? -1 : 0; /* don't allow if lock bit on */
5674 return -1;
5677 #define DEV_NULL_FD 0x10000
5679 #undef open
5681 sys_open (const char *path, int oflag)
5683 char MacPathname[MAXPATHLEN+1];
5685 if (strcmp (path, "/dev/null") == 0)
5686 return DEV_NULL_FD; /* some bogus fd to be ignored in write */
5688 if (Unix2MacPathname (path, MacPathname, MAXPATHLEN+1) == 0)
5689 return -1;
5690 else
5691 return open (MacPathname, oflag);
5694 #undef creat
5696 sys_creat (const char *path, mode_t mode)
5698 char MacPathname[MAXPATHLEN+1];
5700 if (Unix2MacPathname (path, MacPathname, MAXPATHLEN+1) == 0)
5701 return -1;
5702 else
5703 return creat (MacPathname, mode);
5706 #undef unlink
5708 sys_unlink (const char *path)
5710 char MacPathname[MAXPATHLEN+1];
5712 if (Unix2MacPathname (path, MacPathname, MAXPATHLEN+1) == 0)
5713 return -1;
5714 else
5715 return unlink (MacPathname);
5718 #undef read
5720 sys_read (int fildes, char *buf, int count)
5722 if (fildes == 0)
5723 { /* if stdin, call (non-echoing) "getch" in console.h */
5724 if (MacKeyPending ())
5725 { /* don't wait for a key if none has been pressed */
5726 *buf = MacGetChar ();
5727 return 1;
5729 else
5730 return 0;
5732 else
5733 return read (fildes, buf, count);
5736 #undef write
5738 sys_write (int fildes, char *buf, int count)
5740 if (fildes == DEV_NULL_FD)
5741 return count;
5742 else
5743 return write (fildes, buf, count);
5746 #undef rename
5748 sys_rename (const char * old_name, const char * new_name)
5750 char MacOldName[MAXPATHLEN+1], MacNewName[MAXPATHLEN+1];
5752 if (strcmp (old_name, new_name) == 0)
5753 return 0;
5755 if (Unix2MacPathname (old_name, MacOldName, MAXPATHLEN+1) == 0)
5756 return 1;
5758 if (Unix2MacPathname (new_name, MacNewName, MAXPATHLEN+1) == 0)
5759 return 1;
5761 return rename (MacOldName, MacNewName);
5764 #undef fopen
5765 extern FILE *fopen (const char *name, const char *mode);
5766 FILE
5767 sys_fopen (const char *name, const char *mode)
5769 char MacPathname[MAXPATHLEN+1];
5771 if (Unix2MacPathname (name, MacPathname, MAXPATHLEN+1) == 0)
5772 return 0;
5773 else
5774 return fopen (MacPathname, mode);
5777 #include <Events.h>
5779 long targetTicks = 0;
5781 #ifdef __MRC__
5782 __sigfun alarm_signal_func = (__sigfun) 0;
5783 #elif __MWERKS__
5784 __signal_func_ptr alarm_signal_func = (__signal_func_ptr) 0;
5785 #else
5786 You lose!!!
5787 #endif
5789 /* These functions simulate SIG_ALRM. The stub for function signal
5790 stores the signal handler function in alarm_signal_func if a
5791 SIG_ALRM is encountered. CheckAlarm is called in mac_read_socket,
5792 which emacs calls periodically. A pending alarm is represented by
5793 a non-zero targetTicks value. CheckAlarm calls the handler
5794 function pointed to by alarm_signal_func if one has been set up and
5795 an alarm is pending. */
5796 void
5797 CheckAlarm ()
5799 if (targetTicks && TickCount () > targetTicks)
5801 targetTicks = 0;
5802 if (alarm_signal_func)
5803 (*alarm_signal_func)(SIGALRM);
5807 /* Called in sys_select to wait for an alarm signal to arrive. */
5809 pause ()
5811 unsigned long finalTick;
5813 if (!targetTicks) /* no alarm pending */
5814 return -1;
5816 while (TickCount () <= targetTicks)
5817 Delay (1UL, &finalTick); /* wait for 1/60 second before trying again */
5819 targetTicks = 0;
5820 if (alarm_signal_func)
5821 (*alarm_signal_func)(SIGALRM);
5823 return 0;
5827 alarm (int seconds)
5829 long remaining = targetTicks ? (TickCount () - targetTicks) / 60 : 0;
5831 targetTicks = seconds ? TickCount () + 60 * seconds : 0;
5833 return (remaining < 0) ? 0 : (unsigned int) remaining;
5836 #undef signal
5837 #ifdef __MRC__
5838 extern __sigfun signal (int signal, __sigfun signal_func);
5839 __sigfun
5840 sys_signal (int signal_num, __sigfun signal_func)
5841 #elif __MWERKS__
5842 extern __signal_func_ptr signal (int signal, __signal_func_ptr signal_func);
5843 __signal_func_ptr
5844 sys_signal (int signal_num, __signal_func_ptr signal_func)
5845 #else
5846 You lose!!!
5847 #endif
5849 if (signal_num != SIGALRM)
5850 return signal (signal_num, signal_func);
5851 else
5853 #ifdef __MRC__
5854 __sigfun old_signal_func;
5855 #elif __MWERKS__
5856 __signal_func_ptr old_signal_func;
5857 #else
5858 You lose!!!
5859 #endif
5860 old_signal_func = alarm_signal_func;
5861 alarm_signal_func = signal_func;
5862 return old_signal_func;
5866 /* The time functions adjust time values according to the difference
5867 between the Unix and CW epoches. */
5869 #undef gmtime
5870 extern struct tm *gmtime (const time_t *);
5871 struct tm
5872 sys_gmtime (const time_t *timer)
5874 time_t unixTime = *timer + CW_UNIX_EPOCH_DIFF;
5876 return gmtime (&unixTime);
5879 #undef localtime
5880 extern struct tm *localtime (const time_t *);
5881 struct tm *
5882 sys_localtime (const time_t *timer)
5884 time_t unixTime = *timer + CW_UNIX_EPOCH_DIFF;
5886 return localtime (&unixTime);
5889 #undef ctime
5890 extern char *ctime (const time_t *);
5891 char *
5892 sys_ctime (const time_t *timer)
5894 time_t unixTime = *timer + CW_UNIX_EPOCH_DIFF;
5896 return ctime (&unixTime);
5899 #undef time
5900 extern time_t time (time_t *);
5901 time_t
5902 sys_time (time_t *timer)
5904 time_t macTime = time (NULL) - CW_UNIX_EPOCH_DIFF;
5906 if (timer)
5907 *timer = macTime;
5909 return macTime;
5912 /* no subprocesses, empty wait */
5914 wait (int pid)
5916 return 0;
5919 void
5920 croak (char *badfunc)
5922 printf ("%s not yet implemented\r\n", badfunc);
5923 exit (1);
5926 char *
5927 index (const char * str, int chr)
5929 return strchr (str, chr);
5932 char *e[] = { 0 };
5933 char **environ = &e[0];
5935 char *
5936 mktemp (char *template)
5938 int len, k;
5939 static seqnum = 0;
5941 len = strlen (template);
5942 k = len - 1;
5943 while (k >= 0 && template[k] == 'X')
5944 k--;
5946 k++; /* make k index of first 'X' */
5948 if (k < len)
5950 /* Zero filled, number of digits equal to the number of X's. */
5951 sprintf (&template[k], "%0*d", len-k, seqnum++);
5953 return template;
5955 else
5956 return 0;
5959 /* Emulate getpwuid, getpwnam and others. */
5961 #define PASSWD_FIELD_SIZE 256
5963 static char myPasswdName[PASSWD_FIELD_SIZE];
5964 static char myPasswdDir[MAXPATHLEN+1];
5966 static struct passwd myPasswd =
5968 myPasswdName,
5969 myPasswdDir,
5972 /* Initialized by main () in macterm.c to pathname of emacs directory. */
5973 char emacsPasswdDir[MAXPATHLEN+1];
5975 void
5976 InitEmacsPasswdDir ()
5978 int found = false;
5980 if (getwd (emacsPasswdDir) && getwd (myPasswdDir))
5982 /* Need pathname of first ancestor that begins with `emacs' since
5983 Mac emacs application is somewhere in the emacs-20.3 tree. */
5984 int len = strlen (emacsPasswdDir);
5985 /* J points to the "/" following the directory name being compared. */
5986 int j = len - 1;
5987 int i = j - 1;
5988 while (i >= 0 && !found)
5990 while (i >= 0 && emacsPasswdDir[i] != '/')
5991 i--;
5992 if (emacsPasswdDir[i] == '/' && i+5 < len)
5993 found = (strncmp (&(emacsPasswdDir[i+1]), "emacs", 5) == 0);
5994 if (found)
5995 emacsPasswdDir[j+1] = '\0';
5996 else
5998 j = i;
5999 i = j - 1;
6004 if (!found)
6005 { /* setting to "/" probably won't work,
6006 but set it to something anyway. */
6007 strcpy (emacsPasswdDir, "/");
6008 strcpy (myPasswdDir, "/");
6012 static struct passwd emacsPasswd =
6014 "emacs",
6015 emacsPasswdDir,
6018 static int myPasswdInited = 0;
6020 static void
6021 InitMyPasswd ()
6023 char **ownerName;
6025 /* Note: myPasswdDir initialized in InitEmacsPasswdDir to directory
6026 where Emacs was started. */
6028 ownerName = (char **) GetResource ('STR ',-16096);
6029 if (ownerName)
6031 HLock (ownerName);
6032 BlockMove ((unsigned char *) *ownerName,
6033 (unsigned char *) myPasswdName, *ownerName[0] + 1);
6034 HUnlock (ownerName);
6035 p2cstr ((unsigned char *) myPasswdName);
6037 else
6038 myPasswdName[0] = 0;
6041 struct passwd *
6042 getpwuid (uid_t uid)
6044 if (!myPasswdInited)
6046 InitMyPasswd ();
6047 myPasswdInited = 1;
6050 return &myPasswd;
6053 struct passwd *
6054 getpwnam (const char *name)
6056 if (strcmp (name, "emacs") == 0)
6057 return &emacsPasswd;
6059 if (!myPasswdInited)
6061 InitMyPasswd ();
6062 myPasswdInited = 1;
6065 return &myPasswd;
6068 /* The functions fork, kill, sigsetmask, sigblock, request_sigio,
6069 setpgrp, setpriority, and unrequest_sigio are defined to be empty
6070 as in msdos.c. */
6073 fork ()
6075 return -1;
6079 kill (int x, int y)
6081 return -1;
6085 sigsetmask (int x)
6087 return 0;
6091 sigblock (int mask)
6093 return 0;
6096 void
6097 request_sigio (void)
6102 setpgrp ()
6104 return 0;
6107 void
6108 unrequest_sigio (void)
6112 /* djgpp does not implement pipe either. */
6114 pipe (int _fildes[2])
6116 errno = EACCES;
6117 return -1;
6120 /* Hard and symbolic links. */
6122 symlink (const char *name1, const char *name2)
6124 errno = ENOENT;
6125 return -1;
6129 link (const char *name1, const char *name2)
6131 errno = ENOENT;
6132 return -1;
6136 lstat (const char *path, struct stat *sb)
6138 return stat (path, sb);
6142 readlink (const char *path, char *buf, int bufsiz)
6144 errno = ENOENT;
6145 return -1;
6148 mode_t
6149 umask (mode_t numask)
6151 static mode_t mask = 022;
6152 mode_t oldmask = mask;
6153 mask = numask;
6154 return oldmask;
6158 chmod (const char *path, mode_t mode)
6160 /* say it always succeed for now */
6161 return 0;
6165 dup (int oldd)
6167 #ifdef __MRC__
6168 return fcntl (oldd, F_DUPFD, 0);
6169 #elif __MWERKS__
6170 /* current implementation of fcntl in fcntl.mac.c simply returns old
6171 descriptor */
6172 return fcntl (oldd, F_DUPFD);
6173 #else
6174 You lose!!!
6175 #endif
6178 /* This is from the original sysdep.c. Emulate BSD dup2. First close
6179 newd if it already exists. Then, attempt to dup oldd. If not
6180 successful, call dup2 recursively until we are, then close the
6181 unsuccessful ones. */
6183 dup2 (int oldd, int newd)
6185 int fd, ret;
6187 close (newd);
6189 fd = dup (oldd);
6190 if (fd == -1)
6191 return -1;
6192 if (fd == newd)
6193 return newd;
6194 ret = dup2 (oldd, newd);
6195 close (fd);
6196 return ret;
6199 /* let it fail for now */
6200 char *
6201 sbrk (int incr)
6203 return (char *) -1;
6207 fsync (int fd)
6209 return 0;
6213 ioctl (int d, int request, void *argp)
6215 return -1;
6218 #ifdef __MRC__
6220 isatty (int fildes)
6222 if (fildes >=0 && fildes <= 2)
6223 return 1;
6224 else
6225 return 0;
6229 getgid ()
6231 return 100;
6235 getegid ()
6237 return 100;
6241 getuid ()
6243 return 200;
6247 geteuid ()
6249 return 200;
6252 unsigned int
6253 sleep (unsigned int seconds)
6255 unsigned long finalTick;
6257 Delay (seconds * 60UL, &finalTick);
6258 return (0);
6260 #endif /* __MRC__ */
6262 #ifdef __MWERKS__
6263 #undef getpid
6265 getpid ()
6267 return 9999;
6269 #endif /* __MWERKS__ */
6271 /* Return the path to the directory in which Emacs can create
6272 temporary files. The MacOS "temporary items" directory cannot be
6273 used because it removes the file written by a process when it
6274 exits. In that sense it's more like "/dev/null" than "/tmp" (but
6275 again not exactly). And of course Emacs needs to read back the
6276 files written by its subprocesses. So here we write the files to a
6277 directory "Emacs" in the Preferences Folder. This directory is
6278 created if it does not exist. */
6279 static char *
6280 GetTempDirName ()
6282 static char *TempDirName = NULL;
6283 short vRefNum;
6284 long dirID;
6285 OSErr err;
6286 Str255 dirName, fullPath;
6287 CInfoPBRec cpb;
6288 char unixDirName[MAXPATHLEN+1];
6289 DIR *dir;
6291 /* Cache directory name with pointer TempDirName.
6292 Look for it only the first time. */
6293 if (!TempDirName)
6295 err = FindFolder (kOnSystemDisk, kPreferencesFolderType,
6296 kCreateFolder, &vRefNum, &dirID);
6297 if (err != noErr)
6298 return NULL;
6300 *fullPath = '\0';
6301 cpb.dirInfo.ioNamePtr = dirName;
6302 cpb.dirInfo.ioDrParID = dirID;
6304 /* Standard ref num to full path name loop */
6305 do {
6306 cpb.dirInfo.ioVRefNum = vRefNum;
6307 cpb.dirInfo.ioFDirIndex = -1;
6308 cpb.dirInfo.ioDrDirID = cpb.dirInfo.ioDrParID;
6310 err = PBGetCatInfo (&cpb, false);
6312 p2cstr (dirName);
6313 strcat (dirName, ":");
6314 if (strlen (fullPath) + strlen (dirName) <= MAXPATHLEN)
6316 strcat (dirName, fullPath);
6317 strcpy (fullPath, dirName);
6319 else
6320 return NULL;
6322 while (cpb.dirInfo.ioDrDirID != fsRtDirID && err == noErr);
6324 if (strlen (fullPath) + 6 <= MAXPATHLEN)
6325 strcat (fullPath, "Emacs:");
6326 else
6327 return NULL;
6329 if (Mac2UnixPathname (fullPath, unixDirName, MAXPATHLEN+1) == 0)
6330 return NULL;
6332 dir = opendir (unixDirName); /* check whether temp directory exists */
6333 if (dir)
6334 closedir (dir);
6335 else if (mkdir (unixDirName, 0700) != 0) /* create it if not */
6336 return NULL;
6338 TempDirName = (char *) malloc (strlen (unixDirName) + 1);
6339 strcpy (TempDirName, unixDirName);
6342 return TempDirName;
6345 char *
6346 getenv (const char * name)
6348 if (strcmp (name, "TERM") == 0)
6349 return "vt100";
6350 else if (strcmp (name, "TERMCAP") == 0)
6351 /* for debugging purpose when code was still outputting to dumb terminal */
6352 return "d0|vt100|vt100-am|vt100am|dec vt100:do=[do]:co#100:li#32:cl=[cl]:sf=[sf]:km:\
6353 :le=[le]:bs:am:cm=[cm-%d,%d]:nd=[nd]:up=[up]:ce=[ce]:cd=[cd]:so=[so]:se=[se]:\
6354 :us=[us]:ue=[ue]:md=[md]:mr=[mr]:mb=[mb]:me=[me]:is=[is]:\
6355 :rf=/usr/share/lib/tabset/vt100:rs=[rs]:ks=[ks]:ke=[ke]:\
6356 :ku=\\036:kd=\\037:kr=\\035:kl=\\034:kb=[kb]:ho=[ho]:k1=[k1]:k2=[k2]:k3=[k3]:k4=[k4]:\
6357 :pt:sr=[sr]:vt#3:xn:sc=[sc]:rc=[rc]:cs=[cs-%d,%d]";
6358 else if (strcmp (name, "TMPDIR") == 0)
6359 return GetTempDirName ();
6360 else
6361 return (NULL);
6364 #ifdef __MRC__
6365 #include <utsname.h>
6368 uname (struct utsname *name)
6370 char **systemName;
6371 systemName = GetString (-16413); /* IM - Resource Manager Reference */
6372 if (systemName)
6374 BlockMove (*systemName, name->nodename, (*systemName)[0]+1);
6375 p2cstr (name->nodename);
6377 else
6378 return -1;
6380 #endif
6382 #include <Processes.h>
6383 #include <EPPC.h>
6385 /* Event class of HLE sent to subprocess. */
6386 const OSType kEmacsSubprocessSend = 'ESND';
6387 /* Event class of HLE sent back from subprocess. */
6388 const OSType kEmacsSubprocessReply = 'ERPY';
6390 char *
6391 mystrchr (char *s, char c)
6393 while (*s && *s != c)
6395 if (*s == '\\')
6396 s++;
6397 s++;
6400 if (*s)
6402 *s = '\0';
6403 return s;
6405 else
6406 return NULL;
6409 char *
6410 mystrtok (char *s)
6412 while (*s)
6413 s++;
6415 return s + 1;
6418 void
6419 mystrcpy (char *to, char *from)
6421 while (*from)
6423 if (*from == '\\')
6424 from++;
6425 *to++ = *from++;
6427 *to = '\0';
6430 /* Start a Mac subprocess. Arguments for it is passed in argv (null
6431 terminated). The process should run with the default directory
6432 "workdir", read input from "infn", and write output and error to
6433 "outfn" and "errfn", resp. The Process Manager call
6434 LaunchApplication is used to start the subprocess. We use high
6435 level events as the mechanism to pass arguments to the subprocess
6436 and to make Emacs wait for the subprocess to terminate and pass
6437 back a result code. The bulk of the code here packs the arguments
6438 into one message to be passed together with the high level event.
6439 Emacs also sometimes starts a subprocess using a shell to perform
6440 wildcard filename expansion. Since we don't really have a shell on
6441 the Mac, this case is detected and the starting of the shell is
6442 by-passed. We really need to add code here to do filename
6443 expansion to support such functionality. */
6445 run_mac_command (argv, workdir, infn, outfn, errfn)
6446 unsigned char **argv;
6447 const char *workdir;
6448 const char *infn, *outfn, errfn;
6450 char macappname[MAXPATHLEN+1], macworkdir[MAXPATHLEN+1];
6451 char macinfn[MAXPATHLEN+1], macoutfn[MAXPATHLEN+1], macerrfn[MAXPATHLEN+1];
6452 int paramlen, argc, newargc, j, retries;
6453 char **newargv, *param, *p;
6454 OSErr iErr;
6455 FSSpec spec;
6456 LaunchParamBlockRec lpbr;
6457 EventRecord sendEvent, replyEvent;
6458 RgnHandle cursorRegionHdl;
6459 TargetID targ;
6460 unsigned long refCon, len;
6462 if (Unix2MacPathname (workdir, macworkdir, MAXPATHLEN+1) == 0)
6463 return -1;
6464 if (Unix2MacPathname (infn, macinfn, MAXPATHLEN+1) == 0)
6465 return -1;
6466 if (Unix2MacPathname (outfn, macoutfn, MAXPATHLEN+1) == 0)
6467 return -1;
6468 if (Unix2MacPathname (errfn, macerrfn, MAXPATHLEN+1) == 0)
6469 return -1;
6471 paramlen = strlen (macworkdir) + strlen (macinfn) + strlen (macoutfn) + strlen (macerrfn) + 4;
6472 /* count nulls at end of strings */
6474 argc = 0;
6475 while (argv[argc])
6476 argc++;
6478 if (argc == 0)
6479 return -1;
6481 /* If a subprocess is invoked with a shell, we receive 3 arguments of the form:
6482 "<path to emacs bins>/sh" "-c" "<path to emacs bins>/<command> <command args>" */
6483 j = strlen (argv[0]);
6484 if (j >= 3 && strcmp (argv[0]+j-3, "/sh") == 0 && argc == 3 && strcmp (argv[1], "-c") == 0)
6486 char *command, *t, tempmacpathname[MAXPATHLEN+1];
6488 /* The arguments for the command in argv[2] are separated by spaces. Count them and put
6489 the count in newargc. */
6490 command = (char *) alloca (strlen (argv[2])+2);
6491 strcpy (command, argv[2]);
6492 if (command[strlen (command) - 1] != ' ')
6493 strcat (command, " ");
6495 t = command;
6496 newargc = 0;
6497 t = mystrchr (t, ' ');
6498 while (t)
6500 newargc++;
6501 t = mystrchr (t+1, ' ');
6504 newargv = (char **) alloca (sizeof (char *) * newargc);
6506 t = command;
6507 for (j = 0; j < newargc; j++)
6509 newargv[j] = (char *) alloca (strlen (t) + 1);
6510 mystrcpy (newargv[j], t);
6512 t = mystrtok (t);
6513 paramlen += strlen (newargv[j]) + 1;
6516 if (strncmp (newargv[0], "~emacs/", 7) == 0)
6518 if (Unix2MacPathname (newargv[0], tempmacpathname, MAXPATHLEN+1) == 0)
6519 return -1;
6521 else
6522 { /* sometimes Emacs call "sh" without a path for the command */
6523 #if 0
6524 char *t = (char *) alloca (strlen (newargv[0]) + 7 + 1);
6525 strcpy (t, "~emacs/");
6526 strcat (t, newargv[0]);
6527 #endif
6528 Lisp_Object path;
6529 openp (Vexec_path, build_string (newargv[0]), EXEC_SUFFIXES, &path, 1);
6531 if (NILP (path))
6532 return -1;
6533 if (Unix2MacPathname (XSTRING (path)->data, tempmacpathname, MAXPATHLEN+1) == 0)
6534 return -1;
6536 strcpy (macappname, tempmacpathname);
6538 else
6540 if (Unix2MacPathname (argv[0], macappname, MAXPATHLEN+1) == 0)
6541 return -1;
6543 newargv = (char **) alloca (sizeof (char *) * argc);
6544 newargc = argc;
6545 for (j = 1; j < argc; j++)
6547 if (strncmp (argv[j], "~emacs/", 7) == 0)
6549 char *t = strchr (argv[j], ' ');
6550 if (t)
6552 char tempcmdname[MAXPATHLEN+1], tempmaccmdname[MAXPATHLEN+1];
6553 strncpy (tempcmdname, argv[j], t-argv[j]);
6554 tempcmdname[t-argv[j]] = '\0';
6555 if (Unix2MacPathname (tempcmdname, tempmaccmdname, MAXPATHLEN+1) == 0)
6556 return -1;
6557 newargv[j] = (char *) alloca (strlen (tempmaccmdname) + strlen (t) + 1);
6558 strcpy (newargv[j], tempmaccmdname);
6559 strcat (newargv[j], t);
6561 else
6563 char tempmaccmdname[MAXPATHLEN+1];
6564 if (Unix2MacPathname (argv[j], tempmaccmdname, MAXPATHLEN+1) == 0)
6565 return -1;
6566 newargv[j] = (char *) alloca (strlen (tempmaccmdname)+1);
6567 strcpy (newargv[j], tempmaccmdname);
6570 else
6571 newargv[j] = argv[j];
6572 paramlen += strlen (newargv[j]) + 1;
6576 /* After expanding all the arguments, we now know the length of the parameter block to be
6577 sent to the subprocess as a message attached to the HLE. */
6578 param = (char *) malloc (paramlen + 1);
6579 if (!param)
6580 return -1;
6582 p = param;
6583 *p++ = newargc; /* first byte of message contains number of arguments for command */
6584 strcpy (p, macworkdir);
6585 p += strlen (macworkdir);
6586 *p++ = '\0'; /* null terminate strings sent so it's possible to use strcpy over there */
6587 strcpy (p, macinfn);
6588 p += strlen (macinfn);
6589 *p++ = '\0';
6590 strcpy (p, macoutfn);
6591 p += strlen (macoutfn);
6592 *p++ = '\0';
6593 strcpy (p, macerrfn);
6594 p += strlen (macerrfn);
6595 *p++ = '\0';
6596 for (j = 1; j < newargc; j++) {
6597 strcpy (p, newargv[j]);
6598 p += strlen (newargv[j]);
6599 *p++ = '\0';
6602 c2pstr (macappname);
6604 iErr = FSMakeFSSpec (0, 0, macappname, &spec);
6606 if (iErr != noErr) {
6607 free (param);
6608 return -1;
6611 lpbr.launchBlockID = extendedBlock;
6612 lpbr.launchEPBLength = extendedBlockLen;
6613 lpbr.launchControlFlags = launchContinue + launchNoFileFlags;
6614 lpbr.launchAppSpec = &spec;
6615 lpbr.launchAppParameters = NULL;
6617 iErr = LaunchApplication (&lpbr); /* call the subprocess */
6618 if (iErr != noErr) {
6619 free (param);
6620 return -1;
6623 sendEvent.what = kHighLevelEvent;
6624 sendEvent.message = kEmacsSubprocessSend; /* Event ID stored in "where" unused */
6626 retries = 3;
6627 do { /* OS may think current subprocess has terminated if previous one terminated recently */
6628 iErr = PostHighLevelEvent (&sendEvent, &lpbr.launchProcessSN, 0, param, paramlen + 1, receiverIDisPSN);
6630 while (iErr == sessClosedErr && retries-- > 0);
6632 if (iErr != noErr) {
6633 free (param);
6634 return -1;
6637 cursorRegionHdl = NewRgn ();
6639 /* Wait for the subprocess to finish, when it will send us a ERPY high level event */
6640 while (1)
6641 if (WaitNextEvent (highLevelEventMask, &replyEvent, 180, cursorRegionHdl) && replyEvent.message == kEmacsSubprocessReply)
6642 break;
6644 /* The return code is sent through the refCon */
6645 iErr = AcceptHighLevelEvent (&targ, &refCon, NULL, &len);
6646 if (iErr != noErr) {
6647 DisposeHandle ((Handle) cursorRegionHdl);
6648 free (param);
6649 return -1;
6652 DisposeHandle ((Handle) cursorRegionHdl);
6653 free (param);
6655 return refCon;
6658 DIR *
6659 opendir (const char *dirname)
6661 char MacPathname[MAXPATHLEN+1];
6662 DIR *dirp;
6663 CInfoPBRec cipb;
6664 int len;
6666 dirp = (DIR *) malloc (sizeof (DIR));
6667 if (!dirp)
6668 return 0;
6670 /* Handle special case when dirname is "/": sets up for readir to
6671 get all mount volumes. */
6672 if (strcmp (dirname, "/") == 0) {
6673 dirp->getting_volumes = 1; /* special all mounted volumes DIR struct */
6674 dirp->current_index = 1; /* index for first volume */
6675 return dirp;
6678 /* Handle typical cases: not accessing all mounted volumes. */
6679 if (Unix2MacPathname (dirname, MacPathname, MAXPATHLEN+1) == 0)
6680 return 0;
6682 /* Emacs calls opendir without the trailing '/', Mac needs trailing ':' */
6683 len = strlen (MacPathname);
6684 if (MacPathname[len - 1] != ':' && len < MAXPATHLEN)
6685 strcat (MacPathname, ":");
6687 c2pstr (MacPathname);
6688 cipb.hFileInfo.ioNamePtr = MacPathname; /* using full pathname so vRefNum and dirID ignored */
6689 cipb.hFileInfo.ioVRefNum = 0;
6690 cipb.hFileInfo.ioDirID = 0;
6691 cipb.hFileInfo.ioFDirIndex = 0; /* set to 0 to get information about specific dir or file */
6693 errno = PBGetCatInfo (&cipb, false);
6694 if (errno != noErr) {
6695 errno = ENOENT;
6696 return 0;
6699 if (!(cipb.hFileInfo.ioFlAttrib & 0x10)) /* bit 4 = 1 for directories */
6700 return 0; /* not a directory */
6702 dirp->dir_id = cipb.dirInfo.ioDrDirID; /* used later in readdir */
6703 dirp->getting_volumes = 0;
6704 dirp->current_index = 1; /* index for first file/directory */
6706 return dirp;
6710 closedir (DIR *dp)
6712 free (dp);
6714 return 0;
6717 struct dirent *
6718 readdir (DIR *dp)
6720 HParamBlockRec HPBlock;
6721 CInfoPBRec cipb;
6722 static struct dirent s_dirent;
6723 static Str255 s_name;
6724 int done;
6726 /* Handle the root directory containing the mounted volumes. Call
6727 PBHGetVInfo specifying an index to obtain the info for a volume.
6728 PBHGetVInfo returns an error when it receives an index beyond the
6729 last volume, at which time we should return a nil dirent struct
6730 pointer. */
6731 if (dp->getting_volumes) {
6732 HPBlock.volumeParam.ioNamePtr = s_name;
6733 HPBlock.volumeParam.ioVRefNum = 0;
6734 HPBlock.volumeParam.ioVolIndex = dp->current_index;
6736 errno = PBHGetVInfo (&HPBlock, false);
6737 if (errno != noErr) {
6738 errno = ENOENT;
6739 return 0;
6742 p2cstr (s_name);
6743 strcat (s_name, "/"); /* need "/" for stat to work correctly */
6745 dp->current_index++;
6747 s_dirent.d_ino = cipb.dirInfo.ioDrDirID;
6748 s_dirent.d_name = s_name;
6750 return &s_dirent;
6752 else {
6753 cipb.hFileInfo.ioVRefNum = 0;
6754 cipb.hFileInfo.ioNamePtr = s_name; /* location to receive filename returned */
6756 /* return only visible files */
6757 done = false;
6758 while (!done) {
6759 cipb.hFileInfo.ioDirID = dp->dir_id; /* directory ID found by opendir */
6760 cipb.hFileInfo.ioFDirIndex = dp->current_index;
6762 errno = PBGetCatInfo (&cipb, false);
6763 if (errno != noErr) {
6764 errno = ENOENT;
6765 return 0;
6768 /* insist on an visibile entry */
6769 if (cipb.hFileInfo.ioFlAttrib & 0x10) /* directory? */
6770 done = !(cipb.dirInfo.ioDrUsrWds.frFlags & fInvisible);
6771 else
6772 done = !(cipb.hFileInfo.ioFlFndrInfo.fdFlags & fInvisible);
6774 dp->current_index++;
6777 p2cstr (s_name);
6779 s_dirent.d_ino = cipb.dirInfo.ioDrDirID; /* value unimportant: non-zero for valid file */
6780 s_dirent.d_name = s_name;
6782 return &s_dirent;
6786 char *
6787 getwd (char *path)
6789 char MacPathname[MAXPATHLEN+1];
6790 Str255 directoryName;
6791 OSErr errno;
6792 CInfoPBRec cipb;
6794 MacPathname[0] = '\0';
6795 directoryName[0] = '\0';
6796 cipb.dirInfo.ioDrParID = 0;
6797 cipb.dirInfo.ioNamePtr = directoryName; /* empty string = default directory */
6799 do {
6800 cipb.dirInfo.ioVRefNum = 0;
6801 cipb.dirInfo.ioFDirIndex = -1;
6802 cipb.dirInfo.ioDrDirID = cipb.dirInfo.ioDrParID; /* go up to parent each time */
6804 errno = PBGetCatInfo (&cipb, false);
6805 if (errno != noErr) {
6806 errno = ENOENT;
6807 return 0;
6810 p2cstr (directoryName);
6811 strcat (directoryName, ":");
6812 strcat (directoryName, MacPathname); /* attach to front since going up directory tree */
6813 strcpy (MacPathname, directoryName);
6814 } while (cipb.dirInfo.ioDrDirID != fsRtDirID); /* until volume's root directory */
6816 if (Mac2UnixPathname (MacPathname, path, MAXPATHLEN+1) == 0)
6817 return 0;
6818 else
6819 return path;
6822 #endif /* macintosh */