(Fexpand_abbrev): Remove unused variables.
[bpt/emacs.git] / src / sysdep.c
1 /* Interfaces to system-dependent kernel and library entries.
2 Copyright (C) 1985, 86, 87, 88, 93, 94, 95 Free Software Foundation, Inc.
3
4 This file is part of GNU Emacs.
5
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.
10
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.
15
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. */
20
21
22 #include <signal.h>
23 #include <setjmp.h>
24
25 #include <config.h>
26 #ifdef STDC_HEADERS
27 #include <stdlib.h>
28 #endif
29 #include "lisp.h"
30 #include "blockinput.h"
31 #undef NULL
32
33 #ifdef macintosh
34 #ifdef __MRC__
35 __sigfun sys_signal (int signal, __sigfun signal_func);
36 #elif __MWERKS__
37 __signal_func_ptr sys_signal (int signal, __signal_func_ptr signal_func);
38 #else
39 You lose!!!
40 #endif
41 #ifndef subprocesses
42 /* Nonzero means delete a process right away if it exits (process.c). */
43 static int delete_exited_processes;
44 #endif
45 #ifndef HAVE_X_WINDOWS
46 /* Search path for bitmap files (xfns.c). */
47 Lisp_Object Vx_bitmap_file_path;
48 #endif
49 #endif /* macintosh */
50
51 #define min(x,y) ((x) > (y) ? (y) : (x))
52
53 /* In this file, open, read and write refer to the system calls,
54 not our sugared interfaces sys_open, sys_read and sys_write.
55 Contrariwise, for systems where we use the system calls directly,
56 define sys_read, etc. here as aliases for them. */
57 #ifndef read
58 #define sys_read read
59 #define sys_write write
60 #endif /* `read' is not a macro */
61
62 #undef read
63 #undef write
64
65 #ifdef WINDOWSNT
66 #define read _read
67 #define write _write
68 #include <windows.h>
69 extern int errno;
70 #endif /* not WINDOWSNT */
71
72 #ifndef close
73 #define sys_close close
74 #else
75 #undef close
76 #endif
77
78 #ifndef open
79 #define sys_open open
80 #else /* `open' is a macro */
81 #undef open
82 #endif /* `open' is a macro */
83
84 /* Does anyone other than VMS need this? */
85 #ifndef fwrite
86 #define sys_fwrite fwrite
87 #else
88 #undef fwrite
89 #endif
90
91 #ifndef HAVE_H_ERRNO
92 extern int h_errno;
93 #endif
94
95 #include <stdio.h>
96 #include <sys/types.h>
97 #include <sys/stat.h>
98 #include <errno.h>
99
100 /* Get _POSIX_VDISABLE, if it is available. */
101 #ifdef HAVE_UNISTD_H
102 #include <unistd.h>
103 #endif
104
105 /* Get SI_SRPC_DOMAIN, if it is available. */
106 #ifdef HAVE_SYS_SYSTEMINFO_H
107 #include <sys/systeminfo.h>
108 #endif
109
110 #ifdef MSDOS /* Demacs 1.1.2 91/10/20 Manabu Higashida, MW Aug 1993 */
111 #include <dos.h>
112 #include "dosfns.h"
113 #include "msdos.h"
114 #include <sys/param.h>
115
116 #if __DJGPP__ > 1
117 extern int etext;
118 extern unsigned start __asm__ ("start");
119 #endif
120 #endif
121
122 #ifndef errno
123 extern int errno;
124 #endif
125
126 #ifdef VMS
127 #include <rms.h>
128 #include <ttdef.h>
129 #include <tt2def.h>
130 #include <iodef.h>
131 #include <ssdef.h>
132 #include <descrip.h>
133 #include <fibdef.h>
134 #include <atrdef.h>
135 #include <ctype.h>
136 #include <string.h>
137 #ifdef __GNUC__
138 #include <sys/file.h>
139 #else
140 #include <file.h>
141 #endif
142 #undef F_SETFL
143 #ifndef RAB$C_BID
144 #include <rab.h>
145 #endif
146 #define MAXIOSIZE (32 * PAGESIZE) /* Don't I/O more than 32 blocks at a time */
147 #endif /* VMS */
148
149 #ifndef BSD4_1
150 #ifdef BSD_SYSTEM /* avoid writing defined (BSD_SYSTEM) || defined (USG)
151 because the vms compiler doesn't grok `defined' */
152 #include <fcntl.h>
153 #endif
154 #ifdef USG
155 #ifndef USG5
156 #include <fcntl.h>
157 #endif
158 #endif
159 #endif /* not 4.1 bsd */
160
161 #ifndef MSDOS
162 #include <sys/ioctl.h>
163 #endif
164
165 #include "systty.h"
166 #include "syswait.h"
167
168 #ifdef BROKEN_TIOCGWINSZ
169 #undef TIOCGWINSZ
170 #undef TIOCSWINSZ
171 #endif
172
173 #if defined (USG) || defined (DGUX)
174 #include <sys/utsname.h>
175 #include <string.h>
176 #ifndef MEMORY_IN_STRING_H
177 #include <memory.h>
178 #endif
179 #if defined (TIOCGWINSZ) || defined (ISC4_0)
180 #ifdef NEED_SIOCTL
181 #include <sys/sioctl.h>
182 #endif
183 #ifdef NEED_PTEM_H
184 #include <sys/stream.h>
185 #include <sys/ptem.h>
186 #endif
187 #endif /* TIOCGWINSZ or ISC4_0 */
188 #endif /* USG or DGUX */
189
190 extern int quit_char;
191
192 #include "frame.h"
193 #include "window.h"
194 #include "termhooks.h"
195 #include "termchar.h"
196 #include "termopts.h"
197 #include "dispextern.h"
198 #include "process.h"
199
200 #ifdef WINDOWSNT
201 #include <direct.h>
202 /* In process.h which conflicts with the local copy. */
203 #define _P_WAIT 0
204 int _CRTAPI1 _spawnlp (int, const char *, const char *, ...);
205 int _CRTAPI1 _getpid (void);
206 #endif
207
208 #ifdef NONSYSTEM_DIR_LIBRARY
209 #include "ndir.h"
210 #endif /* NONSYSTEM_DIR_LIBRARY */
211
212 #include "syssignal.h"
213 #include "systime.h"
214 #ifdef HAVE_UTIME_H
215 #include <utime.h>
216 #endif
217
218 #ifndef HAVE_UTIMES
219 #ifndef HAVE_STRUCT_UTIMBUF
220 /* We want to use utime rather than utimes, but we couldn't find the
221 structure declaration. We'll use the traditional one. */
222 struct utimbuf {
223 long actime;
224 long modtime;
225 };
226 #endif
227 #endif
228
229 #ifndef VFORK_RETURN_TYPE
230 #define VFORK_RETURN_TYPE int
231 #endif
232
233 /* LPASS8 is new in 4.3, and makes cbreak mode provide all 8 bits. */
234 #ifndef LPASS8
235 #define LPASS8 0
236 #endif
237
238 #ifdef BSD4_1
239 #define LNOFLSH 0100000
240 #endif
241
242 static int baud_convert[] =
243 #ifdef BAUD_CONVERT
244 BAUD_CONVERT;
245 #else
246 {
247 0, 50, 75, 110, 135, 150, 200, 300, 600, 1200,
248 1800, 2400, 4800, 9600, 19200, 38400
249 };
250 #endif
251
252 #if defined (HAVE_LIBNCURSES) && ! defined (NCURSES_OSPEED_T)
253 extern short ospeed;
254 #else
255 #if defined (HAVE_TERMIOS_H) && defined (LINUX)
256 #include <termios.h>
257 /* HJL's version of libc is said to need this on the Alpha.
258 On the other hand, DEC OSF1 on the Alpha needs ospeed to be a short. */
259 extern speed_t ospeed;
260 #else
261 extern short ospeed;
262 #endif
263 #endif
264
265 /* The file descriptor for Emacs's input terminal.
266 Under Unix, this is normally zero except when using X;
267 under VMS, we place the input channel number here. */
268 int input_fd;
269
270 void croak P_ ((char *));
271
272 #ifdef AIXHFT
273 void hft_init ();
274 void hft_reset ();
275 #endif
276
277 \f
278 /* Specify a different file descriptor for further input operations. */
279
280 void
281 change_input_fd (fd)
282 int fd;
283 {
284 input_fd = fd;
285 }
286
287 /* Discard pending input on descriptor input_fd. */
288
289 void
290 discard_tty_input ()
291 {
292 #ifndef WINDOWSNT
293 struct emacs_tty buf;
294
295 if (noninteractive)
296 return;
297
298 /* Discarding input is not safe when the input could contain
299 replies from the X server. So don't do it. */
300 if (read_socket_hook)
301 return;
302
303 #ifdef VMS
304 end_kbd_input ();
305 SYS$QIOW (0, input_fd, IO$_READVBLK|IO$M_PURGE, input_iosb, 0, 0,
306 &buf.main, 0, 0, terminator_mask, 0, 0);
307 queue_kbd_input ();
308 #else /* not VMS */
309 #ifdef APOLLO
310 {
311 int zero = 0;
312 ioctl (input_fd, TIOCFLUSH, &zero);
313 }
314 #else /* not Apollo */
315 #ifdef MSDOS /* Demacs 1.1.1 91/10/16 HIRANO Satoshi */
316 while (dos_keyread () != -1)
317 ;
318 #else /* not MSDOS */
319 EMACS_GET_TTY (input_fd, &buf);
320 EMACS_SET_TTY (input_fd, &buf, 0);
321 #endif /* not MSDOS */
322 #endif /* not Apollo */
323 #endif /* not VMS */
324 #endif /* not WINDOWSNT */
325 }
326
327 #ifdef SIGTSTP
328
329 /* Arrange for character C to be read as the next input from
330 the terminal. */
331
332 void
333 stuff_char (c)
334 char c;
335 {
336 if (read_socket_hook)
337 return;
338
339 /* Should perhaps error if in batch mode */
340 #ifdef TIOCSTI
341 ioctl (input_fd, TIOCSTI, &c);
342 #else /* no TIOCSTI */
343 error ("Cannot stuff terminal input characters in this version of Unix");
344 #endif /* no TIOCSTI */
345 }
346
347 #endif /* SIGTSTP */
348 \f
349 void
350 init_baud_rate ()
351 {
352 if (noninteractive)
353 ospeed = 0;
354 else
355 {
356 #ifdef INIT_BAUD_RATE
357 INIT_BAUD_RATE ();
358 #else
359 #ifdef DOS_NT
360 ospeed = 15;
361 #else /* not DOS_NT */
362 #ifdef VMS
363 struct sensemode sg;
364
365 SYS$QIOW (0, input_fd, IO$_SENSEMODE, &sg, 0, 0,
366 &sg.class, 12, 0, 0, 0, 0 );
367 ospeed = sg.xmit_baud;
368 #else /* not VMS */
369 #ifdef HAVE_TERMIOS
370 struct termios sg;
371
372 sg.c_cflag = B9600;
373 tcgetattr (input_fd, &sg);
374 ospeed = cfgetospeed (&sg);
375 #if defined (USE_GETOBAUD) && defined (getobaud)
376 /* m88k-motorola-sysv3 needs this (ghazi@noc.rutgers.edu) 9/1/94. */
377 if (ospeed == 0)
378 ospeed = getobaud (sg.c_cflag);
379 #endif
380 #else /* neither VMS nor TERMIOS */
381 #ifdef HAVE_TERMIO
382 struct termio sg;
383
384 sg.c_cflag = B9600;
385 #ifdef HAVE_TCATTR
386 tcgetattr (input_fd, &sg);
387 #else
388 ioctl (input_fd, TCGETA, &sg);
389 #endif
390 ospeed = sg.c_cflag & CBAUD;
391 #else /* neither VMS nor TERMIOS nor TERMIO */
392 struct sgttyb sg;
393
394 sg.sg_ospeed = B9600;
395 if (ioctl (input_fd, TIOCGETP, &sg) < 0)
396 abort ();
397 ospeed = sg.sg_ospeed;
398 #endif /* not HAVE_TERMIO */
399 #endif /* not HAVE_TERMIOS */
400 #endif /* not VMS */
401 #endif /* not DOS_NT */
402 #endif /* not INIT_BAUD_RATE */
403 }
404
405 baud_rate = (ospeed < sizeof baud_convert / sizeof baud_convert[0]
406 ? baud_convert[ospeed] : 9600);
407 if (baud_rate == 0)
408 baud_rate = 1200;
409 }
410
411 /*ARGSUSED*/
412 void
413 set_exclusive_use (fd)
414 int fd;
415 {
416 #ifdef FIOCLEX
417 ioctl (fd, FIOCLEX, 0);
418 #endif
419 /* Ok to do nothing if this feature does not exist */
420 }
421 \f
422 #ifndef subprocesses
423
424 wait_without_blocking ()
425 {
426 #ifdef BSD_SYSTEM
427 wait3 (0, WNOHANG | WUNTRACED, 0);
428 #else
429 croak ("wait_without_blocking");
430 #endif
431 synch_process_alive = 0;
432 }
433
434 #endif /* not subprocesses */
435
436 int wait_debugging; /* Set nonzero to make following function work under dbx
437 (at least for bsd). */
438
439 SIGTYPE
440 wait_for_termination_signal ()
441 {}
442
443 /* Wait for subprocess with process id `pid' to terminate and
444 make sure it will get eliminated (not remain forever as a zombie) */
445
446 void
447 wait_for_termination (pid)
448 int pid;
449 {
450 while (1)
451 {
452 #ifdef subprocesses
453 #ifdef VMS
454 int status;
455
456 status = SYS$FORCEX (&pid, 0, 0);
457 break;
458 #else /* not VMS */
459 #if defined (BSD_SYSTEM) || (defined (HPUX) && !defined (HPUX_5))
460 /* Note that kill returns -1 even if the process is just a zombie now.
461 But inevitably a SIGCHLD interrupt should be generated
462 and child_sig will do wait3 and make the process go away. */
463 /* There is some indication that there is a bug involved with
464 termination of subprocesses, perhaps involving a kernel bug too,
465 but no idea what it is. Just as a hunch we signal SIGCHLD to see
466 if that causes the problem to go away or get worse. */
467 sigsetmask (sigmask (SIGCHLD));
468 if (0 > kill (pid, 0))
469 {
470 sigsetmask (SIGEMPTYMASK);
471 kill (getpid (), SIGCHLD);
472 break;
473 }
474 if (wait_debugging)
475 sleep (1);
476 else
477 sigpause (SIGEMPTYMASK);
478 #else /* not BSD_SYSTEM, and not HPUX version >= 6 */
479 #if defined (UNIPLUS)
480 if (0 > kill (pid, 0))
481 break;
482 wait (0);
483 #else /* neither BSD_SYSTEM nor UNIPLUS: random sysV */
484 #ifdef POSIX_SIGNALS /* would this work for LINUX as well? */
485 sigblock (sigmask (SIGCHLD));
486 if (0 > kill (pid, 0))
487 {
488 sigunblock (sigmask (SIGCHLD));
489 break;
490 }
491 sigpause (SIGEMPTYMASK);
492 #else /* not POSIX_SIGNALS */
493 #ifdef HAVE_SYSV_SIGPAUSE
494 sighold (SIGCHLD);
495 if (0 > kill (pid, 0))
496 {
497 sigrelse (SIGCHLD);
498 break;
499 }
500 sigpause (SIGCHLD);
501 #else /* not HAVE_SYSV_SIGPAUSE */
502 #ifdef WINDOWSNT
503 wait (0);
504 break;
505 #else /* not WINDOWSNT */
506 if (0 > kill (pid, 0))
507 break;
508 /* Using sleep instead of pause avoids timing error.
509 If the inferior dies just before the sleep,
510 we lose just one second. */
511 sleep (1);
512 #endif /* not WINDOWSNT */
513 #endif /* not HAVE_SYSV_SIGPAUSE */
514 #endif /* not POSIX_SIGNALS */
515 #endif /* not UNIPLUS */
516 #endif /* not BSD_SYSTEM, and not HPUX version >= 6 */
517 #endif /* not VMS */
518 #else /* not subprocesses */
519 #if __DJGPP__ > 1
520 break;
521 #else /* not __DJGPP__ > 1 */
522 #ifndef BSD4_1
523 if (kill (pid, 0) < 0)
524 break;
525 wait (0);
526 #else /* BSD4_1 */
527 int status;
528 status = wait (0);
529 if (status == pid || status == -1)
530 break;
531 #endif /* BSD4_1 */
532 #endif /* not __DJGPP__ > 1*/
533 #endif /* not subprocesses */
534 }
535 }
536
537 #ifdef subprocesses
538
539 /*
540 * flush any pending output
541 * (may flush input as well; it does not matter the way we use it)
542 */
543
544 void
545 flush_pending_output (channel)
546 int channel;
547 {
548 #ifdef HAVE_TERMIOS
549 /* If we try this, we get hit with SIGTTIN, because
550 the child's tty belongs to the child's pgrp. */
551 #else
552 #ifdef TCFLSH
553 ioctl (channel, TCFLSH, 1);
554 #else
555 #ifdef TIOCFLUSH
556 int zero = 0;
557 /* 3rd arg should be ignored
558 but some 4.2 kernels actually want the address of an int
559 and nonzero means something different. */
560 ioctl (channel, TIOCFLUSH, &zero);
561 #endif
562 #endif
563 #endif
564 }
565 \f
566 #ifndef VMS
567 /* Set up the terminal at the other end of a pseudo-terminal that
568 we will be controlling an inferior through.
569 It should not echo or do line-editing, since that is done
570 in Emacs. No padding needed for insertion into an Emacs buffer. */
571
572 void
573 child_setup_tty (out)
574 int out;
575 {
576 #ifndef DOS_NT
577 struct emacs_tty s;
578
579 EMACS_GET_TTY (out, &s);
580
581 #if defined (HAVE_TERMIO) || defined (HAVE_TERMIOS)
582 s.main.c_oflag |= OPOST; /* Enable output postprocessing */
583 s.main.c_oflag &= ~ONLCR; /* Disable map of NL to CR-NL on output */
584 #ifdef NLDLY
585 s.main.c_oflag &= ~(NLDLY|CRDLY|TABDLY|BSDLY|VTDLY|FFDLY);
586 /* No output delays */
587 #endif
588 s.main.c_lflag &= ~ECHO; /* Disable echo */
589 s.main.c_lflag |= ISIG; /* Enable signals */
590 #ifdef IUCLC
591 s.main.c_iflag &= ~IUCLC; /* Disable downcasing on input. */
592 #endif
593 #ifdef ISTRIP
594 s.main.c_iflag &= ~ISTRIP; /* don't strip 8th bit on input */
595 #endif
596 #ifdef OLCUC
597 s.main.c_oflag &= ~OLCUC; /* Disable upcasing on output. */
598 #endif
599 s.main.c_oflag &= ~TAB3; /* Disable tab expansion */
600 s.main.c_cflag = (s.main.c_cflag & ~CSIZE) | CS8; /* Don't strip 8th bit */
601 #if 0
602 /* Said to be unnecessary: */
603 s.main.c_cc[VMIN] = 1; /* minimum number of characters to accept */
604 s.main.c_cc[VTIME] = 0; /* wait forever for at least 1 character */
605 #endif
606
607 s.main.c_lflag |= ICANON; /* Enable erase/kill and eof processing */
608 s.main.c_cc[VEOF] = 04; /* insure that EOF is Control-D */
609 s.main.c_cc[VERASE] = CDISABLE; /* disable erase processing */
610 s.main.c_cc[VKILL] = CDISABLE; /* disable kill processing */
611
612 #ifdef HPUX
613 s.main.c_cflag = (s.main.c_cflag & ~CBAUD) | B9600; /* baud rate sanity */
614 #endif /* HPUX */
615
616 #ifdef AIX
617 /* AIX enhanced edit loses NULs, so disable it */
618 #ifndef IBMR2AIX
619 s.main.c_line = 0;
620 s.main.c_iflag &= ~ASCEDIT;
621 #endif
622 /* Also, PTY overloads NUL and BREAK.
623 don't ignore break, but don't signal either, so it looks like NUL. */
624 s.main.c_iflag &= ~IGNBRK;
625 s.main.c_iflag &= ~BRKINT;
626 /* QUIT and INTR work better as signals, so disable character forms */
627 s.main.c_cc[VINTR] = 0377;
628 #ifdef SIGNALS_VIA_CHARACTERS
629 /* the QUIT and INTR character are used in process_send_signal
630 so set them here to something useful. */
631 if (s.main.c_cc[VQUIT] == 0377)
632 s.main.c_cc[VQUIT] = '\\'&037; /* Control-\ */
633 if (s.main.c_cc[VINTR] == 0377)
634 s.main.c_cc[VINTR] = 'C'&037; /* Control-C */
635 #else /* no TIOCGPGRP or no TIOCGLTC or no TIOCGETC */
636 /* QUIT and INTR work better as signals, so disable character forms */
637 s.main.c_cc[VQUIT] = 0377;
638 s.main.c_cc[VINTR] = 0377;
639 s.main.c_lflag &= ~ISIG;
640 #endif /* no TIOCGPGRP or no TIOCGLTC or no TIOCGETC */
641 s.main.c_cc[VEOL] = 0377;
642 s.main.c_cflag = (s.main.c_cflag & ~CBAUD) | B9600; /* baud rate sanity */
643 #endif /* AIX */
644
645 #else /* not HAVE_TERMIO */
646
647 s.main.sg_flags &= ~(ECHO | CRMOD | ANYP | ALLDELAY | RAW | LCASE
648 | CBREAK | TANDEM);
649 s.main.sg_flags |= LPASS8;
650 s.main.sg_erase = 0377;
651 s.main.sg_kill = 0377;
652 s.lmode = LLITOUT | s.lmode; /* Don't strip 8th bit */
653
654 #endif /* not HAVE_TERMIO */
655
656 EMACS_SET_TTY (out, &s, 0);
657
658 #ifdef BSD4_1
659 if (interrupt_input)
660 reset_sigio ();
661 #endif /* BSD4_1 */
662 #ifdef RTU
663 {
664 int zero = 0;
665 ioctl (out, FIOASYNC, &zero);
666 }
667 #endif /* RTU */
668 #endif /* not DOS_NT */
669 }
670 #endif /* not VMS */
671
672 #endif /* subprocesses */
673 \f
674 /* Record a signal code and the handler for it. */
675 struct save_signal
676 {
677 int code;
678 SIGTYPE (*handler) P_ ((int));
679 };
680
681 static void save_signal_handlers P_ ((struct save_signal *));
682 static void restore_signal_handlers P_ ((struct save_signal *));
683
684 /* Suspend the Emacs process; give terminal to its superior. */
685
686 void
687 sys_suspend ()
688 {
689 #ifdef VMS
690 /* "Foster" parentage allows emacs to return to a subprocess that attached
691 to the current emacs as a cheaper than starting a whole new process. This
692 is set up by KEPTEDITOR.COM. */
693 unsigned long parent_id, foster_parent_id;
694 char *fpid_string;
695
696 fpid_string = getenv ("EMACS_PARENT_PID");
697 if (fpid_string != NULL)
698 {
699 sscanf (fpid_string, "%x", &foster_parent_id);
700 if (foster_parent_id != 0)
701 parent_id = foster_parent_id;
702 else
703 parent_id = getppid ();
704 }
705 else
706 parent_id = getppid ();
707
708 xfree (fpid_string); /* On VMS, this was malloc'd */
709
710 if (parent_id && parent_id != 0xffffffff)
711 {
712 SIGTYPE (*oldsig)() = (int) signal (SIGINT, SIG_IGN);
713 int status = LIB$ATTACH (&parent_id) & 1;
714 signal (SIGINT, oldsig);
715 return status;
716 }
717 else
718 {
719 struct {
720 int l;
721 char *a;
722 } d_prompt;
723 d_prompt.l = sizeof ("Emacs: "); /* Our special prompt */
724 d_prompt.a = "Emacs: "; /* Just a reminder */
725 LIB$SPAWN (0, 0, 0, 0, 0, 0, 0, 0, 0, 0, &d_prompt, 0);
726 return 1;
727 }
728 return -1;
729 #else
730 #if defined (SIGTSTP) && !defined (MSDOS)
731
732 {
733 int pgrp = EMACS_GETPGRP (0);
734 EMACS_KILLPG (pgrp, SIGTSTP);
735 }
736
737 #else /* No SIGTSTP */
738 #ifdef USG_JOBCTRL /* If you don't know what this is don't mess with it */
739 ptrace (0, 0, 0, 0); /* set for ptrace - caught by csh */
740 kill (getpid (), SIGQUIT);
741
742 #else /* No SIGTSTP or USG_JOBCTRL */
743
744 /* On a system where suspending is not implemented,
745 instead fork a subshell and let it talk directly to the terminal
746 while we wait. */
747 sys_subshell ();
748
749 #endif /* no USG_JOBCTRL */
750 #endif /* no SIGTSTP */
751 #endif /* not VMS */
752 }
753
754 /* Fork a subshell. */
755
756 void
757 sys_subshell ()
758 {
759 #ifdef macintosh
760 error ("Can't spawn subshell");
761 #else
762 #ifndef VMS
763 #ifdef DOS_NT /* Demacs 1.1.2 91/10/20 Manabu Higashida */
764 int st;
765 char oldwd[MAXPATHLEN+1]; /* Fixed length is safe on MSDOS. */
766 #endif
767 int pid;
768 struct save_signal saved_handlers[5];
769 Lisp_Object dir;
770 unsigned char *str = 0;
771 int len;
772
773 saved_handlers[0].code = SIGINT;
774 saved_handlers[1].code = SIGQUIT;
775 saved_handlers[2].code = SIGTERM;
776 #ifdef SIGIO
777 saved_handlers[3].code = SIGIO;
778 saved_handlers[4].code = 0;
779 #else
780 saved_handlers[3].code = 0;
781 #endif
782
783 /* Mentioning current_buffer->buffer would mean including buffer.h,
784 which somehow wedges the hp compiler. So instead... */
785
786 dir = intern ("default-directory");
787 if (NILP (Fboundp (dir)))
788 goto xyzzy;
789 dir = Fsymbol_value (dir);
790 if (!STRINGP (dir))
791 goto xyzzy;
792
793 dir = expand_and_dir_to_file (Funhandled_file_name_directory (dir), Qnil);
794 str = (unsigned char *) alloca (XSTRING (dir)->size + 2);
795 len = XSTRING (dir)->size;
796 bcopy (XSTRING (dir)->data, str, len);
797 if (str[len - 1] != '/') str[len++] = '/';
798 str[len] = 0;
799 xyzzy:
800
801 #ifdef DOS_NT
802 pid = 0;
803 #if __DJGPP__ > 1
804 save_signal_handlers (saved_handlers);
805 synch_process_alive = 1;
806 #endif /* __DJGPP__ > 1 */
807 #else
808 pid = vfork ();
809 if (pid == -1)
810 error ("Can't spawn subshell");
811 #endif
812
813 if (pid == 0)
814 {
815 char *sh = 0;
816
817 #ifdef DOS_NT /* MW, Aug 1993 */
818 getwd (oldwd);
819 if (sh == 0)
820 sh = (char *) egetenv ("SUSPEND"); /* KFS, 1994-12-14 */
821 #endif
822 if (sh == 0)
823 sh = (char *) egetenv ("SHELL");
824 if (sh == 0)
825 sh = "sh";
826
827 /* Use our buffer's default directory for the subshell. */
828 if (str)
829 chdir ((char *) str);
830
831 #ifdef subprocesses
832 close_process_descs (); /* Close Emacs's pipes/ptys */
833 #endif
834
835 #ifdef SET_EMACS_PRIORITY
836 {
837 extern int emacs_priority;
838
839 if (emacs_priority < 0)
840 nice (-emacs_priority);
841 }
842 #endif
843
844 #ifdef MSDOS /* Demacs 1.1.2 91/10/20 Manabu Higashida */
845 st = system (sh);
846 chdir (oldwd);
847 #if 0 /* This is also reported if last command executed in subshell failed, KFS */
848 if (st)
849 report_file_error ("Can't execute subshell", Fcons (build_string (sh), Qnil));
850 #endif
851 #else /* not MSDOS */
852 #ifdef WINDOWSNT
853 /* Waits for process completion */
854 pid = _spawnlp (_P_WAIT, sh, sh, NULL);
855 chdir (oldwd);
856 if (pid == -1)
857 write (1, "Can't execute subshell", 22);
858 #else /* not WINDOWSNT */
859 execlp (sh, sh, 0);
860 write (1, "Can't execute subshell", 22);
861 _exit (1);
862 #endif /* not WINDOWSNT */
863 #endif /* not MSDOS */
864 }
865
866 /* Do this now if we did not do it before. */
867 #if !defined (MSDOS) || __DJGPP__ == 1
868 save_signal_handlers (saved_handlers);
869 synch_process_alive = 1;
870 #endif
871
872 #ifndef DOS_NT
873 wait_for_termination (pid);
874 #endif
875 restore_signal_handlers (saved_handlers);
876 synch_process_alive = 0;
877 #endif /* !VMS */
878 #endif /* !macintosh */
879 }
880
881 static void
882 save_signal_handlers (saved_handlers)
883 struct save_signal *saved_handlers;
884 {
885 while (saved_handlers->code)
886 {
887 saved_handlers->handler
888 = (SIGTYPE (*) P_ ((int))) signal (saved_handlers->code, SIG_IGN);
889 saved_handlers++;
890 }
891 }
892
893 static void
894 restore_signal_handlers (saved_handlers)
895 struct save_signal *saved_handlers;
896 {
897 while (saved_handlers->code)
898 {
899 signal (saved_handlers->code, saved_handlers->handler);
900 saved_handlers++;
901 }
902 }
903 \f
904 #ifdef F_SETFL
905
906 int old_fcntl_flags;
907
908 void
909 init_sigio (fd)
910 int fd;
911 {
912 #ifdef FASYNC
913 old_fcntl_flags = fcntl (fd, F_GETFL, 0) & ~FASYNC;
914 fcntl (fd, F_SETFL, old_fcntl_flags | FASYNC);
915 #endif
916 interrupts_deferred = 0;
917 }
918
919 void
920 reset_sigio ()
921 {
922 unrequest_sigio ();
923 }
924
925 #ifdef FASYNC /* F_SETFL does not imply existence of FASYNC */
926
927 void
928 request_sigio ()
929 {
930 if (read_socket_hook)
931 return;
932
933 #ifdef SIGWINCH
934 sigunblock (sigmask (SIGWINCH));
935 #endif
936 fcntl (input_fd, F_SETFL, old_fcntl_flags | FASYNC);
937
938 interrupts_deferred = 0;
939 }
940
941 void
942 unrequest_sigio ()
943 {
944 if (read_socket_hook)
945 return;
946
947 #ifdef SIGWINCH
948 sigblock (sigmask (SIGWINCH));
949 #endif
950 fcntl (input_fd, F_SETFL, old_fcntl_flags);
951 interrupts_deferred = 1;
952 }
953
954 #else /* no FASYNC */
955 #ifdef STRIDE /* Stride doesn't have FASYNC - use FIOASYNC */
956
957 void
958 request_sigio ()
959 {
960 int on = 1;
961
962 if (read_socket_hook)
963 return;
964
965 ioctl (input_fd, FIOASYNC, &on);
966 interrupts_deferred = 0;
967 }
968
969 void
970 unrequest_sigio ()
971 {
972 int off = 0;
973
974 if (read_socket_hook)
975 return;
976
977 ioctl (input_fd, FIOASYNC, &off);
978 interrupts_deferred = 1;
979 }
980
981 #else /* not FASYNC, not STRIDE */
982
983 #ifdef _CX_UX
984
985 #include <termios.h>
986
987 void
988 request_sigio ()
989 {
990 int on = 1;
991 sigset_t st;
992
993 if (read_socket_hook)
994 return;
995
996 sigemptyset (&st);
997 sigaddset (&st, SIGIO);
998 ioctl (input_fd, FIOASYNC, &on);
999 interrupts_deferred = 0;
1000 sigprocmask (SIG_UNBLOCK, &st, (sigset_t *)0);
1001 }
1002
1003 void
1004 unrequest_sigio ()
1005 {
1006 int off = 0;
1007
1008 if (read_socket_hook)
1009 return;
1010
1011 ioctl (input_fd, FIOASYNC, &off);
1012 interrupts_deferred = 1;
1013 }
1014
1015 #else /* ! _CX_UX */
1016
1017 void
1018 request_sigio ()
1019 {
1020 if (read_socket_hook)
1021 return;
1022
1023 croak ("request_sigio");
1024 }
1025
1026 void
1027 unrequest_sigio ()
1028 {
1029 if (read_socket_hook)
1030 return;
1031
1032 croak ("unrequest_sigio");
1033 }
1034
1035 #endif /* _CX_UX */
1036 #endif /* STRIDE */
1037 #endif /* FASYNC */
1038 #endif /* F_SETFL */
1039 \f
1040 /* Saving and restoring the process group of Emacs's terminal. */
1041
1042 #ifdef BSD_PGRPS
1043
1044 /* The process group of which Emacs was a member when it initially
1045 started.
1046
1047 If Emacs was in its own process group (i.e. inherited_pgroup ==
1048 getpid ()), then we know we're running under a shell with job
1049 control (Emacs would never be run as part of a pipeline).
1050 Everything is fine.
1051
1052 If Emacs was not in its own process group, then we know we're
1053 running under a shell (or a caller) that doesn't know how to
1054 separate itself from Emacs (like sh). Emacs must be in its own
1055 process group in order to receive SIGIO correctly. In this
1056 situation, we put ourselves in our own pgroup, forcibly set the
1057 tty's pgroup to our pgroup, and make sure to restore and reinstate
1058 the tty's pgroup just like any other terminal setting. If
1059 inherited_group was not the tty's pgroup, then we'll get a
1060 SIGTTmumble when we try to change the tty's pgroup, and a CONT if
1061 it goes foreground in the future, which is what should happen. */
1062 int inherited_pgroup;
1063
1064 /* Split off the foreground process group to Emacs alone.
1065 When we are in the foreground, but not started in our own process
1066 group, redirect the TTY to point to our own process group. We need
1067 to be in our own process group to receive SIGIO properly. */
1068 void
1069 narrow_foreground_group ()
1070 {
1071 int me = getpid ();
1072
1073 setpgrp (0, inherited_pgroup);
1074 if (inherited_pgroup != me)
1075 EMACS_SET_TTY_PGRP (input_fd, &me);
1076 setpgrp (0, me);
1077 }
1078
1079 /* Set the tty to our original foreground group. */
1080 void
1081 widen_foreground_group ()
1082 {
1083 if (inherited_pgroup != getpid ())
1084 EMACS_SET_TTY_PGRP (input_fd, &inherited_pgroup);
1085 setpgrp (0, inherited_pgroup);
1086 }
1087
1088 #endif /* BSD_PGRPS */
1089 \f
1090 /* Getting and setting emacs_tty structures. */
1091
1092 /* Set *TC to the parameters associated with the terminal FD.
1093 Return zero if all's well, or -1 if we ran into an error we
1094 couldn't deal with. */
1095 int
1096 emacs_get_tty (fd, settings)
1097 int fd;
1098 struct emacs_tty *settings;
1099 {
1100 /* Retrieve the primary parameters - baud rate, character size, etcetera. */
1101 #ifdef HAVE_TCATTR
1102 /* We have those nifty POSIX tcmumbleattr functions. */
1103 bzero (&settings->main, sizeof (settings->main));
1104 if (tcgetattr (fd, &settings->main) < 0)
1105 return -1;
1106
1107 #else
1108 #ifdef HAVE_TERMIO
1109 /* The SYSV-style interface? */
1110 if (ioctl (fd, TCGETA, &settings->main) < 0)
1111 return -1;
1112
1113 #else
1114 #ifdef VMS
1115 /* Vehemently Monstrous System? :-) */
1116 if (! (SYS$QIOW (0, fd, IO$_SENSEMODE, settings, 0, 0,
1117 &settings->main.class, 12, 0, 0, 0, 0)
1118 & 1))
1119 return -1;
1120
1121 #else
1122 #ifndef DOS_NT
1123 /* I give up - I hope you have the BSD ioctls. */
1124 if (ioctl (fd, TIOCGETP, &settings->main) < 0)
1125 return -1;
1126 #endif /* not DOS_NT */
1127 #endif
1128 #endif
1129 #endif
1130
1131 /* Suivant - Do we have to get struct ltchars data? */
1132 #ifdef HAVE_LTCHARS
1133 if (ioctl (fd, TIOCGLTC, &settings->ltchars) < 0)
1134 return -1;
1135 #endif
1136
1137 /* How about a struct tchars and a wordful of lmode bits? */
1138 #ifdef HAVE_TCHARS
1139 if (ioctl (fd, TIOCGETC, &settings->tchars) < 0
1140 || ioctl (fd, TIOCLGET, &settings->lmode) < 0)
1141 return -1;
1142 #endif
1143
1144 /* We have survived the tempest. */
1145 return 0;
1146 }
1147
1148
1149 /* Set the parameters of the tty on FD according to the contents of
1150 *SETTINGS. If FLUSHP is non-zero, we discard input.
1151 Return 0 if all went well, and -1 if anything failed. */
1152
1153 int
1154 emacs_set_tty (fd, settings, flushp)
1155 int fd;
1156 struct emacs_tty *settings;
1157 int flushp;
1158 {
1159 /* Set the primary parameters - baud rate, character size, etcetera. */
1160 #ifdef HAVE_TCATTR
1161 int i;
1162 /* We have those nifty POSIX tcmumbleattr functions.
1163 William J. Smith <wjs@wiis.wang.com> writes:
1164 "POSIX 1003.1 defines tcsetattr to return success if it was
1165 able to perform any of the requested actions, even if some
1166 of the requested actions could not be performed.
1167 We must read settings back to ensure tty setup properly.
1168 AIX requires this to keep tty from hanging occasionally." */
1169 /* This make sure that we don't loop indefinitely in here. */
1170 for (i = 0 ; i < 10 ; i++)
1171 if (tcsetattr (fd, flushp ? TCSAFLUSH : TCSADRAIN, &settings->main) < 0)
1172 {
1173 if (errno == EINTR)
1174 continue;
1175 else
1176 return -1;
1177 }
1178 else
1179 {
1180 struct termios new;
1181
1182 bzero (&new, sizeof (new));
1183 /* Get the current settings, and see if they're what we asked for. */
1184 tcgetattr (fd, &new);
1185 /* We cannot use memcmp on the whole structure here because under
1186 * aix386 the termios structure has some reserved field that may
1187 * not be filled in.
1188 */
1189 if ( new.c_iflag == settings->main.c_iflag
1190 && new.c_oflag == settings->main.c_oflag
1191 && new.c_cflag == settings->main.c_cflag
1192 && new.c_lflag == settings->main.c_lflag
1193 && memcmp (new.c_cc, settings->main.c_cc, NCCS) == 0)
1194 break;
1195 else
1196 continue;
1197 }
1198
1199 #else
1200 #ifdef HAVE_TERMIO
1201 /* The SYSV-style interface? */
1202 if (ioctl (fd, flushp ? TCSETAF : TCSETAW, &settings->main) < 0)
1203 return -1;
1204
1205 #else
1206 #ifdef VMS
1207 /* Vehemently Monstrous System? :-) */
1208 if (! (SYS$QIOW (0, fd, IO$_SETMODE, &input_iosb, 0, 0,
1209 &settings->main.class, 12, 0, 0, 0, 0)
1210 & 1))
1211 return -1;
1212
1213 #else
1214 #ifndef DOS_NT
1215 /* I give up - I hope you have the BSD ioctls. */
1216 if (ioctl (fd, (flushp) ? TIOCSETP : TIOCSETN, &settings->main) < 0)
1217 return -1;
1218 #endif /* not DOS_NT */
1219
1220 #endif
1221 #endif
1222 #endif
1223
1224 /* Suivant - Do we have to get struct ltchars data? */
1225 #ifdef HAVE_LTCHARS
1226 if (ioctl (fd, TIOCSLTC, &settings->ltchars) < 0)
1227 return -1;
1228 #endif
1229
1230 /* How about a struct tchars and a wordful of lmode bits? */
1231 #ifdef HAVE_TCHARS
1232 if (ioctl (fd, TIOCSETC, &settings->tchars) < 0
1233 || ioctl (fd, TIOCLSET, &settings->lmode) < 0)
1234 return -1;
1235 #endif
1236
1237 /* We have survived the tempest. */
1238 return 0;
1239 }
1240
1241 \f
1242 /* The initial tty mode bits */
1243 struct emacs_tty old_tty;
1244
1245 /* 1 if we have been through init_sys_modes. */
1246 int term_initted;
1247
1248 /* 1 if outer tty status has been recorded. */
1249 int old_tty_valid;
1250
1251 #ifdef BSD4_1
1252 /* BSD 4.1 needs to keep track of the lmode bits in order to start
1253 sigio. */
1254 int lmode;
1255 #endif
1256
1257 #ifndef F_SETOWN_BUG
1258 #ifdef F_SETOWN
1259 int old_fcntl_owner;
1260 #endif /* F_SETOWN */
1261 #endif /* F_SETOWN_BUG */
1262
1263 /* This may also be defined in stdio,
1264 but if so, this does no harm,
1265 and using the same name avoids wasting the other one's space. */
1266
1267 #ifdef nec_ews_svr4
1268 extern char *_sobuf ;
1269 #else
1270 #if defined (USG) || defined (DGUX)
1271 unsigned char _sobuf[BUFSIZ+8];
1272 #else
1273 char _sobuf[BUFSIZ];
1274 #endif
1275 #endif
1276
1277 #ifdef HAVE_LTCHARS
1278 static struct ltchars new_ltchars = {-1,-1,-1,-1,-1,-1};
1279 #endif
1280 #ifdef HAVE_TCHARS
1281 static struct tchars new_tchars = {-1,-1,-1,-1,-1,-1};
1282 #endif
1283
1284 void
1285 init_sys_modes ()
1286 {
1287 struct emacs_tty tty;
1288
1289 #ifdef macintosh
1290 Vwindow_system = intern ("mac");
1291 Vwindow_system_version = make_number (1);
1292
1293 /* cus-start.el complains if delete-exited-processes and x-bitmap-file-path not defined */
1294 #ifndef subprocesses
1295 DEFVAR_BOOL ("delete-exited-processes", &delete_exited_processes,
1296 "*Non-nil means delete processes immediately when they exit.\n\
1297 nil means don't delete them until `list-processes' is run.");
1298 delete_exited_processes = 0;
1299 #endif
1300
1301 #ifndef HAVE_X_WINDOWS
1302 DEFVAR_LISP ("x-bitmap-file-path", &Vx_bitmap_file_path,
1303 "List of directories to search for bitmap files for X.");
1304 Vx_bitmap_file_path = decode_env_path ((char *) 0, ".");
1305 #endif
1306
1307 #endif /* not macintosh */
1308
1309 #ifdef VMS
1310 #if 0
1311 static int oob_chars[2] = {0, 1 << 7}; /* catch C-g's */
1312 extern int (*interrupt_signal) ();
1313 #endif
1314 #endif
1315
1316 Vtty_erase_char = Qnil;
1317
1318 if (noninteractive)
1319 return;
1320
1321 #ifdef VMS
1322 if (!input_ef)
1323 input_ef = get_kbd_event_flag ();
1324 /* LIB$GET_EF (&input_ef); */
1325 SYS$CLREF (input_ef);
1326 waiting_for_ast = 0;
1327 if (!timer_ef)
1328 timer_ef = get_timer_event_flag ();
1329 /* LIB$GET_EF (&timer_ef); */
1330 SYS$CLREF (timer_ef);
1331 #if 0
1332 if (!process_ef)
1333 {
1334 LIB$GET_EF (&process_ef);
1335 SYS$CLREF (process_ef);
1336 }
1337 if (input_ef / 32 != process_ef / 32)
1338 croak ("Input and process event flags in different clusters.");
1339 #endif
1340 if (input_ef / 32 != timer_ef / 32)
1341 croak ("Input and timer event flags in different clusters.");
1342 #if 0
1343 input_eflist = ((unsigned) 1 << (input_ef % 32)) |
1344 ((unsigned) 1 << (process_ef % 32));
1345 #endif
1346 timer_eflist = ((unsigned) 1 << (input_ef % 32)) |
1347 ((unsigned) 1 << (timer_ef % 32));
1348 #ifndef VMS4_4
1349 sys_access_reinit ();
1350 #endif
1351 #endif /* not VMS */
1352
1353 #ifdef BSD_PGRPS
1354 if (! read_socket_hook && EQ (Vwindow_system, Qnil))
1355 narrow_foreground_group ();
1356 #endif
1357
1358 #ifdef HAVE_WINDOW_SYSTEM
1359 /* Emacs' window system on MSDOG uses the `internal terminal' and therefore
1360 needs the initialization code below. */
1361 if (!read_socket_hook && EQ (Vwindow_system, Qnil))
1362 #endif
1363 {
1364 EMACS_GET_TTY (input_fd, &old_tty);
1365
1366 old_tty_valid = 1;
1367
1368 tty = old_tty;
1369
1370 #if defined (HAVE_TERMIO) || defined (HAVE_TERMIOS)
1371 XSETINT (Vtty_erase_char, old_tty.main.c_cc[VERASE]);
1372
1373 #ifdef DGUX
1374 /* This allows meta to be sent on 8th bit. */
1375 tty.main.c_iflag &= ~INPCK; /* don't check input for parity */
1376 #endif
1377 tty.main.c_iflag |= (IGNBRK); /* Ignore break condition */
1378 tty.main.c_iflag &= ~ICRNL; /* Disable map of CR to NL on input */
1379 #ifdef INLCR /* I'm just being cautious,
1380 since I can't check how widespread INLCR is--rms. */
1381 tty.main.c_iflag &= ~INLCR; /* Disable map of NL to CR on input */
1382 #endif
1383 #ifdef ISTRIP
1384 tty.main.c_iflag &= ~ISTRIP; /* don't strip 8th bit on input */
1385 #endif
1386 tty.main.c_lflag &= ~ECHO; /* Disable echo */
1387 tty.main.c_lflag &= ~ICANON; /* Disable erase/kill processing */
1388 #ifdef IEXTEN
1389 tty.main.c_lflag &= ~IEXTEN; /* Disable other editing characters. */
1390 #endif
1391 tty.main.c_lflag |= ISIG; /* Enable signals */
1392 if (flow_control)
1393 {
1394 tty.main.c_iflag |= IXON; /* Enable start/stop output control */
1395 #ifdef IXANY
1396 tty.main.c_iflag &= ~IXANY;
1397 #endif /* IXANY */
1398 }
1399 else
1400 tty.main.c_iflag &= ~IXON; /* Disable start/stop output control */
1401 tty.main.c_oflag &= ~ONLCR; /* Disable map of NL to CR-NL
1402 on output */
1403 tty.main.c_oflag &= ~TAB3; /* Disable tab expansion */
1404 #ifdef CS8
1405 if (meta_key)
1406 {
1407 tty.main.c_cflag |= CS8; /* allow 8th bit on input */
1408 tty.main.c_cflag &= ~PARENB;/* Don't check parity */
1409 }
1410 #endif
1411 tty.main.c_cc[VINTR] = quit_char; /* C-g (usually) gives SIGINT */
1412 /* Set up C-g for both SIGQUIT and SIGINT.
1413 We don't know which we will get, but we handle both alike
1414 so which one it really gives us does not matter. */
1415 tty.main.c_cc[VQUIT] = quit_char;
1416 tty.main.c_cc[VMIN] = 1; /* Input should wait for at least 1 char */
1417 tty.main.c_cc[VTIME] = 0; /* no matter how long that takes. */
1418 #ifdef VSWTCH
1419 tty.main.c_cc[VSWTCH] = CDISABLE; /* Turn off shell layering use
1420 of C-z */
1421 #endif /* VSWTCH */
1422
1423 #if defined (mips) || defined (HAVE_TCATTR)
1424 #ifdef VSUSP
1425 tty.main.c_cc[VSUSP] = CDISABLE; /* Turn off mips handling of C-z. */
1426 #endif /* VSUSP */
1427 #ifdef V_DSUSP
1428 tty.main.c_cc[V_DSUSP] = CDISABLE; /* Turn off mips handling of C-y. */
1429 #endif /* V_DSUSP */
1430 #ifdef VDSUSP /* Some systems have VDSUSP, some have V_DSUSP. */
1431 tty.main.c_cc[VDSUSP] = CDISABLE;
1432 #endif /* VDSUSP */
1433 #ifdef VLNEXT
1434 tty.main.c_cc[VLNEXT] = CDISABLE;
1435 #endif /* VLNEXT */
1436 #ifdef VREPRINT
1437 tty.main.c_cc[VREPRINT] = CDISABLE;
1438 #endif /* VREPRINT */
1439 #ifdef VWERASE
1440 tty.main.c_cc[VWERASE] = CDISABLE;
1441 #endif /* VWERASE */
1442 #ifdef VDISCARD
1443 tty.main.c_cc[VDISCARD] = CDISABLE;
1444 #endif /* VDISCARD */
1445
1446 if (flow_control)
1447 {
1448 #ifdef VSTART
1449 tty.main.c_cc[VSTART] = '\021';
1450 #endif /* VSTART */
1451 #ifdef VSTOP
1452 tty.main.c_cc[VSTOP] = '\023';
1453 #endif /* VSTOP */
1454 }
1455 else
1456 {
1457 #ifdef VSTART
1458 tty.main.c_cc[VSTART] = CDISABLE;
1459 #endif /* VSTART */
1460 #ifdef VSTOP
1461 tty.main.c_cc[VSTOP] = CDISABLE;
1462 #endif /* VSTOP */
1463 }
1464 #endif /* mips or HAVE_TCATTR */
1465
1466 #ifdef SET_LINE_DISCIPLINE
1467 /* Need to explicitly request TERMIODISC line discipline or
1468 Ultrix's termios does not work correctly. */
1469 tty.main.c_line = SET_LINE_DISCIPLINE;
1470 #endif
1471 #ifdef AIX
1472 #ifndef IBMR2AIX
1473 /* AIX enhanced edit loses NULs, so disable it. */
1474 tty.main.c_line = 0;
1475 tty.main.c_iflag &= ~ASCEDIT;
1476 #else
1477 tty.main.c_cc[VSTRT] = 255;
1478 tty.main.c_cc[VSTOP] = 255;
1479 tty.main.c_cc[VSUSP] = 255;
1480 tty.main.c_cc[VDSUSP] = 255;
1481 #endif /* IBMR2AIX */
1482 if (flow_control)
1483 {
1484 #ifdef VSTART
1485 tty.main.c_cc[VSTART] = '\021';
1486 #endif /* VSTART */
1487 #ifdef VSTOP
1488 tty.main.c_cc[VSTOP] = '\023';
1489 #endif /* VSTOP */
1490 }
1491 /* Also, PTY overloads NUL and BREAK.
1492 don't ignore break, but don't signal either, so it looks like NUL.
1493 This really serves a purpose only if running in an XTERM window
1494 or via TELNET or the like, but does no harm elsewhere. */
1495 tty.main.c_iflag &= ~IGNBRK;
1496 tty.main.c_iflag &= ~BRKINT;
1497 #endif
1498 #else /* if not HAVE_TERMIO */
1499 #ifdef VMS
1500 tty.main.tt_char |= TT$M_NOECHO;
1501 if (meta_key)
1502 tty.main.tt_char |= TT$M_EIGHTBIT;
1503 if (flow_control)
1504 tty.main.tt_char |= TT$M_TTSYNC;
1505 else
1506 tty.main.tt_char &= ~TT$M_TTSYNC;
1507 tty.main.tt2_char |= TT2$M_PASTHRU | TT2$M_XON;
1508 #else /* not VMS (BSD, that is) */
1509 #ifndef DOS_NT
1510 XSETINT (Vtty_erase_char, tty.main.sg_erase);
1511 tty.main.sg_flags &= ~(ECHO | CRMOD | XTABS);
1512 if (meta_key)
1513 tty.main.sg_flags |= ANYP;
1514 tty.main.sg_flags |= interrupt_input ? RAW : CBREAK;
1515 #endif /* not DOS_NT */
1516 #endif /* not VMS (BSD, that is) */
1517 #endif /* not HAVE_TERMIO */
1518
1519 /* If going to use CBREAK mode, we must request C-g to interrupt
1520 and turn off start and stop chars, etc. If not going to use
1521 CBREAK mode, do this anyway so as to turn off local flow
1522 control for user coming over network on 4.2; in this case,
1523 only t_stopc and t_startc really matter. */
1524 #ifndef HAVE_TERMIO
1525 #ifdef HAVE_TCHARS
1526 /* Note: if not using CBREAK mode, it makes no difference how we
1527 set this */
1528 tty.tchars = new_tchars;
1529 tty.tchars.t_intrc = quit_char;
1530 if (flow_control)
1531 {
1532 tty.tchars.t_startc = '\021';
1533 tty.tchars.t_stopc = '\023';
1534 }
1535
1536 tty.lmode = LDECCTQ | LLITOUT | LPASS8 | LNOFLSH | old_tty.lmode;
1537 #ifdef ultrix
1538 /* Under Ultrix 4.2a, leaving this out doesn't seem to hurt
1539 anything, and leaving it in breaks the meta key. Go figure. */
1540 tty.lmode &= ~LLITOUT;
1541 #endif
1542
1543 #ifdef BSD4_1
1544 lmode = tty.lmode;
1545 #endif
1546
1547 #endif /* HAVE_TCHARS */
1548 #endif /* not HAVE_TERMIO */
1549
1550 #ifdef HAVE_LTCHARS
1551 tty.ltchars = new_ltchars;
1552 #endif /* HAVE_LTCHARS */
1553 #ifdef MSDOS /* Demacs 1.1.2 91/10/20 Manabu Higashida, MW Aug 1993 */
1554 if (!term_initted)
1555 internal_terminal_init ();
1556 dos_ttraw ();
1557 #endif
1558
1559 EMACS_SET_TTY (input_fd, &tty, 0);
1560
1561 /* This code added to insure that, if flow-control is not to be used,
1562 we have an unlocked terminal at the start. */
1563
1564 #ifdef TCXONC
1565 if (!flow_control) ioctl (input_fd, TCXONC, 1);
1566 #endif
1567 #ifndef APOLLO
1568 #ifdef TIOCSTART
1569 if (!flow_control) ioctl (input_fd, TIOCSTART, 0);
1570 #endif
1571 #endif
1572
1573 #if defined (HAVE_TERMIOS) || defined (HPUX9)
1574 #ifdef TCOON
1575 if (!flow_control) tcflow (input_fd, TCOON);
1576 #endif
1577 #endif
1578
1579 #ifdef AIXHFT
1580 hft_init ();
1581 #ifdef IBMR2AIX
1582 {
1583 /* IBM's HFT device usually thinks a ^J should be LF/CR. We need it
1584 to be only LF. This is the way that is done. */
1585 struct termio tty;
1586
1587 if (ioctl (1, HFTGETID, &tty) != -1)
1588 write (1, "\033[20l", 5);
1589 }
1590 #endif
1591 #endif /* AIXHFT */
1592
1593 #ifdef VMS
1594 /* Appears to do nothing when in PASTHRU mode.
1595 SYS$QIOW (0, input_fd, IO$_SETMODE|IO$M_OUTBAND, 0, 0, 0,
1596 interrupt_signal, oob_chars, 0, 0, 0, 0);
1597 */
1598 queue_kbd_input (0);
1599 #endif /* VMS */
1600 }
1601
1602 #ifdef F_SETFL
1603 #ifndef F_SETOWN_BUG
1604 #ifdef F_GETOWN /* F_SETFL does not imply existence of F_GETOWN */
1605 if (interrupt_input
1606 && ! read_socket_hook && EQ (Vwindow_system, Qnil))
1607 {
1608 old_fcntl_owner = fcntl (input_fd, F_GETOWN, 0);
1609 fcntl (input_fd, F_SETOWN, getpid ());
1610 init_sigio (input_fd);
1611 }
1612 #endif /* F_GETOWN */
1613 #endif /* F_SETOWN_BUG */
1614 #endif /* F_SETFL */
1615
1616 #ifdef BSD4_1
1617 if (interrupt_input)
1618 init_sigio (input_fd);
1619 #endif
1620
1621 #ifdef VMS /* VMS sometimes has this symbol but lacks setvbuf. */
1622 #undef _IOFBF
1623 #endif
1624 #ifdef _IOFBF
1625 /* This symbol is defined on recent USG systems.
1626 Someone says without this call USG won't really buffer the file
1627 even with a call to setbuf. */
1628 setvbuf (stdout, (char *) _sobuf, _IOFBF, sizeof _sobuf);
1629 #else
1630 setbuf (stdout, (char *) _sobuf);
1631 #endif
1632 #ifdef HAVE_WINDOW_SYSTEM
1633 /* Emacs' window system on MSDOG uses the `internal terminal' and therefore
1634 needs the initialization code below. */
1635 if (EQ (Vwindow_system, Qnil)
1636 #ifndef WINDOWSNT
1637 /* When running in tty mode on NT/Win95, we have a read_socket
1638 hook, but still need the rest of the initialization code below. */
1639 && (! read_socket_hook)
1640 #endif
1641 )
1642 #endif
1643 set_terminal_modes ();
1644
1645 if (!term_initted
1646 && FRAMEP (Vterminal_frame)
1647 && FRAME_TERMCAP_P (XFRAME (Vterminal_frame)))
1648 init_frame_faces (XFRAME (Vterminal_frame));
1649
1650 if (term_initted && no_redraw_on_reenter)
1651 {
1652 if (display_completed)
1653 direct_output_forward_char (0);
1654 }
1655 else
1656 {
1657 frame_garbaged = 1;
1658 if (FRAMEP (Vterminal_frame))
1659 FRAME_GARBAGED_P (XFRAME (Vterminal_frame)) = 1;
1660 }
1661
1662 term_initted = 1;
1663 }
1664
1665 /* Return nonzero if safe to use tabs in output.
1666 At the time this is called, init_sys_modes has not been done yet. */
1667
1668 int
1669 tabs_safe_p ()
1670 {
1671 struct emacs_tty tty;
1672
1673 EMACS_GET_TTY (input_fd, &tty);
1674 return EMACS_TTY_TABS_OK (&tty);
1675 }
1676 \f
1677 /* Get terminal size from system.
1678 Store number of lines into *HEIGHTP and width into *WIDTHP.
1679 We store 0 if there's no valid information. */
1680
1681 void
1682 get_frame_size (widthp, heightp)
1683 int *widthp, *heightp;
1684 {
1685
1686 #ifdef TIOCGWINSZ
1687
1688 /* BSD-style. */
1689 struct winsize size;
1690
1691 if (ioctl (input_fd, TIOCGWINSZ, &size) == -1)
1692 *widthp = *heightp = 0;
1693 else
1694 {
1695 *widthp = size.ws_col;
1696 *heightp = size.ws_row;
1697 }
1698
1699 #else
1700 #ifdef TIOCGSIZE
1701
1702 /* SunOS - style. */
1703 struct ttysize size;
1704
1705 if (ioctl (input_fd, TIOCGSIZE, &size) == -1)
1706 *widthp = *heightp = 0;
1707 else
1708 {
1709 *widthp = size.ts_cols;
1710 *heightp = size.ts_lines;
1711 }
1712
1713 #else
1714 #ifdef VMS
1715
1716 struct sensemode tty;
1717
1718 SYS$QIOW (0, input_fd, IO$_SENSEMODE, &tty, 0, 0,
1719 &tty.class, 12, 0, 0, 0, 0);
1720 *widthp = tty.scr_wid;
1721 *heightp = tty.scr_len;
1722
1723 #else
1724 #ifdef MSDOS
1725 *widthp = ScreenCols ();
1726 *heightp = ScreenRows ();
1727 #else /* system doesn't know size */
1728 *widthp = 0;
1729 *heightp = 0;
1730 #endif
1731
1732 #endif /* not VMS */
1733 #endif /* not SunOS-style */
1734 #endif /* not BSD-style */
1735 }
1736
1737 /* Set the logical window size associated with descriptor FD
1738 to HEIGHT and WIDTH. This is used mainly with ptys. */
1739
1740 int
1741 set_window_size (fd, height, width)
1742 int fd, height, width;
1743 {
1744 #ifdef TIOCSWINSZ
1745
1746 /* BSD-style. */
1747 struct winsize size;
1748 size.ws_row = height;
1749 size.ws_col = width;
1750
1751 if (ioctl (fd, TIOCSWINSZ, &size) == -1)
1752 return 0; /* error */
1753 else
1754 return 1;
1755
1756 #else
1757 #ifdef TIOCSSIZE
1758
1759 /* SunOS - style. */
1760 struct ttysize size;
1761 size.ts_lines = height;
1762 size.ts_cols = width;
1763
1764 if (ioctl (fd, TIOCGSIZE, &size) == -1)
1765 return 0;
1766 else
1767 return 1;
1768 #else
1769 return -1;
1770 #endif /* not SunOS-style */
1771 #endif /* not BSD-style */
1772 }
1773
1774 \f
1775 /* Prepare the terminal for exiting Emacs; move the cursor to the
1776 bottom of the frame, turn off interrupt-driven I/O, etc. */
1777 void
1778 reset_sys_modes ()
1779 {
1780 struct frame *sf;
1781
1782 if (noninteractive)
1783 {
1784 fflush (stdout);
1785 return;
1786 }
1787 if (!term_initted)
1788 return;
1789 #ifdef HAVE_WINDOW_SYSTEM
1790 /* Emacs' window system on MSDOG uses the `internal terminal' and therefore
1791 needs the clean-up code below. */
1792 if (!EQ (Vwindow_system, Qnil)
1793 #ifndef WINDOWSNT
1794 /* When running in tty mode on NT/Win95, we have a read_socket
1795 hook, but still need the rest of the clean-up code below. */
1796 || read_socket_hook
1797 #endif
1798 )
1799 return;
1800 #endif
1801 sf = SELECTED_FRAME ();
1802 cursor_to (FRAME_HEIGHT (sf) - 1, 0);
1803 clear_end_of_line (FRAME_WIDTH (sf));
1804 /* clear_end_of_line may move the cursor */
1805 cursor_to (FRAME_HEIGHT (sf) - 1, 0);
1806 #if defined (IBMR2AIX) && defined (AIXHFT)
1807 {
1808 /* HFT devices normally use ^J as a LF/CR. We forced it to
1809 do the LF only. Now, we need to reset it. */
1810 struct termio tty;
1811
1812 if (ioctl (1, HFTGETID, &tty) != -1)
1813 write (1, "\033[20h", 5);
1814 }
1815 #endif
1816
1817 reset_terminal_modes ();
1818 fflush (stdout);
1819 #ifdef BSD_SYSTEM
1820 #ifndef BSD4_1
1821 /* Avoid possible loss of output when changing terminal modes. */
1822 fsync (fileno (stdout));
1823 #endif
1824 #endif
1825
1826 #ifdef F_SETFL
1827 #ifndef F_SETOWN_BUG
1828 #ifdef F_SETOWN /* F_SETFL does not imply existence of F_SETOWN */
1829 if (interrupt_input)
1830 {
1831 reset_sigio ();
1832 fcntl (input_fd, F_SETOWN, old_fcntl_owner);
1833 }
1834 #endif /* F_SETOWN */
1835 #endif /* F_SETOWN_BUG */
1836 #ifdef O_NDELAY
1837 fcntl (input_fd, F_SETFL, fcntl (input_fd, F_GETFL, 0) & ~O_NDELAY);
1838 #endif
1839 #endif /* F_SETFL */
1840 #ifdef BSD4_1
1841 if (interrupt_input)
1842 reset_sigio ();
1843 #endif /* BSD4_1 */
1844
1845 if (old_tty_valid)
1846 while (EMACS_SET_TTY (input_fd, &old_tty, 0) < 0 && errno == EINTR)
1847 ;
1848
1849 #ifdef MSDOS /* Demacs 1.1.2 91/10/20 Manabu Higashida */
1850 dos_ttcooked ();
1851 #endif
1852
1853 #ifdef SET_LINE_DISCIPLINE
1854 /* Ultrix's termios *ignores* any line discipline except TERMIODISC.
1855 A different old line discipline is therefore not restored, yet.
1856 Restore the old line discipline by hand. */
1857 ioctl (0, TIOCSETD, &old_tty.main.c_line);
1858 #endif
1859
1860 #ifdef AIXHFT
1861 hft_reset ();
1862 #endif
1863
1864 #ifdef BSD_PGRPS
1865 widen_foreground_group ();
1866 #endif
1867 }
1868 \f
1869 #ifdef HAVE_PTYS
1870
1871 /* Set up the proper status flags for use of a pty. */
1872
1873 void
1874 setup_pty (fd)
1875 int fd;
1876 {
1877 /* I'm told that TOICREMOTE does not mean control chars
1878 "can't be sent" but rather that they don't have
1879 input-editing or signaling effects.
1880 That should be good, because we have other ways
1881 to do those things in Emacs.
1882 However, telnet mode seems not to work on 4.2.
1883 So TIOCREMOTE is turned off now. */
1884
1885 /* Under hp-ux, if TIOCREMOTE is turned on, some calls
1886 will hang. In particular, the "timeout" feature (which
1887 causes a read to return if there is no data available)
1888 does this. Also it is known that telnet mode will hang
1889 in such a way that Emacs must be stopped (perhaps this
1890 is the same problem).
1891
1892 If TIOCREMOTE is turned off, then there is a bug in
1893 hp-ux which sometimes loses data. Apparently the
1894 code which blocks the master process when the internal
1895 buffer fills up does not work. Other than this,
1896 though, everything else seems to work fine.
1897
1898 Since the latter lossage is more benign, we may as well
1899 lose that way. -- cph */
1900 #ifdef FIONBIO
1901 #ifdef SYSV_PTYS
1902 {
1903 int on = 1;
1904 ioctl (fd, FIONBIO, &on);
1905 }
1906 #endif
1907 #endif
1908 #ifdef IBMRTAIX
1909 /* On AIX, the parent gets SIGHUP when a pty attached child dies. So, we */
1910 /* ignore SIGHUP once we've started a child on a pty. Note that this may */
1911 /* cause EMACS not to die when it should, i.e., when its own controlling */
1912 /* tty goes away. I've complained to the AIX developers, and they may */
1913 /* change this behavior, but I'm not going to hold my breath. */
1914 signal (SIGHUP, SIG_IGN);
1915 #endif
1916 }
1917 #endif /* HAVE_PTYS */
1918 \f
1919 #ifdef VMS
1920
1921 /* Assigning an input channel is done at the start of Emacs execution.
1922 This is called each time Emacs is resumed, also, but does nothing
1923 because input_chain is no longer zero. */
1924
1925 void
1926 init_vms_input ()
1927 {
1928 int status;
1929
1930 if (input_fd == 0)
1931 {
1932 status = SYS$ASSIGN (&input_dsc, &input_fd, 0, 0);
1933 if (! (status & 1))
1934 LIB$STOP (status);
1935 }
1936 }
1937
1938 /* Deassigning the input channel is done before exiting. */
1939
1940 void
1941 stop_vms_input ()
1942 {
1943 return SYS$DASSGN (input_fd);
1944 }
1945
1946 short input_buffer;
1947
1948 /* Request reading one character into the keyboard buffer.
1949 This is done as soon as the buffer becomes empty. */
1950
1951 void
1952 queue_kbd_input ()
1953 {
1954 int status;
1955 extern kbd_input_ast ();
1956
1957 waiting_for_ast = 0;
1958 stop_input = 0;
1959 status = SYS$QIO (0, input_fd, IO$_READVBLK,
1960 &input_iosb, kbd_input_ast, 1,
1961 &input_buffer, 1, 0, terminator_mask, 0, 0);
1962 }
1963
1964 int input_count;
1965
1966 /* Ast routine that is called when keyboard input comes in
1967 in accord with the SYS$QIO above. */
1968
1969 void
1970 kbd_input_ast ()
1971 {
1972 register int c = -1;
1973 int old_errno = errno;
1974 extern EMACS_TIME *input_available_clear_time;
1975
1976 if (waiting_for_ast)
1977 SYS$SETEF (input_ef);
1978 waiting_for_ast = 0;
1979 input_count++;
1980 #ifdef ASTDEBUG
1981 if (input_count == 25)
1982 exit (1);
1983 printf ("Ast # %d,", input_count);
1984 printf (" iosb = %x, %x, %x, %x",
1985 input_iosb.offset, input_iosb.status, input_iosb.termlen,
1986 input_iosb.term);
1987 #endif
1988 if (input_iosb.offset)
1989 {
1990 c = input_buffer;
1991 #ifdef ASTDEBUG
1992 printf (", char = 0%o", c);
1993 #endif
1994 }
1995 #ifdef ASTDEBUG
1996 printf ("\n");
1997 fflush (stdout);
1998 sleep (1);
1999 #endif
2000 if (! stop_input)
2001 queue_kbd_input ();
2002 if (c >= 0)
2003 {
2004 struct input_event e;
2005 e.kind = ascii_keystroke;
2006 XSETINT (e.code, c);
2007 e.frame_or_window = selected_frame;
2008 kbd_buffer_store_event (&e);
2009 }
2010 if (input_available_clear_time)
2011 EMACS_SET_SECS_USECS (*input_available_clear_time, 0, 0);
2012 errno = old_errno;
2013 }
2014
2015 /* Wait until there is something in kbd_buffer. */
2016
2017 void
2018 wait_for_kbd_input ()
2019 {
2020 extern int have_process_input, process_exited;
2021
2022 /* If already something, avoid doing system calls. */
2023 if (detect_input_pending ())
2024 {
2025 return;
2026 }
2027 /* Clear a flag, and tell ast routine above to set it. */
2028 SYS$CLREF (input_ef);
2029 waiting_for_ast = 1;
2030 /* Check for timing error: ast happened while we were doing that. */
2031 if (!detect_input_pending ())
2032 {
2033 /* No timing error: wait for flag to be set. */
2034 set_waiting_for_input (0);
2035 SYS$WFLOR (input_ef, input_eflist);
2036 clear_waiting_for_input (0);
2037 if (!detect_input_pending ())
2038 /* Check for subprocess input availability */
2039 {
2040 int dsp = have_process_input || process_exited;
2041
2042 SYS$CLREF (process_ef);
2043 if (have_process_input)
2044 process_command_input ();
2045 if (process_exited)
2046 process_exit ();
2047 if (dsp)
2048 {
2049 update_mode_lines++;
2050 prepare_menu_bars ();
2051 redisplay_preserve_echo_area ();
2052 }
2053 }
2054 }
2055 waiting_for_ast = 0;
2056 }
2057
2058 /* Get rid of any pending QIO, when we are about to suspend
2059 or when we want to throw away pending input.
2060 We wait for a positive sign that the AST routine has run
2061 and therefore there is no I/O request queued when we return.
2062 SYS$SETAST is used to avoid a timing error. */
2063
2064 void
2065 end_kbd_input ()
2066 {
2067 #ifdef ASTDEBUG
2068 printf ("At end_kbd_input.\n");
2069 fflush (stdout);
2070 sleep (1);
2071 #endif
2072 if (LIB$AST_IN_PROG ()) /* Don't wait if suspending from kbd_buffer_store_event! */
2073 {
2074 SYS$CANCEL (input_fd);
2075 return;
2076 }
2077
2078 SYS$SETAST (0);
2079 /* Clear a flag, and tell ast routine above to set it. */
2080 SYS$CLREF (input_ef);
2081 waiting_for_ast = 1;
2082 stop_input = 1;
2083 SYS$CANCEL (input_fd);
2084 SYS$SETAST (1);
2085 SYS$WAITFR (input_ef);
2086 waiting_for_ast = 0;
2087 }
2088
2089 /* Wait for either input available or time interval expiry. */
2090
2091 void
2092 input_wait_timeout (timeval)
2093 int timeval; /* Time to wait, in seconds */
2094 {
2095 int time [2];
2096 static int zero = 0;
2097 static int large = -10000000;
2098
2099 LIB$EMUL (&timeval, &large, &zero, time); /* Convert to VMS format */
2100
2101 /* If already something, avoid doing system calls. */
2102 if (detect_input_pending ())
2103 {
2104 return;
2105 }
2106 /* Clear a flag, and tell ast routine above to set it. */
2107 SYS$CLREF (input_ef);
2108 waiting_for_ast = 1;
2109 /* Check for timing error: ast happened while we were doing that. */
2110 if (!detect_input_pending ())
2111 {
2112 /* No timing error: wait for flag to be set. */
2113 SYS$CANTIM (1, 0);
2114 if (SYS$SETIMR (timer_ef, time, 0, 1) & 1) /* Set timer */
2115 SYS$WFLOR (timer_ef, timer_eflist); /* Wait for timer expiry or input */
2116 }
2117 waiting_for_ast = 0;
2118 }
2119
2120 /* The standard `sleep' routine works some other way
2121 and it stops working if you have ever quit out of it.
2122 This one continues to work. */
2123
2124 sys_sleep (timeval)
2125 int timeval;
2126 {
2127 int time [2];
2128 static int zero = 0;
2129 static int large = -10000000;
2130
2131 LIB$EMUL (&timeval, &large, &zero, time); /* Convert to VMS format */
2132
2133 SYS$CANTIM (1, 0);
2134 if (SYS$SETIMR (timer_ef, time, 0, 1) & 1) /* Set timer */
2135 SYS$WAITFR (timer_ef); /* Wait for timer expiry only */
2136 }
2137
2138 void
2139 init_sigio (fd)
2140 int fd;
2141 {
2142 request_sigio ();
2143 }
2144
2145 reset_sigio ()
2146 {
2147 unrequest_sigio ();
2148 }
2149
2150 void
2151 request_sigio ()
2152 {
2153 croak ("request sigio");
2154 }
2155
2156 void
2157 unrequest_sigio ()
2158 {
2159 croak ("unrequest sigio");
2160 }
2161
2162 #endif /* VMS */
2163 \f
2164 /* Note that VMS compiler won't accept defined (CANNOT_DUMP). */
2165 #ifndef CANNOT_DUMP
2166 #define NEED_STARTS
2167 #endif
2168
2169 #ifndef SYSTEM_MALLOC
2170 #ifndef NEED_STARTS
2171 #define NEED_STARTS
2172 #endif
2173 #endif
2174
2175 #ifdef NEED_STARTS
2176 /* Some systems that cannot dump also cannot implement these. */
2177
2178 /*
2179 * Return the address of the start of the text segment prior to
2180 * doing an unexec. After unexec the return value is undefined.
2181 * See crt0.c for further explanation and _start.
2182 *
2183 */
2184
2185 #ifndef HAVE_TEXT_START
2186 char *
2187 start_of_text ()
2188 {
2189 #ifdef TEXT_START
2190 return ((char *) TEXT_START);
2191 #else
2192 #ifdef GOULD
2193 extern csrt ();
2194 return ((char *) csrt);
2195 #else /* not GOULD */
2196 extern int _start ();
2197 return ((char *) _start);
2198 #endif /* GOULD */
2199 #endif /* TEXT_START */
2200 }
2201 #endif /* not HAVE_TEXT_START */
2202
2203 /*
2204 * Return the address of the start of the data segment prior to
2205 * doing an unexec. After unexec the return value is undefined.
2206 * See crt0.c for further information and definition of data_start.
2207 *
2208 * Apparently, on BSD systems this is etext at startup. On
2209 * USG systems (swapping) this is highly mmu dependent and
2210 * is also dependent on whether or not the program is running
2211 * with shared text. Generally there is a (possibly large)
2212 * gap between end of text and start of data with shared text.
2213 *
2214 * On Uniplus+ systems with shared text, data starts at a
2215 * fixed address. Each port (from a given oem) is generally
2216 * different, and the specific value of the start of data can
2217 * be obtained via the UniPlus+ specific "uvar" system call,
2218 * however the method outlined in crt0.c seems to be more portable.
2219 *
2220 * Probably what will have to happen when a USG unexec is available,
2221 * at least on UniPlus, is temacs will have to be made unshared so
2222 * that text and data are contiguous. Then once loadup is complete,
2223 * unexec will produce a shared executable where the data can be
2224 * at the normal shared text boundary and the startofdata variable
2225 * will be patched by unexec to the correct value.
2226 *
2227 */
2228
2229 char *
2230 start_of_data ()
2231 {
2232 #ifdef DATA_START
2233 return ((char *) DATA_START);
2234 #else
2235 #ifdef ORDINARY_LINK
2236 /*
2237 * This is a hack. Since we're not linking crt0.c or pre_crt0.c,
2238 * data_start isn't defined. We take the address of environ, which
2239 * is known to live at or near the start of the system crt0.c, and
2240 * we don't sweat the handful of bytes that might lose.
2241 */
2242 extern char **environ;
2243
2244 return ((char *) &environ);
2245 #else
2246 extern int data_start;
2247 return ((char *) &data_start);
2248 #endif /* ORDINARY_LINK */
2249 #endif /* DATA_START */
2250 }
2251 #endif /* NEED_STARTS (not CANNOT_DUMP or not SYSTEM_MALLOC) */
2252
2253 #ifndef CANNOT_DUMP
2254 /* Some systems that cannot dump also cannot implement these. */
2255
2256 /*
2257 * Return the address of the end of the text segment prior to
2258 * doing an unexec. After unexec the return value is undefined.
2259 */
2260
2261 char *
2262 end_of_text ()
2263 {
2264 #ifdef TEXT_END
2265 return ((char *) TEXT_END);
2266 #else
2267 extern int etext;
2268 return ((char *) &etext);
2269 #endif
2270 }
2271
2272 /*
2273 * Return the address of the end of the data segment prior to
2274 * doing an unexec. After unexec the return value is undefined.
2275 */
2276
2277 char *
2278 end_of_data ()
2279 {
2280 #ifdef DATA_END
2281 return ((char *) DATA_END);
2282 #else
2283 extern int edata;
2284 return ((char *) &edata);
2285 #endif
2286 }
2287
2288 #endif /* not CANNOT_DUMP */
2289 \f
2290 /* init_system_name sets up the string for the Lisp function
2291 system-name to return. */
2292
2293 #ifdef BSD4_1
2294 #include <whoami.h>
2295 #endif
2296
2297 extern Lisp_Object Vsystem_name;
2298
2299 #ifndef BSD4_1
2300 #ifndef VMS
2301 #ifdef HAVE_SOCKETS
2302 #include <sys/socket.h>
2303 #include <netdb.h>
2304 #endif /* HAVE_SOCKETS */
2305 #endif /* not VMS */
2306 #endif /* not BSD4_1 */
2307
2308 void
2309 init_system_name ()
2310 {
2311 #ifdef BSD4_1
2312 Vsystem_name = build_string (sysname);
2313 #else
2314 #ifdef VMS
2315 char *sp, *end;
2316 if ((sp = egetenv ("SYS$NODE")) == 0)
2317 Vsystem_name = build_string ("vax-vms");
2318 else if ((end = index (sp, ':')) == 0)
2319 Vsystem_name = build_string (sp);
2320 else
2321 Vsystem_name = make_string (sp, end - sp);
2322 #else
2323 #ifndef HAVE_GETHOSTNAME
2324 struct utsname uts;
2325 uname (&uts);
2326 Vsystem_name = build_string (uts.nodename);
2327 #else /* HAVE_GETHOSTNAME */
2328 unsigned int hostname_size = 256;
2329 char *hostname = (char *) alloca (hostname_size);
2330
2331 /* Try to get the host name; if the buffer is too short, try
2332 again. Apparently, the only indication gethostname gives of
2333 whether the buffer was large enough is the presence or absence
2334 of a '\0' in the string. Eech. */
2335 for (;;)
2336 {
2337 gethostname (hostname, hostname_size - 1);
2338 hostname[hostname_size - 1] = '\0';
2339
2340 /* Was the buffer large enough for the '\0'? */
2341 if (strlen (hostname) < hostname_size - 1)
2342 break;
2343
2344 hostname_size <<= 1;
2345 hostname = (char *) alloca (hostname_size);
2346 }
2347 #ifdef HAVE_SOCKETS
2348 /* Turn the hostname into the official, fully-qualified hostname.
2349 Don't do this if we're going to dump; this can confuse system
2350 libraries on some machines and make the dumped emacs core dump. */
2351 #ifndef CANNOT_DUMP
2352 if (initialized)
2353 #endif /* not CANNOT_DUMP */
2354 if (! index (hostname, '.'))
2355 {
2356 struct hostent *hp;
2357 int count;
2358 for (count = 0;; count++)
2359 {
2360 #ifdef TRY_AGAIN
2361 h_errno = 0;
2362 #endif
2363 hp = gethostbyname (hostname);
2364 #ifdef TRY_AGAIN
2365 if (! (hp == 0 && h_errno == TRY_AGAIN))
2366 #endif
2367 break;
2368 if (count >= 5)
2369 break;
2370 Fsleep_for (make_number (1), Qnil);
2371 }
2372 if (hp)
2373 {
2374 char *fqdn = (char *) hp->h_name;
2375 char *p;
2376
2377 if (!index (fqdn, '.'))
2378 {
2379 /* We still don't have a fully qualified domain name.
2380 Try to find one in the list of alternate names */
2381 char **alias = hp->h_aliases;
2382 while (*alias && !index (*alias, '.'))
2383 alias++;
2384 if (*alias)
2385 fqdn = *alias;
2386 }
2387 hostname = fqdn;
2388 #if 0
2389 /* Convert the host name to lower case. */
2390 /* Using ctype.h here would introduce a possible locale
2391 dependence that is probably wrong for hostnames. */
2392 p = hostname;
2393 while (*p)
2394 {
2395 if (*p >= 'A' && *p <= 'Z')
2396 *p += 'a' - 'A';
2397 p++;
2398 }
2399 #endif
2400 }
2401 }
2402 #endif /* HAVE_SOCKETS */
2403 /* We used to try using getdomainname here,
2404 but NIIBE Yutaka <gniibe@etl.go.jp> says that
2405 getdomainname gets the NIS/YP domain which often is not the same
2406 as in Internet domain name. */
2407 #if 0 /* Turned off because sysinfo is not really likely to return the
2408 correct Internet domain. */
2409 #if (HAVE_SYSINFO && defined (SI_SRPC_DOMAIN))
2410 if (! index (hostname, '.'))
2411 {
2412 /* The hostname is not fully qualified. Append the domain name. */
2413
2414 int hostlen = strlen (hostname);
2415 int domain_size = 256;
2416
2417 for (;;)
2418 {
2419 char *domain = (char *) alloca (domain_size + 1);
2420 char *fqdn = (char *) alloca (hostlen + 1 + domain_size + 1);
2421 int sys_domain_size = sysinfo (SI_SRPC_DOMAIN, domain, domain_size);
2422 if (sys_domain_size <= 0)
2423 break;
2424 if (domain_size < sys_domain_size)
2425 {
2426 domain_size = sys_domain_size;
2427 continue;
2428 }
2429 strcpy (fqdn, hostname);
2430 if (domain[0] == '.')
2431 strcpy (fqdn + hostlen, domain);
2432 else if (domain[0] != 0)
2433 {
2434 fqdn[hostlen] = '.';
2435 strcpy (fqdn + hostlen + 1, domain);
2436 }
2437 hostname = fqdn;
2438 break;
2439 }
2440 }
2441 #endif /* HAVE_SYSINFO && defined (SI_SRPC_DOMAIN) */
2442 #endif /* 0 */
2443 Vsystem_name = build_string (hostname);
2444 #endif /* HAVE_GETHOSTNAME */
2445 #endif /* VMS */
2446 #endif /* BSD4_1 */
2447 {
2448 unsigned char *p;
2449 for (p = XSTRING (Vsystem_name)->data; *p; p++)
2450 if (*p == ' ' || *p == '\t')
2451 *p = '-';
2452 }
2453 }
2454 \f
2455 #ifndef MSDOS
2456 #ifndef VMS
2457 #if !defined (HAVE_SELECT) || defined (BROKEN_SELECT_NON_X)
2458
2459 #include "sysselect.h"
2460 #undef select
2461
2462 #if defined (HAVE_X_WINDOWS) && !defined (HAVE_SELECT)
2463 /* Cause explanatory error message at compile time,
2464 since the select emulation is not good enough for X. */
2465 int *x = &x_windows_lose_if_no_select_system_call;
2466 #endif
2467
2468 /* Emulate as much as select as is possible under 4.1 and needed by Gnu Emacs
2469 * Only checks read descriptors.
2470 */
2471 /* How long to wait between checking fds in select */
2472 #define SELECT_PAUSE 1
2473 int select_alarmed;
2474
2475 /* For longjmp'ing back to read_input_waiting. */
2476
2477 jmp_buf read_alarm_throw;
2478
2479 /* Nonzero if the alarm signal should throw back to read_input_waiting.
2480 The read_socket_hook function sets this to 1 while it is waiting. */
2481
2482 int read_alarm_should_throw;
2483
2484 SIGTYPE
2485 select_alarm ()
2486 {
2487 select_alarmed = 1;
2488 #ifdef BSD4_1
2489 sigrelse (SIGALRM);
2490 #else /* not BSD4_1 */
2491 signal (SIGALRM, SIG_IGN);
2492 #endif /* not BSD4_1 */
2493 if (read_alarm_should_throw)
2494 longjmp (read_alarm_throw, 1);
2495 }
2496
2497 #ifndef WINDOWSNT
2498 /* Only rfds are checked. */
2499 int
2500 sys_select (nfds, rfds, wfds, efds, timeout)
2501 int nfds;
2502 SELECT_TYPE *rfds, *wfds, *efds;
2503 EMACS_TIME *timeout;
2504 {
2505 int ravail = 0, old_alarm;
2506 SELECT_TYPE orfds;
2507 int timeoutval;
2508 int *local_timeout;
2509 extern int proc_buffered_char[];
2510 #ifndef subprocesses
2511 int process_tick = 0, update_tick = 0;
2512 #else
2513 extern int process_tick, update_tick;
2514 #endif
2515 SIGTYPE (*old_trap) ();
2516 unsigned char buf;
2517
2518 #if defined (HAVE_SELECT) && defined (HAVE_X_WINDOWS)
2519 /* If we're using X, then the native select will work; we only need the
2520 emulation for non-X usage. */
2521 if (!NILP (Vwindow_system))
2522 return select (nfds, rfds, wfds, efds, timeout);
2523 #endif
2524 timeoutval = timeout ? EMACS_SECS (*timeout) : 100000;
2525 local_timeout = &timeoutval;
2526 FD_ZERO (&orfds);
2527 if (rfds)
2528 {
2529 orfds = *rfds;
2530 FD_ZERO (rfds);
2531 }
2532 if (wfds)
2533 FD_ZERO (wfds);
2534 if (efds)
2535 FD_ZERO (efds);
2536
2537 /* If we are looking only for the terminal, with no timeout,
2538 just read it and wait -- that's more efficient. */
2539 if (*local_timeout == 100000 && process_tick == update_tick
2540 && FD_ISSET (0, &orfds))
2541 {
2542 int fd;
2543 for (fd = 1; fd < nfds; ++fd)
2544 if (FD_ISSET (fd, &orfds))
2545 goto hardway;
2546 if (! detect_input_pending ())
2547 read_input_waiting ();
2548 FD_SET (0, rfds);
2549 return 1;
2550 }
2551
2552 hardway:
2553 /* Once a second, till the timer expires, check all the flagged read
2554 * descriptors to see if any input is available. If there is some then
2555 * set the corresponding bit in the return copy of rfds.
2556 */
2557 while (1)
2558 {
2559 register int to_check, fd;
2560
2561 if (rfds)
2562 {
2563 for (to_check = nfds, fd = 0; --to_check >= 0; fd++)
2564 {
2565 if (FD_ISSET (fd, &orfds))
2566 {
2567 int avail = 0, status = 0;
2568
2569 if (fd == 0)
2570 avail = detect_input_pending (); /* Special keyboard handler */
2571 else
2572 {
2573 #ifdef FIONREAD
2574 status = ioctl (fd, FIONREAD, &avail);
2575 #else /* no FIONREAD */
2576 /* Hoping it will return -1 if nothing available
2577 or 0 if all 0 chars requested are read. */
2578 if (proc_buffered_char[fd] >= 0)
2579 avail = 1;
2580 else
2581 {
2582 avail = read (fd, &buf, 1);
2583 if (avail > 0)
2584 proc_buffered_char[fd] = buf;
2585 }
2586 #endif /* no FIONREAD */
2587 }
2588 if (status >= 0 && avail > 0)
2589 {
2590 FD_SET (fd, rfds);
2591 ravail++;
2592 }
2593 }
2594 }
2595 }
2596 if (*local_timeout == 0 || ravail != 0 || process_tick != update_tick)
2597 break;
2598 old_alarm = alarm (0);
2599 old_trap = signal (SIGALRM, select_alarm);
2600 select_alarmed = 0;
2601 alarm (SELECT_PAUSE);
2602 /* Wait for a SIGALRM (or maybe a SIGTINT) */
2603 while (select_alarmed == 0 && *local_timeout != 0
2604 && process_tick == update_tick)
2605 {
2606 /* If we are interested in terminal input,
2607 wait by reading the terminal.
2608 That makes instant wakeup for terminal input at least. */
2609 if (FD_ISSET (0, &orfds))
2610 {
2611 read_input_waiting ();
2612 if (detect_input_pending ())
2613 select_alarmed = 1;
2614 }
2615 else
2616 pause ();
2617 }
2618 (*local_timeout) -= SELECT_PAUSE;
2619 /* Reset the old alarm if there was one */
2620 alarm (0);
2621 signal (SIGALRM, old_trap);
2622 if (old_alarm != 0)
2623 {
2624 /* Reset or forge an interrupt for the original handler. */
2625 old_alarm -= SELECT_PAUSE;
2626 if (old_alarm <= 0)
2627 kill (getpid (), SIGALRM); /* Fake an alarm with the orig' handler */
2628 else
2629 alarm (old_alarm);
2630 }
2631 if (*local_timeout == 0) /* Stop on timer being cleared */
2632 break;
2633 }
2634 return ravail;
2635 }
2636 #endif /* not WINDOWSNT */
2637
2638 /* Read keyboard input into the standard buffer,
2639 waiting for at least one character. */
2640
2641 /* Make all keyboard buffers much bigger when using a window system. */
2642 #ifdef HAVE_WINDOW_SYSTEM
2643 #define BUFFER_SIZE_FACTOR 16
2644 #else
2645 #define BUFFER_SIZE_FACTOR 1
2646 #endif
2647
2648 void
2649 read_input_waiting ()
2650 {
2651 struct input_event e;
2652 int nread, i;
2653 extern int quit_char;
2654
2655 if (read_socket_hook)
2656 {
2657 struct input_event buf[256];
2658
2659 read_alarm_should_throw = 0;
2660 if (! setjmp (read_alarm_throw))
2661 nread = (*read_socket_hook) (0, buf, 256, 1);
2662 else
2663 nread = -1;
2664
2665 /* Scan the chars for C-g and store them in kbd_buffer. */
2666 for (i = 0; i < nread; i++)
2667 {
2668 kbd_buffer_store_event (&buf[i]);
2669 /* Don't look at input that follows a C-g too closely.
2670 This reduces lossage due to autorepeat on C-g. */
2671 if (buf[i].kind == ascii_keystroke
2672 && buf[i].code == quit_char)
2673 break;
2674 }
2675 }
2676 else
2677 {
2678 char buf[3];
2679 nread = read (fileno (stdin), buf, 1);
2680
2681 /* Scan the chars for C-g and store them in kbd_buffer. */
2682 e.kind = ascii_keystroke;
2683 e.frame_or_window = selected_frame;
2684 e.modifiers = 0;
2685 for (i = 0; i < nread; i++)
2686 {
2687 /* Convert chars > 0177 to meta events if desired.
2688 We do this under the same conditions that read_avail_input does. */
2689 if (read_socket_hook == 0)
2690 {
2691 /* If the user says she has a meta key, then believe her. */
2692 if (meta_key == 1 && (buf[i] & 0x80))
2693 e.modifiers = meta_modifier;
2694 if (meta_key != 2)
2695 buf[i] &= ~0x80;
2696 }
2697
2698 XSETINT (e.code, buf[i]);
2699 kbd_buffer_store_event (&e);
2700 /* Don't look at input that follows a C-g too closely.
2701 This reduces lossage due to autorepeat on C-g. */
2702 if (buf[i] == quit_char)
2703 break;
2704 }
2705 }
2706 }
2707
2708 #endif /* not HAVE_SELECT */
2709 #endif /* not VMS */
2710 #endif /* not MSDOS */
2711 \f
2712 #ifdef BSD4_1
2713 /*
2714 * Partially emulate 4.2 open call.
2715 * open is defined as this in 4.1.
2716 *
2717 * - added by Michael Bloom @ Citicorp/TTI
2718 *
2719 */
2720
2721 int
2722 sys_open (path, oflag, mode)
2723 char *path;
2724 int oflag, mode;
2725 {
2726 if (oflag & O_CREAT)
2727 return creat (path, mode);
2728 else
2729 return open (path, oflag);
2730 }
2731
2732 void
2733 init_sigio (fd)
2734 int fd;
2735 {
2736 if (noninteractive)
2737 return;
2738 lmode = LINTRUP | lmode;
2739 ioctl (fd, TIOCLSET, &lmode);
2740 }
2741
2742 void
2743 reset_sigio ()
2744 {
2745 if (noninteractive)
2746 return;
2747 lmode = ~LINTRUP & lmode;
2748 ioctl (0, TIOCLSET, &lmode);
2749 }
2750
2751 void
2752 request_sigio ()
2753 {
2754 sigrelse (SIGTINT);
2755
2756 interrupts_deferred = 0;
2757 }
2758
2759 void
2760 unrequest_sigio ()
2761 {
2762 sighold (SIGTINT);
2763
2764 interrupts_deferred = 1;
2765 }
2766
2767 /* still inside #ifdef BSD4_1 */
2768 #ifdef subprocesses
2769
2770 int sigheld; /* Mask of held signals */
2771
2772 void
2773 sigholdx (signum)
2774 int signum;
2775 {
2776 sigheld |= sigbit (signum);
2777 sighold (signum);
2778 }
2779
2780 void
2781 sigisheld (signum)
2782 int signum;
2783 {
2784 sigheld |= sigbit (signum);
2785 }
2786
2787 void
2788 sigunhold (signum)
2789 int signum;
2790 {
2791 sigheld &= ~sigbit (signum);
2792 sigrelse (signum);
2793 }
2794
2795 void
2796 sigfree () /* Free all held signals */
2797 {
2798 int i;
2799 for (i = 0; i < NSIG; i++)
2800 if (sigheld & sigbit (i))
2801 sigrelse (i);
2802 sigheld = 0;
2803 }
2804
2805 int
2806 sigbit (i)
2807 {
2808 return 1 << (i - 1);
2809 }
2810 #endif /* subprocesses */
2811 #endif /* BSD4_1 */
2812 \f
2813 /* POSIX signals support - DJB */
2814 /* Anyone with POSIX signals should have ANSI C declarations */
2815
2816 #ifdef POSIX_SIGNALS
2817
2818 sigset_t empty_mask, full_mask;
2819
2820 void
2821 init_signals ()
2822 {
2823 sigemptyset (&empty_mask);
2824 sigfillset (&full_mask);
2825 }
2826
2827 signal_handler_t
2828 sys_signal (int signal_number, signal_handler_t action)
2829 {
2830 struct sigaction new_action, old_action;
2831 sigemptyset (&new_action.sa_mask);
2832 new_action.sa_handler = action;
2833 #ifdef SA_RESTART
2834 /* Emacs mostly works better with restartable system services. If this
2835 * flag exists, we probably want to turn it on here.
2836 */
2837 new_action.sa_flags = SA_RESTART;
2838 #else
2839 new_action.sa_flags = 0;
2840 #endif
2841 sigaction (signal_number, &new_action, &old_action);
2842 return (old_action.sa_handler);
2843 }
2844
2845 #ifndef __GNUC__
2846 /* If we're compiling with GCC, we don't need this function, since it
2847 can be written as a macro. */
2848 sigset_t
2849 sys_sigmask (int sig)
2850 {
2851 sigset_t mask;
2852 sigemptyset (&mask);
2853 sigaddset (&mask, sig);
2854 return mask;
2855 }
2856 #endif
2857
2858 /* I'd like to have these guys return pointers to the mask storage in here,
2859 but there'd be trouble if the code was saving multiple masks. I'll be
2860 safe and pass the structure. It normally won't be more than 2 bytes
2861 anyhow. - DJB */
2862
2863 sigset_t
2864 sys_sigblock (sigset_t new_mask)
2865 {
2866 sigset_t old_mask;
2867 sigprocmask (SIG_BLOCK, &new_mask, &old_mask);
2868 return (old_mask);
2869 }
2870
2871 sigset_t
2872 sys_sigunblock (sigset_t new_mask)
2873 {
2874 sigset_t old_mask;
2875 sigprocmask (SIG_UNBLOCK, &new_mask, &old_mask);
2876 return (old_mask);
2877 }
2878
2879 sigset_t
2880 sys_sigsetmask (sigset_t new_mask)
2881 {
2882 sigset_t old_mask;
2883 sigprocmask (SIG_SETMASK, &new_mask, &old_mask);
2884 return (old_mask);
2885 }
2886
2887 #endif /* POSIX_SIGNALS */
2888 \f
2889 #ifndef HAVE_RANDOM
2890 #ifdef random
2891 #define HAVE_RANDOM
2892 #endif
2893 #endif
2894
2895 /* Figure out how many bits the system's random number generator uses.
2896 `random' and `lrand48' are assumed to return 31 usable bits.
2897 BSD `rand' returns a 31 bit value but the low order bits are unusable;
2898 so we'll shift it and treat it like the 15-bit USG `rand'. */
2899
2900 #ifndef RAND_BITS
2901 # ifdef HAVE_RANDOM
2902 # define RAND_BITS 31
2903 # else /* !HAVE_RANDOM */
2904 # ifdef HAVE_LRAND48
2905 # define RAND_BITS 31
2906 # define random lrand48
2907 # else /* !HAVE_LRAND48 */
2908 # define RAND_BITS 15
2909 # if RAND_MAX == 32767
2910 # define random rand
2911 # else /* RAND_MAX != 32767 */
2912 # if RAND_MAX == 2147483647
2913 # define random() (rand () >> 16)
2914 # else /* RAND_MAX != 2147483647 */
2915 # ifdef USG
2916 # define random rand
2917 # else
2918 # define random() (rand () >> 16)
2919 # endif /* !USG */
2920 # endif /* RAND_MAX != 2147483647 */
2921 # endif /* RAND_MAX != 32767 */
2922 # endif /* !HAVE_LRAND48 */
2923 # endif /* !HAVE_RANDOM */
2924 #endif /* !RAND_BITS */
2925
2926 void
2927 seed_random (arg)
2928 long arg;
2929 {
2930 #ifdef HAVE_RANDOM
2931 srandom ((unsigned int)arg);
2932 #else
2933 # ifdef HAVE_LRAND48
2934 srand48 (arg);
2935 # else
2936 srand ((unsigned int)arg);
2937 # endif
2938 #endif
2939 }
2940
2941 /*
2942 * Build a full Emacs-sized word out of whatever we've got.
2943 * This suffices even for a 64-bit architecture with a 15-bit rand.
2944 */
2945 long
2946 get_random ()
2947 {
2948 long val = random ();
2949 #if VALBITS > RAND_BITS
2950 val = (val << RAND_BITS) ^ random ();
2951 #if VALBITS > 2*RAND_BITS
2952 val = (val << RAND_BITS) ^ random ();
2953 #if VALBITS > 3*RAND_BITS
2954 val = (val << RAND_BITS) ^ random ();
2955 #if VALBITS > 4*RAND_BITS
2956 val = (val << RAND_BITS) ^ random ();
2957 #endif /* need at least 5 */
2958 #endif /* need at least 4 */
2959 #endif /* need at least 3 */
2960 #endif /* need at least 2 */
2961 return val & ((1L << VALBITS) - 1);
2962 }
2963 \f
2964 #ifdef WRONG_NAME_INSQUE
2965
2966 insque (q,p)
2967 caddr_t q,p;
2968 {
2969 _insque (q,p);
2970 }
2971
2972 #endif
2973 \f
2974 #ifdef VMS
2975
2976 #ifdef getenv
2977 /* If any place else asks for the TERM variable,
2978 allow it to be overridden with the EMACS_TERM variable
2979 before attempting to translate the logical name TERM. As a last
2980 resort, ask for VAX C's special idea of the TERM variable. */
2981 #undef getenv
2982 char *
2983 sys_getenv (name)
2984 char *name;
2985 {
2986 register char *val;
2987 static char buf[256];
2988 static struct dsc$descriptor_s equiv
2989 = {sizeof (buf), DSC$K_DTYPE_T, DSC$K_CLASS_S, buf};
2990 static struct dsc$descriptor_s d_name
2991 = {0, DSC$K_DTYPE_T, DSC$K_CLASS_S, 0};
2992 short eqlen;
2993
2994 if (!strcmp (name, "TERM"))
2995 {
2996 val = (char *) getenv ("EMACS_TERM");
2997 if (val)
2998 return val;
2999 }
3000
3001 d_name.dsc$w_length = strlen (name);
3002 d_name.dsc$a_pointer = name;
3003 if (LIB$SYS_TRNLOG (&d_name, &eqlen, &equiv) == 1)
3004 {
3005 char *str = (char *) xmalloc (eqlen + 1);
3006 bcopy (buf, str, eqlen);
3007 str[eqlen] = '\0';
3008 /* This is a storage leak, but a pain to fix. With luck,
3009 no one will ever notice. */
3010 return str;
3011 }
3012 return (char *) getenv (name);
3013 }
3014 #endif /* getenv */
3015
3016 #ifdef abort
3017 /* Since VMS doesn't believe in core dumps, the only way to debug this beast is
3018 to force a call on the debugger from within the image. */
3019 #undef abort
3020 sys_abort ()
3021 {
3022 reset_sys_modes ();
3023 LIB$SIGNAL (SS$_DEBUG);
3024 }
3025 #endif /* abort */
3026 #endif /* VMS */
3027 \f
3028 #ifdef VMS
3029 #ifdef LINK_CRTL_SHARE
3030 #ifdef SHARABLE_LIB_BUG
3031 /* Variables declared noshare and initialized in sharable libraries
3032 cannot be shared. The VMS linker incorrectly forces you to use a private
3033 version which is uninitialized... If not for this "feature", we
3034 could use the C library definition of sys_nerr and sys_errlist. */
3035 int sys_nerr = 35;
3036 char *sys_errlist[] =
3037 {
3038 "error 0",
3039 "not owner",
3040 "no such file or directory",
3041 "no such process",
3042 "interrupted system call",
3043 "i/o error",
3044 "no such device or address",
3045 "argument list too long",
3046 "exec format error",
3047 "bad file number",
3048 "no child process",
3049 "no more processes",
3050 "not enough memory",
3051 "permission denied",
3052 "bad address",
3053 "block device required",
3054 "mount devices busy",
3055 "file exists",
3056 "cross-device link",
3057 "no such device",
3058 "not a directory",
3059 "is a directory",
3060 "invalid argument",
3061 "file table overflow",
3062 "too many open files",
3063 "not a typewriter",
3064 "text file busy",
3065 "file too big",
3066 "no space left on device",
3067 "illegal seek",
3068 "read-only file system",
3069 "too many links",
3070 "broken pipe",
3071 "math argument",
3072 "result too large",
3073 "I/O stream empty",
3074 "vax/vms specific error code nontranslatable error"
3075 };
3076 #endif /* SHARABLE_LIB_BUG */
3077 #endif /* LINK_CRTL_SHARE */
3078 #endif /* VMS */
3079
3080 #ifndef HAVE_STRERROR
3081 #ifndef WINDOWSNT
3082 char *
3083 strerror (errnum)
3084 int errnum;
3085 {
3086 extern char *sys_errlist[];
3087 extern int sys_nerr;
3088
3089 if (errnum >= 0 && errnum < sys_nerr)
3090 return sys_errlist[errnum];
3091 return (char *) "Unknown error";
3092 }
3093 #endif /* not WINDOWSNT */
3094 #endif /* ! HAVE_STRERROR */
3095 \f
3096 #ifdef INTERRUPTIBLE_OPEN
3097
3098 int
3099 /* VARARGS 2 */
3100 sys_open (path, oflag, mode)
3101 char *path;
3102 int oflag, mode;
3103 {
3104 register int rtnval;
3105
3106 while ((rtnval = open (path, oflag, mode)) == -1
3107 && (errno == EINTR));
3108 return (rtnval);
3109 }
3110
3111 #endif /* INTERRUPTIBLE_OPEN */
3112
3113 #ifdef INTERRUPTIBLE_CLOSE
3114
3115 int
3116 sys_close (fd)
3117 int fd;
3118 {
3119 int did_retry = 0;
3120 register int rtnval;
3121
3122 while ((rtnval = close (fd)) == -1
3123 && (errno == EINTR))
3124 did_retry = 1;
3125
3126 /* If close is interrupted SunOS 4.1 may or may not have closed the
3127 file descriptor. If it did the second close will fail with
3128 errno = EBADF. That means we have succeeded. */
3129 if (rtnval == -1 && did_retry && errno == EBADF)
3130 return 0;
3131
3132 return rtnval;
3133 }
3134
3135 #endif /* INTERRUPTIBLE_CLOSE */
3136
3137 #ifdef INTERRUPTIBLE_IO
3138
3139 int
3140 sys_read (fildes, buf, nbyte)
3141 int fildes;
3142 char *buf;
3143 unsigned int nbyte;
3144 {
3145 register int rtnval;
3146
3147 while ((rtnval = read (fildes, buf, nbyte)) == -1
3148 && (errno == EINTR));
3149 return (rtnval);
3150 }
3151
3152 int
3153 sys_write (fildes, buf, nbyte)
3154 int fildes;
3155 char *buf;
3156 unsigned int nbyte;
3157 {
3158 register int rtnval, bytes_written;
3159
3160 bytes_written = 0;
3161
3162 while (nbyte > 0)
3163 {
3164 rtnval = write (fildes, buf, nbyte);
3165
3166 if (rtnval == -1)
3167 {
3168 if (errno == EINTR)
3169 continue;
3170 else
3171 return (bytes_written ? bytes_written : -1);
3172 }
3173
3174 buf += rtnval;
3175 nbyte -= rtnval;
3176 bytes_written += rtnval;
3177 }
3178 return (bytes_written);
3179 }
3180
3181 #endif /* INTERRUPTIBLE_IO */
3182 \f
3183 #ifndef HAVE_VFORK
3184 #ifndef WINDOWSNT
3185 /*
3186 * Substitute fork for vfork on USG flavors.
3187 */
3188
3189 VFORK_RETURN_TYPE
3190 vfork ()
3191 {
3192 return (fork ());
3193 }
3194 #endif /* not WINDOWSNT */
3195 #endif /* not HAVE_VFORK */
3196 \f
3197 #ifdef USG
3198 /*
3199 * All of the following are for USG.
3200 *
3201 * On USG systems the system calls are INTERRUPTIBLE by signals
3202 * that the user program has elected to catch. Thus the system call
3203 * must be retried in these cases. To handle this without massive
3204 * changes in the source code, we remap the standard system call names
3205 * to names for our own functions in sysdep.c that do the system call
3206 * with retries. Actually, for portability reasons, it is good
3207 * programming practice, as this example shows, to limit all actual
3208 * system calls to a single occurrence in the source. Sure, this
3209 * adds an extra level of function call overhead but it is almost
3210 * always negligible. Fred Fish, Unisoft Systems Inc.
3211 */
3212
3213 #ifndef HAVE_SYS_SIGLIST
3214 char *sys_siglist[NSIG + 1] =
3215 {
3216 #ifdef AIX
3217 /* AIX has changed the signals a bit */
3218 "bogus signal", /* 0 */
3219 "hangup", /* 1 SIGHUP */
3220 "interrupt", /* 2 SIGINT */
3221 "quit", /* 3 SIGQUIT */
3222 "illegal instruction", /* 4 SIGILL */
3223 "trace trap", /* 5 SIGTRAP */
3224 "IOT instruction", /* 6 SIGIOT */
3225 "crash likely", /* 7 SIGDANGER */
3226 "floating point exception", /* 8 SIGFPE */
3227 "kill", /* 9 SIGKILL */
3228 "bus error", /* 10 SIGBUS */
3229 "segmentation violation", /* 11 SIGSEGV */
3230 "bad argument to system call", /* 12 SIGSYS */
3231 "write on a pipe with no one to read it", /* 13 SIGPIPE */
3232 "alarm clock", /* 14 SIGALRM */
3233 "software termination signum", /* 15 SIGTERM */
3234 "user defined signal 1", /* 16 SIGUSR1 */
3235 "user defined signal 2", /* 17 SIGUSR2 */
3236 "death of a child", /* 18 SIGCLD */
3237 "power-fail restart", /* 19 SIGPWR */
3238 "bogus signal", /* 20 */
3239 "bogus signal", /* 21 */
3240 "bogus signal", /* 22 */
3241 "bogus signal", /* 23 */
3242 "bogus signal", /* 24 */
3243 "LAN I/O interrupt", /* 25 SIGAIO */
3244 "PTY I/O interrupt", /* 26 SIGPTY */
3245 "I/O intervention required", /* 27 SIGIOINT */
3246 #ifdef AIXHFT
3247 "HFT grant", /* 28 SIGGRANT */
3248 "HFT retract", /* 29 SIGRETRACT */
3249 "HFT sound done", /* 30 SIGSOUND */
3250 "HFT input ready", /* 31 SIGMSG */
3251 #endif
3252 #else /* not AIX */
3253 "bogus signal", /* 0 */
3254 "hangup", /* 1 SIGHUP */
3255 "interrupt", /* 2 SIGINT */
3256 "quit", /* 3 SIGQUIT */
3257 "illegal instruction", /* 4 SIGILL */
3258 "trace trap", /* 5 SIGTRAP */
3259 "IOT instruction", /* 6 SIGIOT */
3260 "EMT instruction", /* 7 SIGEMT */
3261 "floating point exception", /* 8 SIGFPE */
3262 "kill", /* 9 SIGKILL */
3263 "bus error", /* 10 SIGBUS */
3264 "segmentation violation", /* 11 SIGSEGV */
3265 "bad argument to system call", /* 12 SIGSYS */
3266 "write on a pipe with no one to read it", /* 13 SIGPIPE */
3267 "alarm clock", /* 14 SIGALRM */
3268 "software termination signum", /* 15 SIGTERM */
3269 "user defined signal 1", /* 16 SIGUSR1 */
3270 "user defined signal 2", /* 17 SIGUSR2 */
3271 "death of a child", /* 18 SIGCLD */
3272 "power-fail restart", /* 19 SIGPWR */
3273 #ifdef sun
3274 "window size change", /* 20 SIGWINCH */
3275 "urgent socket condition", /* 21 SIGURG */
3276 "pollable event occurred", /* 22 SIGPOLL */
3277 "stop (cannot be caught or ignored)", /* 23 SIGSTOP */
3278 "user stop requested from tty", /* 24 SIGTSTP */
3279 "stopped process has been continued", /* 25 SIGCONT */
3280 "background tty read attempted", /* 26 SIGTTIN */
3281 "background tty write attempted", /* 27 SIGTTOU */
3282 "virtual timer expired", /* 28 SIGVTALRM */
3283 "profiling timer expired", /* 29 SIGPROF */
3284 "exceeded cpu limit", /* 30 SIGXCPU */
3285 "exceeded file size limit", /* 31 SIGXFSZ */
3286 "process's lwps are blocked", /* 32 SIGWAITING */
3287 "special signal used by thread library", /* 33 SIGLWP */
3288 #ifdef SIGFREEZE
3289 "Special Signal Used By CPR", /* 34 SIGFREEZE */
3290 #endif
3291 #ifdef SIGTHAW
3292 "Special Signal Used By CPR", /* 35 SIGTHAW */
3293 #endif
3294 #endif /* sun */
3295 #endif /* not AIX */
3296 0
3297 };
3298 #endif /* HAVE_SYS_SIGLIST */
3299
3300 /*
3301 * Warning, this function may not duplicate 4.2 action properly
3302 * under error conditions.
3303 */
3304
3305 #ifndef MAXPATHLEN
3306 /* In 4.1, param.h fails to define this. */
3307 #define MAXPATHLEN 1024
3308 #endif
3309
3310 #ifndef HAVE_GETWD
3311
3312 char *
3313 getwd (pathname)
3314 char *pathname;
3315 {
3316 char *npath, *spath;
3317 extern char *getcwd ();
3318
3319 BLOCK_INPUT; /* getcwd uses malloc */
3320 spath = npath = getcwd ((char *) 0, MAXPATHLEN);
3321 if (spath == 0)
3322 return spath;
3323 /* On Altos 3068, getcwd can return @hostname/dir, so discard
3324 up to first slash. Should be harmless on other systems. */
3325 while (*npath && *npath != '/')
3326 npath++;
3327 strcpy (pathname, npath);
3328 free (spath); /* getcwd uses malloc */
3329 UNBLOCK_INPUT;
3330 return pathname;
3331 }
3332
3333 #endif /* HAVE_GETWD */
3334
3335 /*
3336 * Emulate rename using unlink/link. Note that this is
3337 * only partially correct. Also, doesn't enforce restriction
3338 * that files be of same type (regular->regular, dir->dir, etc).
3339 */
3340
3341 #ifndef HAVE_RENAME
3342
3343 rename (from, to)
3344 const char *from;
3345 const char *to;
3346 {
3347 if (access (from, 0) == 0)
3348 {
3349 unlink (to);
3350 if (link (from, to) == 0)
3351 if (unlink (from) == 0)
3352 return (0);
3353 }
3354 return (-1);
3355 }
3356
3357 #endif
3358
3359
3360 #ifdef HPUX
3361 #ifndef HAVE_PERROR
3362
3363 /* HPUX curses library references perror, but as far as we know
3364 it won't be called. Anyway this definition will do for now. */
3365
3366 perror ()
3367 {
3368 }
3369
3370 #endif /* not HAVE_PERROR */
3371 #endif /* HPUX */
3372
3373 #ifndef HAVE_DUP2
3374
3375 /*
3376 * Emulate BSD dup2. First close newd if it already exists.
3377 * Then, attempt to dup oldd. If not successful, call dup2 recursively
3378 * until we are, then close the unsuccessful ones.
3379 */
3380
3381 dup2 (oldd, newd)
3382 int oldd;
3383 int newd;
3384 {
3385 register int fd, ret;
3386
3387 sys_close (newd);
3388
3389 #ifdef F_DUPFD
3390 fd = fcntl (oldd, F_DUPFD, newd);
3391 if (fd != newd)
3392 error ("can't dup2 (%i,%i) : %s", oldd, newd, strerror (errno));
3393 #else
3394 fd = dup (old);
3395 if (fd == -1)
3396 return -1;
3397 if (fd == new)
3398 return new;
3399 ret = dup2 (old,new);
3400 sys_close (fd);
3401 return ret;
3402 #endif
3403 }
3404
3405 #endif /* not HAVE_DUP2 */
3406
3407 /*
3408 * Gettimeofday. Simulate as much as possible. Only accurate
3409 * to nearest second. Emacs doesn't use tzp so ignore it for now.
3410 * Only needed when subprocesses are defined.
3411 */
3412
3413 #ifdef subprocesses
3414 #ifndef VMS
3415 #ifndef HAVE_GETTIMEOFDAY
3416 #ifdef HAVE_TIMEVAL
3417
3418 /* ARGSUSED */
3419 int
3420 gettimeofday (tp, tzp)
3421 struct timeval *tp;
3422 struct timezone *tzp;
3423 {
3424 extern long time ();
3425
3426 tp->tv_sec = time ((long *)0);
3427 tp->tv_usec = 0;
3428 if (tzp != 0)
3429 tzp->tz_minuteswest = -1;
3430 return 0;
3431 }
3432
3433 #endif
3434 #endif
3435 #endif
3436 #endif /* subprocess && !HAVE_GETTIMEOFDAY && HAVE_TIMEVAL && !VMS */
3437
3438 /*
3439 * This function will go away as soon as all the stubs fixed. (fnf)
3440 */
3441
3442 void
3443 croak (badfunc)
3444 char *badfunc;
3445 {
3446 printf ("%s not yet implemented\r\n", badfunc);
3447 reset_sys_modes ();
3448 exit (1);
3449 }
3450
3451 #endif /* USG */
3452 \f
3453 #ifdef DGUX
3454
3455 char *sys_siglist[NSIG + 1] =
3456 {
3457 "null signal", /* 0 SIGNULL */
3458 "hangup", /* 1 SIGHUP */
3459 "interrupt", /* 2 SIGINT */
3460 "quit", /* 3 SIGQUIT */
3461 "illegal instruction", /* 4 SIGILL */
3462 "trace trap", /* 5 SIGTRAP */
3463 "abort termination", /* 6 SIGABRT */
3464 "SIGEMT", /* 7 SIGEMT */
3465 "floating point exception", /* 8 SIGFPE */
3466 "kill", /* 9 SIGKILL */
3467 "bus error", /* 10 SIGBUS */
3468 "segmentation violation", /* 11 SIGSEGV */
3469 "bad argument to system call", /* 12 SIGSYS */
3470 "write on a pipe with no reader", /* 13 SIGPIPE */
3471 "alarm clock", /* 14 SIGALRM */
3472 "software termination signal", /* 15 SIGTERM */
3473 "user defined signal 1", /* 16 SIGUSR1 */
3474 "user defined signal 2", /* 17 SIGUSR2 */
3475 "child stopped or terminated", /* 18 SIGCLD */
3476 "power-fail restart", /* 19 SIGPWR */
3477 "window size changed", /* 20 SIGWINCH */
3478 "undefined", /* 21 */
3479 "pollable event occurred", /* 22 SIGPOLL */
3480 "sendable stop signal not from tty", /* 23 SIGSTOP */
3481 "stop signal from tty", /* 24 SIGSTP */
3482 "continue a stopped process", /* 25 SIGCONT */
3483 "attempted background tty read", /* 26 SIGTTIN */
3484 "attempted background tty write", /* 27 SIGTTOU */
3485 "undefined", /* 28 */
3486 "undefined", /* 29 */
3487 "undefined", /* 30 */
3488 "undefined", /* 31 */
3489 "undefined", /* 32 */
3490 "socket (TCP/IP) urgent data arrival", /* 33 SIGURG */
3491 "I/O is possible", /* 34 SIGIO */
3492 "exceeded cpu time limit", /* 35 SIGXCPU */
3493 "exceeded file size limit", /* 36 SIGXFSZ */
3494 "virtual time alarm", /* 37 SIGVTALRM */
3495 "profiling time alarm", /* 38 SIGPROF */
3496 "undefined", /* 39 */
3497 "file record locks revoked", /* 40 SIGLOST */
3498 "undefined", /* 41 */
3499 "undefined", /* 42 */
3500 "undefined", /* 43 */
3501 "undefined", /* 44 */
3502 "undefined", /* 45 */
3503 "undefined", /* 46 */
3504 "undefined", /* 47 */
3505 "undefined", /* 48 */
3506 "undefined", /* 49 */
3507 "undefined", /* 50 */
3508 "undefined", /* 51 */
3509 "undefined", /* 52 */
3510 "undefined", /* 53 */
3511 "undefined", /* 54 */
3512 "undefined", /* 55 */
3513 "undefined", /* 56 */
3514 "undefined", /* 57 */
3515 "undefined", /* 58 */
3516 "undefined", /* 59 */
3517 "undefined", /* 60 */
3518 "undefined", /* 61 */
3519 "undefined", /* 62 */
3520 "undefined", /* 63 */
3521 "notification message in mess. queue", /* 64 SIGDGNOTIFY */
3522 0
3523 };
3524
3525 #endif /* DGUX */
3526 \f
3527 /* Directory routines for systems that don't have them. */
3528
3529 #ifdef SYSV_SYSTEM_DIR
3530
3531 #include <dirent.h>
3532
3533 #if defined (BROKEN_CLOSEDIR) || !defined (HAVE_CLOSEDIR)
3534
3535 int
3536 closedir (dirp)
3537 register DIR *dirp; /* stream from opendir */
3538 {
3539 int rtnval;
3540
3541 rtnval = sys_close (dirp->dd_fd);
3542
3543 /* Some systems (like Solaris) allocate the buffer and the DIR all
3544 in one block. Why in the world are we freeing this ourselves
3545 anyway? */
3546 #if ! (defined (sun) && defined (USG5_4))
3547 xfree ((char *) dirp->dd_buf); /* directory block defined in <dirent.h> */
3548 #endif
3549 xfree ((char *) dirp);
3550
3551 return rtnval;
3552 }
3553 #endif /* BROKEN_CLOSEDIR or not HAVE_CLOSEDIR */
3554 #endif /* SYSV_SYSTEM_DIR */
3555
3556 #ifdef NONSYSTEM_DIR_LIBRARY
3557
3558 DIR *
3559 opendir (filename)
3560 char *filename; /* name of directory */
3561 {
3562 register DIR *dirp; /* -> malloc'ed storage */
3563 register int fd; /* file descriptor for read */
3564 struct stat sbuf; /* result of fstat */
3565
3566 fd = sys_open (filename, 0);
3567 if (fd < 0)
3568 return 0;
3569
3570 BLOCK_INPUT;
3571 if (fstat (fd, &sbuf) < 0
3572 || (sbuf.st_mode & S_IFMT) != S_IFDIR
3573 || (dirp = (DIR *) malloc (sizeof (DIR))) == 0)
3574 {
3575 sys_close (fd);
3576 UNBLOCK_INPUT;
3577 return 0; /* bad luck today */
3578 }
3579 UNBLOCK_INPUT;
3580
3581 dirp->dd_fd = fd;
3582 dirp->dd_loc = dirp->dd_size = 0; /* refill needed */
3583
3584 return dirp;
3585 }
3586
3587 void
3588 closedir (dirp)
3589 register DIR *dirp; /* stream from opendir */
3590 {
3591 sys_close (dirp->dd_fd);
3592 xfree ((char *) dirp);
3593 }
3594
3595
3596 #ifndef VMS
3597 #define DIRSIZ 14
3598 struct olddir
3599 {
3600 ino_t od_ino; /* inode */
3601 char od_name[DIRSIZ]; /* filename */
3602 };
3603 #endif /* not VMS */
3604
3605 struct direct dir_static; /* simulated directory contents */
3606
3607 /* ARGUSED */
3608 struct direct *
3609 readdir (dirp)
3610 register DIR *dirp; /* stream from opendir */
3611 {
3612 #ifndef VMS
3613 register struct olddir *dp; /* -> directory data */
3614 #else /* VMS */
3615 register struct dir$_name *dp; /* -> directory data */
3616 register struct dir$_version *dv; /* -> version data */
3617 #endif /* VMS */
3618
3619 for (; ;)
3620 {
3621 if (dirp->dd_loc >= dirp->dd_size)
3622 dirp->dd_loc = dirp->dd_size = 0;
3623
3624 if (dirp->dd_size == 0 /* refill buffer */
3625 && (dirp->dd_size = sys_read (dirp->dd_fd, dirp->dd_buf, DIRBLKSIZ)) <= 0)
3626 return 0;
3627
3628 #ifndef VMS
3629 dp = (struct olddir *) &dirp->dd_buf[dirp->dd_loc];
3630 dirp->dd_loc += sizeof (struct olddir);
3631
3632 if (dp->od_ino != 0) /* not deleted entry */
3633 {
3634 dir_static.d_ino = dp->od_ino;
3635 strncpy (dir_static.d_name, dp->od_name, DIRSIZ);
3636 dir_static.d_name[DIRSIZ] = '\0';
3637 dir_static.d_namlen = strlen (dir_static.d_name);
3638 dir_static.d_reclen = sizeof (struct direct)
3639 - MAXNAMLEN + 3
3640 + dir_static.d_namlen - dir_static.d_namlen % 4;
3641 return &dir_static; /* -> simulated structure */
3642 }
3643 #else /* VMS */
3644 dp = (struct dir$_name *) dirp->dd_buf;
3645 if (dirp->dd_loc == 0)
3646 dirp->dd_loc = (dp->dir$b_namecount&1) ? dp->dir$b_namecount + 1
3647 : dp->dir$b_namecount;
3648 dv = (struct dir$_version *)&dp->dir$t_name[dirp->dd_loc];
3649 dir_static.d_ino = dv->dir$w_fid_num;
3650 dir_static.d_namlen = dp->dir$b_namecount;
3651 dir_static.d_reclen = sizeof (struct direct)
3652 - MAXNAMLEN + 3
3653 + dir_static.d_namlen - dir_static.d_namlen % 4;
3654 strncpy (dir_static.d_name, dp->dir$t_name, dp->dir$b_namecount);
3655 dir_static.d_name[dir_static.d_namlen] = '\0';
3656 dirp->dd_loc = dirp->dd_size; /* only one record at a time */
3657 return &dir_static;
3658 #endif /* VMS */
3659 }
3660 }
3661
3662 #ifdef VMS
3663 /* readdirver is just like readdir except it returns all versions of a file
3664 as separate entries. */
3665
3666 /* ARGUSED */
3667 struct direct *
3668 readdirver (dirp)
3669 register DIR *dirp; /* stream from opendir */
3670 {
3671 register struct dir$_name *dp; /* -> directory data */
3672 register struct dir$_version *dv; /* -> version data */
3673
3674 if (dirp->dd_loc >= dirp->dd_size - sizeof (struct dir$_name))
3675 dirp->dd_loc = dirp->dd_size = 0;
3676
3677 if (dirp->dd_size == 0 /* refill buffer */
3678 && (dirp->dd_size = sys_read (dirp->dd_fd, dirp->dd_buf, DIRBLKSIZ)) <= 0)
3679 return 0;
3680
3681 dp = (struct dir$_name *) dirp->dd_buf;
3682 if (dirp->dd_loc == 0)
3683 dirp->dd_loc = (dp->dir$b_namecount & 1) ? dp->dir$b_namecount + 1
3684 : dp->dir$b_namecount;
3685 dv = (struct dir$_version *) &dp->dir$t_name[dirp->dd_loc];
3686 strncpy (dir_static.d_name, dp->dir$t_name, dp->dir$b_namecount);
3687 sprintf (&dir_static.d_name[dp->dir$b_namecount], ";%d", dv->dir$w_version);
3688 dir_static.d_namlen = strlen (dir_static.d_name);
3689 dir_static.d_ino = dv->dir$w_fid_num;
3690 dir_static.d_reclen = sizeof (struct direct) - MAXNAMLEN + 3
3691 + dir_static.d_namlen - dir_static.d_namlen % 4;
3692 dirp->dd_loc = ((char *) (++dv) - dp->dir$t_name);
3693 return &dir_static;
3694 }
3695
3696 #endif /* VMS */
3697
3698 #endif /* NONSYSTEM_DIR_LIBRARY */
3699
3700 \f
3701 int
3702 set_file_times (filename, atime, mtime)
3703 char *filename;
3704 EMACS_TIME atime, mtime;
3705 {
3706 #ifdef HAVE_UTIMES
3707 struct timeval tv[2];
3708 tv[0] = atime;
3709 tv[1] = mtime;
3710 return utimes (filename, tv);
3711 #else /* not HAVE_UTIMES */
3712 struct utimbuf utb;
3713 utb.actime = EMACS_SECS (atime);
3714 utb.modtime = EMACS_SECS (mtime);
3715 return utime (filename, &utb);
3716 #endif /* not HAVE_UTIMES */
3717 }
3718 \f
3719 /* mkdir and rmdir functions, for systems which don't have them. */
3720
3721 #ifndef HAVE_MKDIR
3722 /*
3723 * Written by Robert Rother, Mariah Corporation, August 1985.
3724 *
3725 * If you want it, it's yours. All I ask in return is that if you
3726 * figure out how to do this in a Bourne Shell script you send me
3727 * a copy.
3728 * sdcsvax!rmr or rmr@uscd
3729 *
3730 * Severely hacked over by John Gilmore to make a 4.2BSD compatible
3731 * subroutine. 11Mar86; hoptoad!gnu
3732 *
3733 * Modified by rmtodd@uokmax 6-28-87 -- when making an already existing dir,
3734 * subroutine didn't return EEXIST. It does now.
3735 */
3736
3737 /*
3738 * Make a directory.
3739 */
3740 #ifdef MKDIR_PROTOTYPE
3741 MKDIR_PROTOTYPE
3742 #else
3743 int
3744 mkdir (dpath, dmode)
3745 char *dpath;
3746 int dmode;
3747 #endif
3748 {
3749 int cpid, status, fd;
3750 struct stat statbuf;
3751
3752 if (stat (dpath, &statbuf) == 0)
3753 {
3754 errno = EEXIST; /* Stat worked, so it already exists */
3755 return -1;
3756 }
3757
3758 /* If stat fails for a reason other than non-existence, return error */
3759 if (errno != ENOENT)
3760 return -1;
3761
3762 synch_process_alive = 1;
3763 switch (cpid = fork ())
3764 {
3765
3766 case -1: /* Error in fork */
3767 return (-1); /* Errno is set already */
3768
3769 case 0: /* Child process */
3770 /*
3771 * Cheap hack to set mode of new directory. Since this
3772 * child process is going away anyway, we zap its umask.
3773 * FIXME, this won't suffice to set SUID, SGID, etc. on this
3774 * directory. Does anybody care?
3775 */
3776 status = umask (0); /* Get current umask */
3777 status = umask (status | (0777 & ~dmode)); /* Set for mkdir */
3778 fd = sys_open ("/dev/null", 2);
3779 if (fd >= 0)
3780 {
3781 dup2 (fd, 0);
3782 dup2 (fd, 1);
3783 dup2 (fd, 2);
3784 }
3785 execl ("/bin/mkdir", "mkdir", dpath, (char *) 0);
3786 _exit (-1); /* Can't exec /bin/mkdir */
3787
3788 default: /* Parent process */
3789 wait_for_termination (cpid);
3790 }
3791
3792 if (synch_process_death != 0 || synch_process_retcode != 0)
3793 {
3794 errno = EIO; /* We don't know why, but */
3795 return -1; /* /bin/mkdir failed */
3796 }
3797
3798 return 0;
3799 }
3800 #endif /* not HAVE_MKDIR */
3801
3802 #ifndef HAVE_RMDIR
3803 int
3804 rmdir (dpath)
3805 char *dpath;
3806 {
3807 int cpid, status, fd;
3808 struct stat statbuf;
3809
3810 if (stat (dpath, &statbuf) != 0)
3811 {
3812 /* Stat just set errno. We don't have to */
3813 return -1;
3814 }
3815
3816 synch_process_alive = 1;
3817 switch (cpid = fork ())
3818 {
3819
3820 case -1: /* Error in fork */
3821 return (-1); /* Errno is set already */
3822
3823 case 0: /* Child process */
3824 fd = sys_open ("/dev/null", 2);
3825 if (fd >= 0)
3826 {
3827 dup2 (fd, 0);
3828 dup2 (fd, 1);
3829 dup2 (fd, 2);
3830 }
3831 execl ("/bin/rmdir", "rmdir", dpath, (char *) 0);
3832 _exit (-1); /* Can't exec /bin/rmdir */
3833
3834 default: /* Parent process */
3835 wait_for_termination (cpid);
3836 }
3837
3838 if (synch_process_death != 0 || synch_process_retcode != 0)
3839 {
3840 errno = EIO; /* We don't know why, but */
3841 return -1; /* /bin/rmdir failed */
3842 }
3843
3844 return 0;
3845 }
3846 #endif /* !HAVE_RMDIR */
3847
3848
3849 \f
3850 /* Functions for VMS */
3851 #ifdef VMS
3852 #include "vms-pwd.h"
3853 #include <acldef.h>
3854 #include <chpdef.h>
3855 #include <jpidef.h>
3856
3857 /* Return as a string the VMS error string pertaining to STATUS.
3858 Reuses the same static buffer each time it is called. */
3859
3860 char *
3861 vmserrstr (status)
3862 int status; /* VMS status code */
3863 {
3864 int bufadr[2];
3865 short len;
3866 static char buf[257];
3867
3868 bufadr[0] = sizeof buf - 1;
3869 bufadr[1] = (int) buf;
3870 if (! (SYS$GETMSG (status, &len, bufadr, 0x1, 0) & 1))
3871 return "untranslatable VMS error status";
3872 buf[len] = '\0';
3873 return buf;
3874 }
3875
3876 #ifdef access
3877 #undef access
3878
3879 /* The following is necessary because 'access' emulation by VMS C (2.0) does
3880 * not work correctly. (It also doesn't work well in version 2.3.)
3881 */
3882
3883 #ifdef VMS4_4
3884
3885 #define DESCRIPTOR(name,string) struct dsc$descriptor_s name = \
3886 { strlen (string), DSC$K_DTYPE_T, DSC$K_CLASS_S, string }
3887
3888 typedef union {
3889 struct {
3890 unsigned short s_buflen;
3891 unsigned short s_code;
3892 char *s_bufadr;
3893 unsigned short *s_retlenadr;
3894 } s;
3895 int end;
3896 } item;
3897 #define buflen s.s_buflen
3898 #define code s.s_code
3899 #define bufadr s.s_bufadr
3900 #define retlenadr s.s_retlenadr
3901
3902 #define R_OK 4 /* test for read permission */
3903 #define W_OK 2 /* test for write permission */
3904 #define X_OK 1 /* test for execute (search) permission */
3905 #define F_OK 0 /* test for presence of file */
3906
3907 int
3908 sys_access (path, mode)
3909 char *path;
3910 int mode;
3911 {
3912 static char *user = NULL;
3913 char dir_fn[512];
3914
3915 /* translate possible directory spec into .DIR file name, so brain-dead
3916 * access can treat the directory like a file. */
3917 if (directory_file_name (path, dir_fn))
3918 path = dir_fn;
3919
3920 if (mode == F_OK)
3921 return access (path, mode);
3922 if (user == NULL && (user = (char *) getenv ("USER")) == NULL)
3923 return -1;
3924 {
3925 int stat;
3926 int flags;
3927 int acces;
3928 unsigned short int dummy;
3929 item itemlst[3];
3930 static int constant = ACL$C_FILE;
3931 DESCRIPTOR (path_desc, path);
3932 DESCRIPTOR (user_desc, user);
3933
3934 flags = 0;
3935 acces = 0;
3936 if ((mode & X_OK) && ((stat = access (path, mode)) < 0 || mode == X_OK))
3937 return stat;
3938 if (mode & R_OK)
3939 acces |= CHP$M_READ;
3940 if (mode & W_OK)
3941 acces |= CHP$M_WRITE;
3942 itemlst[0].buflen = sizeof (int);
3943 itemlst[0].code = CHP$_FLAGS;
3944 itemlst[0].bufadr = (char *) &flags;
3945 itemlst[0].retlenadr = &dummy;
3946 itemlst[1].buflen = sizeof (int);
3947 itemlst[1].code = CHP$_ACCESS;
3948 itemlst[1].bufadr = (char *) &acces;
3949 itemlst[1].retlenadr = &dummy;
3950 itemlst[2].end = CHP$_END;
3951 stat = SYS$CHECK_ACCESS (&constant, &path_desc, &user_desc, itemlst);
3952 return stat == SS$_NORMAL ? 0 : -1;
3953 }
3954 }
3955
3956 #else /* not VMS4_4 */
3957
3958 #include <prvdef.h>
3959 #define ACE$M_WRITE 2
3960 #define ACE$C_KEYID 1
3961
3962 static unsigned short memid, grpid;
3963 static unsigned int uic;
3964
3965 /* Called from init_sys_modes, so it happens not very often
3966 but at least each time Emacs is loaded. */
3967 void
3968 sys_access_reinit ()
3969 {
3970 uic = 0;
3971 }
3972
3973 int
3974 sys_access (filename, type)
3975 char * filename;
3976 int type;
3977 {
3978 struct FAB fab;
3979 struct XABPRO xab;
3980 int status, size, i, typecode, acl_controlled;
3981 unsigned int *aclptr, *aclend, aclbuf[60];
3982 union prvdef prvmask;
3983
3984 /* Get UIC and GRP values for protection checking. */
3985 if (uic == 0)
3986 {
3987 status = LIB$GETJPI (&JPI$_UIC, 0, 0, &uic, 0, 0);
3988 if (! (status & 1))
3989 return -1;
3990 memid = uic & 0xFFFF;
3991 grpid = uic >> 16;
3992 }
3993
3994 if (type != 2) /* not checking write access */
3995 return access (filename, type);
3996
3997 /* Check write protection. */
3998
3999 #define CHECKPRIV(bit) (prvmask.bit)
4000 #define WRITABLE(field) (! ((xab.xab$w_pro >> field) & XAB$M_NOWRITE))
4001
4002 /* Find privilege bits */
4003 status = SYS$SETPRV (0, 0, 0, prvmask);
4004 if (! (status & 1))
4005 error ("Unable to find privileges: %s", vmserrstr (status));
4006 if (CHECKPRIV (PRV$V_BYPASS))
4007 return 0; /* BYPASS enabled */
4008 fab = cc$rms_fab;
4009 fab.fab$b_fac = FAB$M_GET;
4010 fab.fab$l_fna = filename;
4011 fab.fab$b_fns = strlen (filename);
4012 fab.fab$l_xab = &xab;
4013 xab = cc$rms_xabpro;
4014 xab.xab$l_aclbuf = aclbuf;
4015 xab.xab$w_aclsiz = sizeof (aclbuf);
4016 status = SYS$OPEN (&fab, 0, 0);
4017 if (! (status & 1))
4018 return -1;
4019 SYS$CLOSE (&fab, 0, 0);
4020 /* Check system access */
4021 if (CHECKPRIV (PRV$V_SYSPRV) && WRITABLE (XAB$V_SYS))
4022 return 0;
4023 /* Check ACL entries, if any */
4024 acl_controlled = 0;
4025 if (xab.xab$w_acllen > 0)
4026 {
4027 aclptr = aclbuf;
4028 aclend = &aclbuf[xab.xab$w_acllen / 4];
4029 while (*aclptr && aclptr < aclend)
4030 {
4031 size = (*aclptr & 0xff) / 4;
4032 typecode = (*aclptr >> 8) & 0xff;
4033 if (typecode == ACE$C_KEYID)
4034 for (i = size - 1; i > 1; i--)
4035 if (aclptr[i] == uic)
4036 {
4037 acl_controlled = 1;
4038 if (aclptr[1] & ACE$M_WRITE)
4039 return 0; /* Write access through ACL */
4040 }
4041 aclptr = &aclptr[size];
4042 }
4043 if (acl_controlled) /* ACL specified, prohibits write access */
4044 return -1;
4045 }
4046 /* No ACL entries specified, check normal protection */
4047 if (WRITABLE (XAB$V_WLD)) /* World writable */
4048 return 0;
4049 if (WRITABLE (XAB$V_GRP) &&
4050 (unsigned short) (xab.xab$l_uic >> 16) == grpid)
4051 return 0; /* Group writable */
4052 if (WRITABLE (XAB$V_OWN) &&
4053 (xab.xab$l_uic & 0xFFFF) == memid)
4054 return 0; /* Owner writable */
4055
4056 return -1; /* Not writable */
4057 }
4058 #endif /* not VMS4_4 */
4059 #endif /* access */
4060
4061 static char vtbuf[NAM$C_MAXRSS+1];
4062
4063 /* translate a vms file spec to a unix path */
4064 char *
4065 sys_translate_vms (vfile)
4066 char * vfile;
4067 {
4068 char * p;
4069 char * targ;
4070
4071 if (!vfile)
4072 return 0;
4073
4074 targ = vtbuf;
4075
4076 /* leading device or logical name is a root directory */
4077 if (p = strchr (vfile, ':'))
4078 {
4079 *targ++ = '/';
4080 while (vfile < p)
4081 *targ++ = *vfile++;
4082 vfile++;
4083 *targ++ = '/';
4084 }
4085 p = vfile;
4086 if (*p == '[' || *p == '<')
4087 {
4088 while (*++vfile != *p + 2)
4089 switch (*vfile)
4090 {
4091 case '.':
4092 if (vfile[-1] == *p)
4093 *targ++ = '.';
4094 *targ++ = '/';
4095 break;
4096
4097 case '-':
4098 *targ++ = '.';
4099 *targ++ = '.';
4100 break;
4101
4102 default:
4103 *targ++ = *vfile;
4104 break;
4105 }
4106 vfile++;
4107 *targ++ = '/';
4108 }
4109 while (*vfile)
4110 *targ++ = *vfile++;
4111
4112 return vtbuf;
4113 }
4114
4115 static char utbuf[NAM$C_MAXRSS+1];
4116
4117 /* translate a unix path to a VMS file spec */
4118 char *
4119 sys_translate_unix (ufile)
4120 char * ufile;
4121 {
4122 int slash_seen = 0;
4123 char *p;
4124 char * targ;
4125
4126 if (!ufile)
4127 return 0;
4128
4129 targ = utbuf;
4130
4131 if (*ufile == '/')
4132 {
4133 ufile++;
4134 }
4135
4136 while (*ufile)
4137 {
4138 switch (*ufile)
4139 {
4140 case '/':
4141 if (slash_seen)
4142 if (index (&ufile[1], '/'))
4143 *targ++ = '.';
4144 else
4145 *targ++ = ']';
4146 else
4147 {
4148 *targ++ = ':';
4149 if (index (&ufile[1], '/'))
4150 *targ++ = '[';
4151 slash_seen = 1;
4152 }
4153 break;
4154
4155 case '.':
4156 if (strncmp (ufile, "./", 2) == 0)
4157 {
4158 if (!slash_seen)
4159 {
4160 *targ++ = '[';
4161 slash_seen = 1;
4162 }
4163 ufile++; /* skip the dot */
4164 if (index (&ufile[1], '/'))
4165 *targ++ = '.';
4166 else
4167 *targ++ = ']';
4168 }
4169 else if (strncmp (ufile, "../", 3) == 0)
4170 {
4171 if (!slash_seen)
4172 {
4173 *targ++ = '[';
4174 slash_seen = 1;
4175 }
4176 *targ++ = '-';
4177 ufile += 2; /* skip the dots */
4178 if (index (&ufile[1], '/'))
4179 *targ++ = '.';
4180 else
4181 *targ++ = ']';
4182 }
4183 else
4184 *targ++ = *ufile;
4185 break;
4186
4187 default:
4188 *targ++ = *ufile;
4189 break;
4190 }
4191 ufile++;
4192 }
4193 *targ = '\0';
4194
4195 return utbuf;
4196 }
4197
4198 char *
4199 getwd (pathname)
4200 char *pathname;
4201 {
4202 char *ptr, *val;
4203 extern char *getcwd ();
4204
4205 #define MAXPATHLEN 1024
4206
4207 ptr = xmalloc (MAXPATHLEN);
4208 val = getcwd (ptr, MAXPATHLEN);
4209 if (val == 0)
4210 {
4211 xfree (ptr);
4212 return val;
4213 }
4214 strcpy (pathname, ptr);
4215 xfree (ptr);
4216
4217 return pathname;
4218 }
4219
4220 int
4221 getppid ()
4222 {
4223 long item_code = JPI$_OWNER;
4224 unsigned long parent_id;
4225 int status;
4226
4227 if (((status = LIB$GETJPI (&item_code, 0, 0, &parent_id)) & 1) == 0)
4228 {
4229 errno = EVMSERR;
4230 vaxc$errno = status;
4231 return -1;
4232 }
4233 return parent_id;
4234 }
4235
4236 #undef getuid
4237 unsigned
4238 sys_getuid ()
4239 {
4240 return (getgid () << 16) | getuid ();
4241 }
4242
4243 int
4244 sys_read (fildes, buf, nbyte)
4245 int fildes;
4246 char *buf;
4247 unsigned int nbyte;
4248 {
4249 return read (fildes, buf, (nbyte < MAXIOSIZE ? nbyte : MAXIOSIZE));
4250 }
4251
4252 #if 0
4253 int
4254 sys_write (fildes, buf, nbyte)
4255 int fildes;
4256 char *buf;
4257 unsigned int nbyte;
4258 {
4259 register int nwrote, rtnval = 0;
4260
4261 while (nbyte > MAXIOSIZE && (nwrote = write (fildes, buf, MAXIOSIZE)) > 0) {
4262 nbyte -= nwrote;
4263 buf += nwrote;
4264 rtnval += nwrote;
4265 }
4266 if (nwrote < 0)
4267 return rtnval ? rtnval : -1;
4268 if ((nwrote = write (fildes, buf, nbyte)) < 0)
4269 return rtnval ? rtnval : -1;
4270 return (rtnval + nwrote);
4271 }
4272 #endif /* 0 */
4273
4274 /*
4275 * VAX/VMS VAX C RTL really loses. It insists that records
4276 * end with a newline (carriage return) character, and if they
4277 * don't it adds one (nice of it isn't it!)
4278 *
4279 * Thus we do this stupidity below.
4280 */
4281
4282 int
4283 sys_write (fildes, buf, nbytes)
4284 int fildes;
4285 char *buf;
4286 unsigned int nbytes;
4287 {
4288 register char *p;
4289 register char *e;
4290 int sum = 0;
4291 struct stat st;
4292
4293 fstat (fildes, &st);
4294 p = buf;
4295 while (nbytes > 0)
4296 {
4297 int len, retval;
4298
4299 /* Handle fixed-length files with carriage control. */
4300 if (st.st_fab_rfm == FAB$C_FIX
4301 && ((st.st_fab_rat & (FAB$M_FTN | FAB$M_CR)) != 0))
4302 {
4303 len = st.st_fab_mrs;
4304 retval = write (fildes, p, min (len, nbytes));
4305 if (retval != len)
4306 return -1;
4307 retval++; /* This skips the implied carriage control */
4308 }
4309 else
4310 {
4311 e = p + min (MAXIOSIZE, nbytes) - 1;
4312 while (*e != '\n' && e > p) e--;
4313 if (p == e) /* Ok.. so here we add a newline... sigh. */
4314 e = p + min (MAXIOSIZE, nbytes) - 1;
4315 len = e + 1 - p;
4316 retval = write (fildes, p, len);
4317 if (retval != len)
4318 return -1;
4319 }
4320 p += retval;
4321 sum += retval;
4322 nbytes -= retval;
4323 }
4324 return sum;
4325 }
4326
4327 /* Create file NEW copying its attributes from file OLD. If
4328 OLD is 0 or does not exist, create based on the value of
4329 vms_stmlf_recfm. */
4330
4331 /* Protection value the file should ultimately have.
4332 Set by create_copy_attrs, and use by rename_sansversions. */
4333 static unsigned short int fab_final_pro;
4334
4335 int
4336 creat_copy_attrs (old, new)
4337 char *old, *new;
4338 {
4339 struct FAB fab = cc$rms_fab;
4340 struct XABPRO xabpro;
4341 char aclbuf[256]; /* Choice of size is arbitrary. See below. */
4342 extern int vms_stmlf_recfm;
4343
4344 if (old)
4345 {
4346 fab.fab$b_fac = FAB$M_GET;
4347 fab.fab$l_fna = old;
4348 fab.fab$b_fns = strlen (old);
4349 fab.fab$l_xab = (char *) &xabpro;
4350 xabpro = cc$rms_xabpro;
4351 xabpro.xab$l_aclbuf = aclbuf;
4352 xabpro.xab$w_aclsiz = sizeof aclbuf;
4353 /* Call $OPEN to fill in the fab & xabpro fields. */
4354 if (SYS$OPEN (&fab, 0, 0) & 1)
4355 {
4356 SYS$CLOSE (&fab, 0, 0);
4357 fab.fab$l_alq = 0; /* zero the allocation quantity */
4358 if (xabpro.xab$w_acllen > 0)
4359 {
4360 if (xabpro.xab$w_acllen > sizeof aclbuf)
4361 /* If the acl buffer was too short, redo open with longer one.
4362 Wouldn't need to do this if there were some system imposed
4363 limit on the size of an ACL, but I can't find any such. */
4364 {
4365 xabpro.xab$l_aclbuf = (char *) alloca (xabpro.xab$w_acllen);
4366 xabpro.xab$w_aclsiz = xabpro.xab$w_acllen;
4367 if (SYS$OPEN (&fab, 0, 0) & 1)
4368 SYS$CLOSE (&fab, 0, 0);
4369 else
4370 old = 0;
4371 }
4372 }
4373 else
4374 xabpro.xab$l_aclbuf = 0;
4375 }
4376 else
4377 old = 0;
4378 }
4379 fab.fab$l_fna = new;
4380 fab.fab$b_fns = strlen (new);
4381 if (!old)
4382 {
4383 fab.fab$l_xab = 0;
4384 fab.fab$b_rfm = vms_stmlf_recfm ? FAB$C_STMLF : FAB$C_VAR;
4385 fab.fab$b_rat = FAB$M_CR;
4386 }
4387
4388 /* Set the file protections such that we will be able to manipulate
4389 this file. Once we are done writing and renaming it, we will set
4390 the protections back. */
4391 if (old)
4392 fab_final_pro = xabpro.xab$w_pro;
4393 else
4394 SYS$SETDFPROT (0, &fab_final_pro);
4395 xabpro.xab$w_pro &= 0xff0f; /* set O:rewd for now. This is set back later. */
4396
4397 /* Create the new file with either default attrs or attrs copied
4398 from old file. */
4399 if (!(SYS$CREATE (&fab, 0, 0) & 1))
4400 return -1;
4401 SYS$CLOSE (&fab, 0, 0);
4402 /* As this is a "replacement" for creat, return a file descriptor
4403 opened for writing. */
4404 return open (new, O_WRONLY);
4405 }
4406
4407 #ifdef creat
4408 #undef creat
4409 #include <varargs.h>
4410 #ifdef __GNUC__
4411 #ifndef va_count
4412 #define va_count(X) ((X) = *(((int *) &(va_alist)) - 1))
4413 #endif
4414 #endif
4415
4416 int
4417 sys_creat (va_alist)
4418 va_dcl
4419 {
4420 va_list list_incrementer;
4421 char *name;
4422 int mode;
4423 int rfd; /* related file descriptor */
4424 int fd; /* Our new file descriptor */
4425 int count;
4426 struct stat st_buf;
4427 char rfm[12];
4428 char rat[15];
4429 char mrs[13];
4430 char fsz[13];
4431 extern int vms_stmlf_recfm;
4432
4433 va_count (count);
4434 va_start (list_incrementer);
4435 name = va_arg (list_incrementer, char *);
4436 mode = va_arg (list_incrementer, int);
4437 if (count > 2)
4438 rfd = va_arg (list_incrementer, int);
4439 va_end (list_incrementer);
4440 if (count > 2)
4441 {
4442 /* Use information from the related file descriptor to set record
4443 format of the newly created file. */
4444 fstat (rfd, &st_buf);
4445 switch (st_buf.st_fab_rfm)
4446 {
4447 case FAB$C_FIX:
4448 strcpy (rfm, "rfm = fix");
4449 sprintf (mrs, "mrs = %d", st_buf.st_fab_mrs);
4450 strcpy (rat, "rat = ");
4451 if (st_buf.st_fab_rat & FAB$M_CR)
4452 strcat (rat, "cr");
4453 else if (st_buf.st_fab_rat & FAB$M_FTN)
4454 strcat (rat, "ftn");
4455 else if (st_buf.st_fab_rat & FAB$M_PRN)
4456 strcat (rat, "prn");
4457 if (st_buf.st_fab_rat & FAB$M_BLK)
4458 if (st_buf.st_fab_rat & (FAB$M_CR|FAB$M_FTN|FAB$M_PRN))
4459 strcat (rat, ", blk");
4460 else
4461 strcat (rat, "blk");
4462 return creat (name, 0, rfm, rat, mrs);
4463
4464 case FAB$C_VFC:
4465 strcpy (rfm, "rfm = vfc");
4466 sprintf (fsz, "fsz = %d", st_buf.st_fab_fsz);
4467 strcpy (rat, "rat = ");
4468 if (st_buf.st_fab_rat & FAB$M_CR)
4469 strcat (rat, "cr");
4470 else if (st_buf.st_fab_rat & FAB$M_FTN)
4471 strcat (rat, "ftn");
4472 else if (st_buf.st_fab_rat & FAB$M_PRN)
4473 strcat (rat, "prn");
4474 if (st_buf.st_fab_rat & FAB$M_BLK)
4475 if (st_buf.st_fab_rat & (FAB$M_CR|FAB$M_FTN|FAB$M_PRN))
4476 strcat (rat, ", blk");
4477 else
4478 strcat (rat, "blk");
4479 return creat (name, 0, rfm, rat, fsz);
4480
4481 case FAB$C_STM:
4482 strcpy (rfm, "rfm = stm");
4483 break;
4484
4485 case FAB$C_STMCR:
4486 strcpy (rfm, "rfm = stmcr");
4487 break;
4488
4489 case FAB$C_STMLF:
4490 strcpy (rfm, "rfm = stmlf");
4491 break;
4492
4493 case FAB$C_UDF:
4494 strcpy (rfm, "rfm = udf");
4495 break;
4496
4497 case FAB$C_VAR:
4498 strcpy (rfm, "rfm = var");
4499 break;
4500 }
4501 strcpy (rat, "rat = ");
4502 if (st_buf.st_fab_rat & FAB$M_CR)
4503 strcat (rat, "cr");
4504 else if (st_buf.st_fab_rat & FAB$M_FTN)
4505 strcat (rat, "ftn");
4506 else if (st_buf.st_fab_rat & FAB$M_PRN)
4507 strcat (rat, "prn");
4508 if (st_buf.st_fab_rat & FAB$M_BLK)
4509 if (st_buf.st_fab_rat & (FAB$M_CR|FAB$M_FTN|FAB$M_PRN))
4510 strcat (rat, ", blk");
4511 else
4512 strcat (rat, "blk");
4513 }
4514 else
4515 {
4516 strcpy (rfm, vms_stmlf_recfm ? "rfm = stmlf" : "rfm=var");
4517 strcpy (rat, "rat=cr");
4518 }
4519 /* Until the VAX C RTL fixes the many bugs with modes, always use
4520 mode 0 to get the user's default protection. */
4521 fd = creat (name, 0, rfm, rat);
4522 if (fd < 0 && errno == EEXIST)
4523 {
4524 if (unlink (name) < 0)
4525 report_file_error ("delete", build_string (name));
4526 fd = creat (name, 0, rfm, rat);
4527 }
4528 return fd;
4529 }
4530 #endif /* creat */
4531
4532 /* fwrite to stdout is S L O W. Speed it up by using fputc...*/
4533 int
4534 sys_fwrite (ptr, size, num, fp)
4535 register char * ptr;
4536 FILE * fp;
4537 {
4538 register int tot = num * size;
4539
4540 while (tot--)
4541 fputc (*ptr++, fp);
4542 return num;
4543 }
4544
4545 /*
4546 * The VMS C library routine creat actually creates a new version of an
4547 * existing file rather than truncating the old version. There are times
4548 * when this is not the desired behavior, for instance, when writing an
4549 * auto save file (you only want one version), or when you don't have
4550 * write permission in the directory containing the file (but the file
4551 * itself is writable). Hence this routine, which is equivalent to
4552 * "close (creat (fn, 0));" on Unix if fn already exists.
4553 */
4554 int
4555 vms_truncate (fn)
4556 char *fn;
4557 {
4558 struct FAB xfab = cc$rms_fab;
4559 struct RAB xrab = cc$rms_rab;
4560 int status;
4561
4562 xfab.fab$l_fop = FAB$M_TEF; /* free allocated but unused blocks on close */
4563 xfab.fab$b_fac = FAB$M_TRN | FAB$M_GET; /* allow truncate and get access */
4564 xfab.fab$b_shr = FAB$M_NIL; /* allow no sharing - file must be locked */
4565 xfab.fab$l_fna = fn;
4566 xfab.fab$b_fns = strlen (fn);
4567 xfab.fab$l_dna = ";0"; /* default to latest version of the file */
4568 xfab.fab$b_dns = 2;
4569 xrab.rab$l_fab = &xfab;
4570
4571 /* This gibberish opens the file, positions to the first record, and
4572 deletes all records from there until the end of file. */
4573 if ((SYS$OPEN (&xfab) & 01) == 01)
4574 {
4575 if ((SYS$CONNECT (&xrab) & 01) == 01 &&
4576 (SYS$FIND (&xrab) & 01) == 01 &&
4577 (SYS$TRUNCATE (&xrab) & 01) == 01)
4578 status = 0;
4579 else
4580 status = -1;
4581 }
4582 else
4583 status = -1;
4584 SYS$CLOSE (&xfab);
4585 return status;
4586 }
4587
4588 /* Define this symbol to actually read SYSUAF.DAT. This requires either
4589 SYSPRV or a readable SYSUAF.DAT. */
4590
4591 #ifdef READ_SYSUAF
4592 /*
4593 * getuaf.c
4594 *
4595 * Routine to read the VMS User Authorization File and return
4596 * a specific user's record.
4597 */
4598
4599 static struct UAF retuaf;
4600
4601 struct UAF *
4602 get_uaf_name (uname)
4603 char * uname;
4604 {
4605 register status;
4606 struct FAB uaf_fab;
4607 struct RAB uaf_rab;
4608
4609 uaf_fab = cc$rms_fab;
4610 uaf_rab = cc$rms_rab;
4611 /* initialize fab fields */
4612 uaf_fab.fab$l_fna = "SYS$SYSTEM:SYSUAF.DAT";
4613 uaf_fab.fab$b_fns = 21;
4614 uaf_fab.fab$b_fac = FAB$M_GET;
4615 uaf_fab.fab$b_org = FAB$C_IDX;
4616 uaf_fab.fab$b_shr = FAB$M_GET|FAB$M_PUT|FAB$M_UPD|FAB$M_DEL;
4617 /* initialize rab fields */
4618 uaf_rab.rab$l_fab = &uaf_fab;
4619 /* open the User Authorization File */
4620 status = SYS$OPEN (&uaf_fab);
4621 if (!(status&1))
4622 {
4623 errno = EVMSERR;
4624 vaxc$errno = status;
4625 return 0;
4626 }
4627 status = SYS$CONNECT (&uaf_rab);
4628 if (!(status&1))
4629 {
4630 errno = EVMSERR;
4631 vaxc$errno = status;
4632 return 0;
4633 }
4634 /* read the requested record - index is in uname */
4635 uaf_rab.rab$l_kbf = uname;
4636 uaf_rab.rab$b_ksz = strlen (uname);
4637 uaf_rab.rab$b_rac = RAB$C_KEY;
4638 uaf_rab.rab$l_ubf = (char *)&retuaf;
4639 uaf_rab.rab$w_usz = sizeof retuaf;
4640 status = SYS$GET (&uaf_rab);
4641 if (!(status&1))
4642 {
4643 errno = EVMSERR;
4644 vaxc$errno = status;
4645 return 0;
4646 }
4647 /* close the User Authorization File */
4648 status = SYS$DISCONNECT (&uaf_rab);
4649 if (!(status&1))
4650 {
4651 errno = EVMSERR;
4652 vaxc$errno = status;
4653 return 0;
4654 }
4655 status = SYS$CLOSE (&uaf_fab);
4656 if (!(status&1))
4657 {
4658 errno = EVMSERR;
4659 vaxc$errno = status;
4660 return 0;
4661 }
4662 return &retuaf;
4663 }
4664
4665 struct UAF *
4666 get_uaf_uic (uic)
4667 unsigned long uic;
4668 {
4669 register status;
4670 struct FAB uaf_fab;
4671 struct RAB uaf_rab;
4672
4673 uaf_fab = cc$rms_fab;
4674 uaf_rab = cc$rms_rab;
4675 /* initialize fab fields */
4676 uaf_fab.fab$l_fna = "SYS$SYSTEM:SYSUAF.DAT";
4677 uaf_fab.fab$b_fns = 21;
4678 uaf_fab.fab$b_fac = FAB$M_GET;
4679 uaf_fab.fab$b_org = FAB$C_IDX;
4680 uaf_fab.fab$b_shr = FAB$M_GET|FAB$M_PUT|FAB$M_UPD|FAB$M_DEL;
4681 /* initialize rab fields */
4682 uaf_rab.rab$l_fab = &uaf_fab;
4683 /* open the User Authorization File */
4684 status = SYS$OPEN (&uaf_fab);
4685 if (!(status&1))
4686 {
4687 errno = EVMSERR;
4688 vaxc$errno = status;
4689 return 0;
4690 }
4691 status = SYS$CONNECT (&uaf_rab);
4692 if (!(status&1))
4693 {
4694 errno = EVMSERR;
4695 vaxc$errno = status;
4696 return 0;
4697 }
4698 /* read the requested record - index is in uic */
4699 uaf_rab.rab$b_krf = 1; /* 1st alternate key */
4700 uaf_rab.rab$l_kbf = (char *) &uic;
4701 uaf_rab.rab$b_ksz = sizeof uic;
4702 uaf_rab.rab$b_rac = RAB$C_KEY;
4703 uaf_rab.rab$l_ubf = (char *)&retuaf;
4704 uaf_rab.rab$w_usz = sizeof retuaf;
4705 status = SYS$GET (&uaf_rab);
4706 if (!(status&1))
4707 {
4708 errno = EVMSERR;
4709 vaxc$errno = status;
4710 return 0;
4711 }
4712 /* close the User Authorization File */
4713 status = SYS$DISCONNECT (&uaf_rab);
4714 if (!(status&1))
4715 {
4716 errno = EVMSERR;
4717 vaxc$errno = status;
4718 return 0;
4719 }
4720 status = SYS$CLOSE (&uaf_fab);
4721 if (!(status&1))
4722 {
4723 errno = EVMSERR;
4724 vaxc$errno = status;
4725 return 0;
4726 }
4727 return &retuaf;
4728 }
4729
4730 static struct passwd retpw;
4731
4732 struct passwd *
4733 cnv_uaf_pw (up)
4734 struct UAF * up;
4735 {
4736 char * ptr;
4737
4738 /* copy these out first because if the username is 32 chars, the next
4739 section will overwrite the first byte of the UIC */
4740 retpw.pw_uid = up->uaf$w_mem;
4741 retpw.pw_gid = up->uaf$w_grp;
4742
4743 /* I suppose this is not the best style, to possibly overwrite one
4744 byte beyond the end of the field, but what the heck... */
4745 ptr = &up->uaf$t_username[UAF$S_USERNAME];
4746 while (ptr[-1] == ' ')
4747 ptr--;
4748 *ptr = '\0';
4749 strcpy (retpw.pw_name, up->uaf$t_username);
4750
4751 /* the rest of these are counted ascii strings */
4752 strncpy (retpw.pw_gecos, &up->uaf$t_owner[1], up->uaf$t_owner[0]);
4753 retpw.pw_gecos[up->uaf$t_owner[0]] = '\0';
4754 strncpy (retpw.pw_dir, &up->uaf$t_defdev[1], up->uaf$t_defdev[0]);
4755 retpw.pw_dir[up->uaf$t_defdev[0]] = '\0';
4756 strncat (retpw.pw_dir, &up->uaf$t_defdir[1], up->uaf$t_defdir[0]);
4757 retpw.pw_dir[up->uaf$t_defdev[0] + up->uaf$t_defdir[0]] = '\0';
4758 strncpy (retpw.pw_shell, &up->uaf$t_defcli[1], up->uaf$t_defcli[0]);
4759 retpw.pw_shell[up->uaf$t_defcli[0]] = '\0';
4760
4761 return &retpw;
4762 }
4763 #else /* not READ_SYSUAF */
4764 static struct passwd retpw;
4765 #endif /* not READ_SYSUAF */
4766
4767 struct passwd *
4768 getpwnam (name)
4769 char * name;
4770 {
4771 #ifdef READ_SYSUAF
4772 struct UAF *up;
4773 #else
4774 char * user;
4775 char * dir;
4776 unsigned char * full;
4777 #endif /* READ_SYSUAF */
4778 char *ptr = name;
4779
4780 while (*ptr)
4781 {
4782 if ('a' <= *ptr && *ptr <= 'z')
4783 *ptr -= 040;
4784 ptr++;
4785 }
4786 #ifdef READ_SYSUAF
4787 if (!(up = get_uaf_name (name)))
4788 return 0;
4789 return cnv_uaf_pw (up);
4790 #else
4791 if (strcmp (name, getenv ("USER")) == 0)
4792 {
4793 retpw.pw_uid = getuid ();
4794 retpw.pw_gid = getgid ();
4795 strcpy (retpw.pw_name, name);
4796 if (full = egetenv ("FULLNAME"))
4797 strcpy (retpw.pw_gecos, full);
4798 else
4799 *retpw.pw_gecos = '\0';
4800 strcpy (retpw.pw_dir, egetenv ("HOME"));
4801 *retpw.pw_shell = '\0';
4802 return &retpw;
4803 }
4804 else
4805 return 0;
4806 #endif /* not READ_SYSUAF */
4807 }
4808
4809 struct passwd *
4810 getpwuid (uid)
4811 unsigned long uid;
4812 {
4813 #ifdef READ_SYSUAF
4814 struct UAF * up;
4815
4816 if (!(up = get_uaf_uic (uid)))
4817 return 0;
4818 return cnv_uaf_pw (up);
4819 #else
4820 if (uid == sys_getuid ())
4821 return getpwnam (egetenv ("USER"));
4822 else
4823 return 0;
4824 #endif /* not READ_SYSUAF */
4825 }
4826
4827 /* return total address space available to the current process. This is
4828 the sum of the current p0 size, p1 size and free page table entries
4829 available. */
4830 int
4831 vlimit ()
4832 {
4833 int item_code;
4834 unsigned long free_pages;
4835 unsigned long frep0va;
4836 unsigned long frep1va;
4837 register status;
4838
4839 item_code = JPI$_FREPTECNT;
4840 if (((status = LIB$GETJPI (&item_code, 0, 0, &free_pages)) & 1) == 0)
4841 {
4842 errno = EVMSERR;
4843 vaxc$errno = status;
4844 return -1;
4845 }
4846 free_pages *= 512;
4847
4848 item_code = JPI$_FREP0VA;
4849 if (((status = LIB$GETJPI (&item_code, 0, 0, &frep0va)) & 1) == 0)
4850 {
4851 errno = EVMSERR;
4852 vaxc$errno = status;
4853 return -1;
4854 }
4855 item_code = JPI$_FREP1VA;
4856 if (((status = LIB$GETJPI (&item_code, 0, 0, &frep1va)) & 1) == 0)
4857 {
4858 errno = EVMSERR;
4859 vaxc$errno = status;
4860 return -1;
4861 }
4862
4863 return free_pages + frep0va + (0x7fffffff - frep1va);
4864 }
4865
4866 int
4867 define_logical_name (varname, string)
4868 char *varname;
4869 char *string;
4870 {
4871 struct dsc$descriptor_s strdsc =
4872 {strlen (string), DSC$K_DTYPE_T, DSC$K_CLASS_S, string};
4873 struct dsc$descriptor_s envdsc =
4874 {strlen (varname), DSC$K_DTYPE_T, DSC$K_CLASS_S, varname};
4875 struct dsc$descriptor_s lnmdsc =
4876 {7, DSC$K_DTYPE_T, DSC$K_CLASS_S, "LNM$JOB"};
4877
4878 return LIB$SET_LOGICAL (&envdsc, &strdsc, &lnmdsc, 0, 0);
4879 }
4880
4881 int
4882 delete_logical_name (varname)
4883 char *varname;
4884 {
4885 struct dsc$descriptor_s envdsc =
4886 {strlen (varname), DSC$K_DTYPE_T, DSC$K_CLASS_S, varname};
4887 struct dsc$descriptor_s lnmdsc =
4888 {7, DSC$K_DTYPE_T, DSC$K_CLASS_S, "LNM$JOB"};
4889
4890 return LIB$DELETE_LOGICAL (&envdsc, &lnmdsc);
4891 }
4892
4893 int
4894 ulimit ()
4895 {
4896 return 0;
4897 }
4898
4899 int
4900 setpgrp ()
4901 {
4902 return 0;
4903 }
4904
4905 int
4906 execvp ()
4907 {
4908 error ("execvp system call not implemented");
4909 return -1;
4910 }
4911
4912 int
4913 rename (from, to)
4914 char *from, *to;
4915 {
4916 int status;
4917 struct FAB from_fab = cc$rms_fab, to_fab = cc$rms_fab;
4918 struct NAM from_nam = cc$rms_nam, to_nam = cc$rms_nam;
4919 char from_esn[NAM$C_MAXRSS];
4920 char to_esn[NAM$C_MAXRSS];
4921
4922 from_fab.fab$l_fna = from;
4923 from_fab.fab$b_fns = strlen (from);
4924 from_fab.fab$l_nam = &from_nam;
4925 from_fab.fab$l_fop = FAB$M_NAM;
4926
4927 from_nam.nam$l_esa = from_esn;
4928 from_nam.nam$b_ess = sizeof from_esn;
4929
4930 to_fab.fab$l_fna = to;
4931 to_fab.fab$b_fns = strlen (to);
4932 to_fab.fab$l_nam = &to_nam;
4933 to_fab.fab$l_fop = FAB$M_NAM;
4934
4935 to_nam.nam$l_esa = to_esn;
4936 to_nam.nam$b_ess = sizeof to_esn;
4937
4938 status = SYS$RENAME (&from_fab, 0, 0, &to_fab);
4939
4940 if (status & 1)
4941 return 0;
4942 else
4943 {
4944 if (status == RMS$_DEV)
4945 errno = EXDEV;
4946 else
4947 errno = EVMSERR;
4948 vaxc$errno = status;
4949 return -1;
4950 }
4951 }
4952
4953 /* This function renames a file like `rename', but it strips
4954 the version number from the "to" filename, such that the "to" file is
4955 will always be a new version. It also sets the file protection once it is
4956 finished. The protection that we will use is stored in fab_final_pro,
4957 and was set when we did a creat_copy_attrs to create the file that we
4958 are renaming.
4959
4960 We could use the chmod function, but Eunichs uses 3 bits per user category
4961 to describe the protection, and VMS uses 4 (write and delete are separate
4962 bits). To maintain portability, the VMS implementation of `chmod' wires
4963 the W and D bits together. */
4964
4965
4966 static struct fibdef fib; /* We need this initialized to zero */
4967 char vms_file_written[NAM$C_MAXRSS];
4968
4969 int
4970 rename_sans_version (from,to)
4971 char *from, *to;
4972 {
4973 short int chan;
4974 int stat;
4975 short int iosb[4];
4976 int status;
4977 struct FAB to_fab = cc$rms_fab;
4978 struct NAM to_nam = cc$rms_nam;
4979 struct dsc$descriptor fib_d ={sizeof (fib),0,0,(char*) &fib};
4980 struct dsc$descriptor fib_attr[2]
4981 = {{sizeof (fab_final_pro),ATR$C_FPRO,0,(char*) &fab_final_pro},{0,0,0,0}};
4982 char to_esn[NAM$C_MAXRSS];
4983
4984 $DESCRIPTOR (disk,to_esn);
4985
4986 to_fab.fab$l_fna = to;
4987 to_fab.fab$b_fns = strlen (to);
4988 to_fab.fab$l_nam = &to_nam;
4989 to_fab.fab$l_fop = FAB$M_NAM;
4990
4991 to_nam.nam$l_esa = to_esn;
4992 to_nam.nam$b_ess = sizeof to_esn;
4993
4994 status = SYS$PARSE (&to_fab, 0, 0); /* figure out the full file name */
4995
4996 if (to_nam.nam$l_fnb && NAM$M_EXP_VER)
4997 *(to_nam.nam$l_ver) = '\0';
4998
4999 stat = rename (from, to_esn);
5000 if (stat < 0)
5001 return stat;
5002
5003 strcpy (vms_file_written, to_esn);
5004
5005 to_fab.fab$l_fna = vms_file_written; /* this points to the versionless name */
5006 to_fab.fab$b_fns = strlen (vms_file_written);
5007
5008 /* Now set the file protection to the correct value */
5009 SYS$OPEN (&to_fab, 0, 0); /* This fills in the nam$w_fid fields */
5010
5011 /* Copy these fields into the fib */
5012 fib.fib$r_fid_overlay.fib$w_fid[0] = to_nam.nam$w_fid[0];
5013 fib.fib$r_fid_overlay.fib$w_fid[1] = to_nam.nam$w_fid[1];
5014 fib.fib$r_fid_overlay.fib$w_fid[2] = to_nam.nam$w_fid[2];
5015
5016 SYS$CLOSE (&to_fab, 0, 0);
5017
5018 stat = SYS$ASSIGN (&disk, &chan, 0, 0); /* open a channel to the disk */
5019 if (!stat)
5020 LIB$SIGNAL (stat);
5021 stat = SYS$QIOW (0, chan, IO$_MODIFY, iosb, 0, 0, &fib_d,
5022 0, 0, 0, &fib_attr, 0);
5023 if (!stat)
5024 LIB$SIGNAL (stat);
5025 stat = SYS$DASSGN (chan);
5026 if (!stat)
5027 LIB$SIGNAL (stat);
5028 strcpy (vms_file_written, to_esn); /* We will write this to the terminal*/
5029 return 0;
5030 }
5031
5032 int
5033 link (file, new)
5034 char * file, * new;
5035 {
5036 register status;
5037 struct FAB fab;
5038 struct NAM nam;
5039 unsigned short fid[3];
5040 char esa[NAM$C_MAXRSS];
5041
5042 fab = cc$rms_fab;
5043 fab.fab$l_fop = FAB$M_OFP;
5044 fab.fab$l_fna = file;
5045 fab.fab$b_fns = strlen (file);
5046 fab.fab$l_nam = &nam;
5047
5048 nam = cc$rms_nam;
5049 nam.nam$l_esa = esa;
5050 nam.nam$b_ess = NAM$C_MAXRSS;
5051
5052 status = SYS$PARSE (&fab);
5053 if ((status & 1) == 0)
5054 {
5055 errno = EVMSERR;
5056 vaxc$errno = status;
5057 return -1;
5058 }
5059 status = SYS$SEARCH (&fab);
5060 if ((status & 1) == 0)
5061 {
5062 errno = EVMSERR;
5063 vaxc$errno = status;
5064 return -1;
5065 }
5066
5067 fid[0] = nam.nam$w_fid[0];
5068 fid[1] = nam.nam$w_fid[1];
5069 fid[2] = nam.nam$w_fid[2];
5070
5071 fab.fab$l_fna = new;
5072 fab.fab$b_fns = strlen (new);
5073
5074 status = SYS$PARSE (&fab);
5075 if ((status & 1) == 0)
5076 {
5077 errno = EVMSERR;
5078 vaxc$errno = status;
5079 return -1;
5080 }
5081
5082 nam.nam$w_fid[0] = fid[0];
5083 nam.nam$w_fid[1] = fid[1];
5084 nam.nam$w_fid[2] = fid[2];
5085
5086 nam.nam$l_esa = nam.nam$l_name;
5087 nam.nam$b_esl = nam.nam$b_name + nam.nam$b_type + nam.nam$b_ver;
5088
5089 status = SYS$ENTER (&fab);
5090 if ((status & 1) == 0)
5091 {
5092 errno = EVMSERR;
5093 vaxc$errno = status;
5094 return -1;
5095 }
5096
5097 return 0;
5098 }
5099
5100 void
5101 croak (badfunc)
5102 char *badfunc;
5103 {
5104 printf ("%s not yet implemented\r\n", badfunc);
5105 reset_sys_modes ();
5106 exit (1);
5107 }
5108
5109 long
5110 random ()
5111 {
5112 /* Arrange to return a range centered on zero. */
5113 return rand () - (1 << 30);
5114 }
5115
5116 void
5117 srandom (seed)
5118 {
5119 srand (seed);
5120 }
5121 #endif /* VMS */
5122 \f
5123 #ifdef AIXHFT
5124
5125 /* Called from init_sys_modes. */
5126 void
5127 hft_init ()
5128 {
5129 int junk;
5130
5131 /* If we're not on an HFT we shouldn't do any of this. We determine
5132 if we are on an HFT by trying to get an HFT error code. If this
5133 call fails, we're not on an HFT. */
5134 #ifdef IBMR2AIX
5135 if (ioctl (0, HFQERROR, &junk) < 0)
5136 return;
5137 #else /* not IBMR2AIX */
5138 if (ioctl (0, HFQEIO, 0) < 0)
5139 return;
5140 #endif /* not IBMR2AIX */
5141
5142 /* On AIX the default hft keyboard mapping uses backspace rather than delete
5143 as the rubout key's ASCII code. Here this is changed. The bug is that
5144 there's no way to determine the old mapping, so in reset_sys_modes
5145 we need to assume that the normal map had been present. Of course, this
5146 code also doesn't help if on a terminal emulator which doesn't understand
5147 HFT VTD's. */
5148 {
5149 struct hfbuf buf;
5150 struct hfkeymap keymap;
5151
5152 buf.hf_bufp = (char *)&keymap;
5153 buf.hf_buflen = sizeof (keymap);
5154 keymap.hf_nkeys = 2;
5155 keymap.hfkey[0].hf_kpos = 15;
5156 keymap.hfkey[0].hf_kstate = HFMAPCHAR | HFSHFNONE;
5157 #ifdef IBMR2AIX
5158 keymap.hfkey[0].hf_keyidh = '<';
5159 #else /* not IBMR2AIX */
5160 keymap.hfkey[0].hf_page = '<';
5161 #endif /* not IBMR2AIX */
5162 keymap.hfkey[0].hf_char = 127;
5163 keymap.hfkey[1].hf_kpos = 15;
5164 keymap.hfkey[1].hf_kstate = HFMAPCHAR | HFSHFSHFT;
5165 #ifdef IBMR2AIX
5166 keymap.hfkey[1].hf_keyidh = '<';
5167 #else /* not IBMR2AIX */
5168 keymap.hfkey[1].hf_page = '<';
5169 #endif /* not IBMR2AIX */
5170 keymap.hfkey[1].hf_char = 127;
5171 hftctl (0, HFSKBD, &buf);
5172 }
5173 /* The HFT system on AIX doesn't optimize for scrolling, so it's really ugly
5174 at times. */
5175 line_ins_del_ok = char_ins_del_ok = 0;
5176 }
5177
5178 /* Reset the rubout key to backspace. */
5179
5180 void
5181 hft_reset ()
5182 {
5183 struct hfbuf buf;
5184 struct hfkeymap keymap;
5185 int junk;
5186
5187 #ifdef IBMR2AIX
5188 if (ioctl (0, HFQERROR, &junk) < 0)
5189 return;
5190 #else /* not IBMR2AIX */
5191 if (ioctl (0, HFQEIO, 0) < 0)
5192 return;
5193 #endif /* not IBMR2AIX */
5194
5195 buf.hf_bufp = (char *)&keymap;
5196 buf.hf_buflen = sizeof (keymap);
5197 keymap.hf_nkeys = 2;
5198 keymap.hfkey[0].hf_kpos = 15;
5199 keymap.hfkey[0].hf_kstate = HFMAPCHAR | HFSHFNONE;
5200 #ifdef IBMR2AIX
5201 keymap.hfkey[0].hf_keyidh = '<';
5202 #else /* not IBMR2AIX */
5203 keymap.hfkey[0].hf_page = '<';
5204 #endif /* not IBMR2AIX */
5205 keymap.hfkey[0].hf_char = 8;
5206 keymap.hfkey[1].hf_kpos = 15;
5207 keymap.hfkey[1].hf_kstate = HFMAPCHAR | HFSHFSHFT;
5208 #ifdef IBMR2AIX
5209 keymap.hfkey[1].hf_keyidh = '<';
5210 #else /* not IBMR2AIX */
5211 keymap.hfkey[1].hf_page = '<';
5212 #endif /* not IBMR2AIX */
5213 keymap.hfkey[1].hf_char = 8;
5214 hftctl (0, HFSKBD, &buf);
5215 }
5216
5217 #endif /* AIXHFT */
5218
5219 #ifdef USE_DL_STUBS
5220
5221 /* These are included on Sunos 4.1 when we do not use shared libraries.
5222 X11 libraries may refer to these functions but (we hope) do not
5223 actually call them. */
5224
5225 void *
5226 dlopen ()
5227 {
5228 return 0;
5229 }
5230
5231 void *
5232 dlsym ()
5233 {
5234 return 0;
5235 }
5236
5237 int
5238 dlclose ()
5239 {
5240 return -1;
5241 }
5242
5243 #endif /* USE_DL_STUBS */
5244 \f
5245 #ifndef BSTRING
5246
5247 #ifndef bzero
5248
5249 void
5250 bzero (b, length)
5251 register char *b;
5252 register int length;
5253 {
5254 #ifdef VMS
5255 short zero = 0;
5256 long max_str = 65535;
5257
5258 while (length > max_str) {
5259 (void) LIB$MOVC5 (&zero, &zero, &zero, &max_str, b);
5260 length -= max_str;
5261 b += max_str;
5262 }
5263 max_str = length;
5264 (void) LIB$MOVC5 (&zero, &zero, &zero, &max_str, b);
5265 #else
5266 while (length-- > 0)
5267 *b++ = 0;
5268 #endif /* not VMS */
5269 }
5270
5271 #endif /* no bzero */
5272 #endif /* BSTRING */
5273
5274 #if (!defined (BSTRING) && !defined (bcopy)) || defined (NEED_BCOPY)
5275 #undef bcopy
5276
5277 /* Saying `void' requires a declaration, above, where bcopy is used
5278 and that declaration causes pain for systems where bcopy is a macro. */
5279 bcopy (b1, b2, length)
5280 register char *b1;
5281 register char *b2;
5282 register int length;
5283 {
5284 #ifdef VMS
5285 long max_str = 65535;
5286
5287 while (length > max_str) {
5288 (void) LIB$MOVC3 (&max_str, b1, b2);
5289 length -= max_str;
5290 b1 += max_str;
5291 b2 += max_str;
5292 }
5293 max_str = length;
5294 (void) LIB$MOVC3 (&length, b1, b2);
5295 #else
5296 while (length-- > 0)
5297 *b2++ = *b1++;
5298 #endif /* not VMS */
5299 }
5300 #endif /* (!defined (BSTRING) && !defined (bcopy)) || defined (NEED_BCOPY) */
5301
5302 #ifndef BSTRING
5303 #ifndef bcmp
5304 int
5305 bcmp (b1, b2, length) /* This could be a macro! */
5306 register char *b1;
5307 register char *b2;
5308 register int length;
5309 {
5310 #ifdef VMS
5311 struct dsc$descriptor_s src1 = {length, DSC$K_DTYPE_T, DSC$K_CLASS_S, b1};
5312 struct dsc$descriptor_s src2 = {length, DSC$K_DTYPE_T, DSC$K_CLASS_S, b2};
5313
5314 return STR$COMPARE (&src1, &src2);
5315 #else
5316 while (length-- > 0)
5317 if (*b1++ != *b2++)
5318 return 1;
5319
5320 return 0;
5321 #endif /* not VMS */
5322 }
5323 #endif /* no bcmp */
5324 #endif /* not BSTRING */
5325
5326 /* All the Macintosh stuffs go here */
5327
5328 #ifdef macintosh
5329
5330 #include <Files.h>
5331 #include <MacTypes.h>
5332 #include <TextUtils.h>
5333 #include <Folders.h>
5334
5335 #include <dirent.h>
5336 #include <sys/stat.h>
5337 #include <string.h>
5338 #include <pwd.h>
5339 #include <sys/param.h>
5340
5341 /* Convert a Mac pathname to Unix form. A Mac full pathname is one
5342 that does not begin with a ':' and contains at least one ':'. A Mac
5343 full pathname causes an '/' to be prepended to the Unix pathname.
5344 The algorithm for the rest of the pathname is as follows:
5345 For each segment between two ':',
5346 if it is non-null, copy as is and then add a '/' at the end,
5347 otherwise, insert a "../" into the Unix pathname.
5348 Returns 1 if successful; 0 if fails. */
5349
5350 int
5351 Mac2UnixPathname (const char *mfn, char *ufn, int ufnbuflen)
5352 {
5353 const char *p, *q, *pe;
5354
5355 strcpy (ufn, "");
5356
5357 if (*mfn == '\0')
5358 return 1;
5359
5360 p = strchr (mfn, ':');
5361 if (p != 0 && p != mfn) /* full pathname */
5362 strcat (ufn, "/");
5363
5364 p = mfn;
5365 if (*p == ':')
5366 p++;
5367
5368 pe = mfn + strlen (mfn);
5369 while (p < pe)
5370 {
5371 q = strchr (p, ':');
5372 if (q)
5373 {
5374 if (q == p)
5375 { /* two consecutive ':' */
5376 if (strlen (ufn) + 3 >= ufnbuflen)
5377 return 0;
5378 strcat (ufn, "../");
5379 }
5380 else
5381 {
5382 if (strlen (ufn) + (q - p) + 1 >= ufnbuflen)
5383 return 0;
5384 strncat (ufn, p, q - p);
5385 strcat (ufn, "/");
5386 }
5387 p = q + 1;
5388 }
5389 else
5390 {
5391 if (strlen (ufn) + (pe - p) >= ufnbuflen)
5392 return 0;
5393 strncat (ufn, p, pe - p); /* no separator for last one */
5394 p = pe;
5395 }
5396 }
5397
5398 return 1;
5399 }
5400
5401 extern char *GetTempDirName ();
5402
5403 /* Convert a Unix pathname to Mac form. Approximately reverse of the
5404 above in algorithm. */
5405 int
5406 Unix2MacPathname (const char *ufn, char *mfn, int mfnbuflen)
5407 {
5408 const char *p, *q, *pe;
5409 char expandedPathname[MAXPATHLEN+1];
5410
5411 strcpy (mfn, "");
5412
5413 if (*ufn == '\0')
5414 return 1;
5415
5416 p = ufn;
5417
5418 /* Check for and handle volume names. Last comparison: strangely
5419 somewhere `/.emacs' is passed. A temporary fix for now. */
5420 if (*p == '/' && strchr (p+1, '/') == NULL && strcmp (p, "/.emacs") != 0)
5421 {
5422 if (strlen (p) + 1 > mfnbuflen)
5423 return 0;
5424 strcpy (mfn, p+1);
5425 strcat (mfn, ":");
5426 return 1;
5427 }
5428
5429 if (strncmp (p, "~emacs/", 7) == 0)
5430 { /* expand to emacs dir found by InitEmacsPasswdDir */
5431 struct passwd *pw = getpwnam ("emacs");
5432 p += 7;
5433 if (strlen (pw->pw_dir) + strlen (p) > MAXPATHLEN)
5434 return 0;
5435 strcpy (expandedPathname, pw->pw_dir);
5436 strcat (expandedPathname, p);
5437 p = expandedPathname;
5438 /* Now p points to the pathname with emacs dir prefix. */
5439 }
5440 else if (strncmp (p, "/tmp/", 5) == 0)
5441 {
5442 char *t = GetTempDirName ();
5443 p += 5;
5444 if (strlen (t) + strlen (p) > MAXPATHLEN)
5445 return 0;
5446 strcpy (expandedPathname, t);
5447 strcat (expandedPathname, p);
5448 p = expandedPathname;
5449 /* Now p points to the pathname with emacs dir prefix. */
5450 }
5451 else if (*p != '/') /* relative pathname */
5452 strcat (mfn, ":");
5453
5454 if (*p == '/')
5455 p++;
5456
5457 pe = p + strlen (p);
5458 while (p < pe)
5459 {
5460 q = strchr (p, '/');
5461 if (q)
5462 {
5463 if (q - p == 2 && *p == '.' && *(p+1) == '.')
5464 {
5465 if (strlen (mfn) + 1 >= mfnbuflen)
5466 return 0;
5467 strcat (mfn, ":");
5468 }
5469 else
5470 {
5471 if (strlen (mfn) + (q - p) + 1 >= mfnbuflen)
5472 return 0;
5473 strncat (mfn, p, q - p);
5474 strcat (mfn, ":");
5475 }
5476 p = q + 1;
5477 }
5478 else
5479 {
5480 if (strlen (mfn) + (pe - p) >= mfnbuflen)
5481 return 0;
5482 strncat (mfn, p, pe - p);
5483 p = pe;
5484 }
5485 }
5486
5487 return 1;
5488 }
5489
5490 /* The following functions with "sys_" prefix are stubs to Unix
5491 functions that have already been implemented by CW or MPW. The
5492 calls to them in Emacs source course are #define'd to call the sys_
5493 versions by the header files s-mac.h. In these stubs pathnames are
5494 converted between their Unix and Mac forms. */
5495 /* Unix Epoch is Jan 1, 1970 while Mac Epoch is Jan 1, 1904: 66 years
5496 + 17 leap days */
5497 #define MAC_UNIX_EPOCH_DIFF ((365L * 66 + 17) * 24 * 60 * 60)
5498
5499 /* CW Epoch is Jan 1, 1900 (aaarghhhhh!); remember, 1900 is not a leap
5500 year! */
5501 #define CW_UNIX_EPOCH_DIFF ((365L * 70 + 17) * 24 * 60 * 60)
5502
5503 /* Define our own stat function for both MrC and CW. The reason for
5504 doing this: "stat" is both the name of a struct and function name:
5505 can't use the same trick like that for sys_open, sys_close, etc. to
5506 redirect Emacs's calls to our own version that converts Unix style
5507 filenames to Mac style filename because all sorts of compilation
5508 errors will be generated if stat is #define'd to be sys_stat. */
5509
5510 int
5511 stat (const char *path, struct stat *buf)
5512 {
5513 char MacPathname[MAXPATHLEN+1];
5514 CInfoPBRec cipb;
5515
5516 if (Unix2MacPathname (path, MacPathname, MAXPATHLEN+1) == 0)
5517 return -1;
5518
5519 c2pstr (MacPathname);
5520 cipb.hFileInfo.ioNamePtr = MacPathname;
5521 cipb.hFileInfo.ioVRefNum = 0;
5522 cipb.hFileInfo.ioDirID = 0;
5523 cipb.hFileInfo.ioFDirIndex = 0; /* set to 0 to get information about specific dir or file */
5524
5525 errno = PBGetCatInfo (&cipb, false);
5526 if (errno == -43) /* -43: fnfErr defined in Errors.h */
5527 errno = ENOENT;
5528 if (errno != noErr)
5529 return -1;
5530
5531 if (cipb.hFileInfo.ioFlAttrib & 0x10)
5532 { /* bit 4 = 1 for directories */
5533 buf->st_mode = S_IFDIR | S_IREAD | S_IEXEC;
5534 if (!(cipb.hFileInfo.ioFlAttrib & 0x1)) /* bit 1 = 1 for locked files/directories */
5535 buf->st_mode |= S_IWRITE;
5536 buf->st_ino = cipb.dirInfo.ioDrDirID;
5537 buf->st_dev = cipb.dirInfo.ioVRefNum;
5538 buf->st_size = cipb.dirInfo.ioDrNmFls; /* size of dir = number of files and dirs */
5539 buf->st_atime = buf->st_mtime = cipb.dirInfo.ioDrMdDat - MAC_UNIX_EPOCH_DIFF;
5540 buf->st_ctime = cipb.dirInfo.ioDrCrDat - MAC_UNIX_EPOCH_DIFF;
5541 }
5542 else
5543 {
5544 buf->st_mode = S_IFREG | S_IREAD;
5545 if (!(cipb.hFileInfo.ioFlAttrib & 0x1)) /* bit 1 = 1 for locked files/directories */
5546 buf->st_mode |= S_IWRITE;
5547 if (cipb.hFileInfo.ioFlFndrInfo.fdType == 'APPL')
5548 buf->st_mode |= S_IEXEC;
5549 buf->st_ino = cipb.hFileInfo.ioDirID;
5550 buf->st_dev = cipb.hFileInfo.ioVRefNum;
5551 buf->st_size = cipb.hFileInfo.ioFlLgLen;
5552 buf->st_atime = buf->st_mtime = cipb.hFileInfo.ioFlMdDat - MAC_UNIX_EPOCH_DIFF;
5553 buf->st_ctime = cipb.hFileInfo.ioFlCrDat - MAC_UNIX_EPOCH_DIFF;
5554 }
5555 buf->st_nlink = 1;
5556 buf->st_uid = getuid ();
5557 buf->st_gid = getgid ();
5558 buf->st_rdev = 0;
5559
5560 return 0;
5561 }
5562
5563 #if __MRC__
5564
5565 /* CW defines fstat in stat.mac.c while MPW does not provide this
5566 function. Without the information of how to get from a file
5567 descriptor in MPW StdCLib to a Mac OS file spec, it should be hard
5568 to implement this function. Fortunately, there is only one place
5569 where this function is called in our configuration: in fileio.c,
5570 where only the st_dev and st_ino fields are used to determine
5571 whether two fildes point to different i-nodes to prevent copying
5572 a file onto itself equal. What we have here probably needs
5573 improvement. */
5574 int
5575 fstat (int fildes, struct stat *buf)
5576 {
5577 buf->st_dev = 0;
5578 buf->st_ino = fildes;
5579 return 0; /* success */
5580 }
5581
5582 #endif /* __MRC__ */
5583
5584 /* From Think Reference code example */
5585 int
5586 mkdir (const char *dirname, int mode)
5587 {
5588 #pragma unused (mode)
5589
5590 HFileParam hfpb;
5591 char MacPathname[MAXPATHLEN+1];
5592
5593 if (Unix2MacPathname (dirname, MacPathname, MAXPATHLEN+1) == 0)
5594 return -1;
5595
5596 c2pstr (MacPathname);
5597 hfpb.ioNamePtr = MacPathname;
5598 hfpb.ioVRefNum = 0; /*ignored unless name is invalid */
5599 hfpb.ioDirID = 0; /*parent is the root */
5600
5601 /* Just return the Mac OSErr code for now. */
5602 errno = PBDirCreate ((HParmBlkPtr) &hfpb, false);
5603 return errno == noErr ? 0 : -1;
5604 }
5605
5606 int
5607 rmdir (const char *dirname)
5608 {
5609 HFileParam hfpb;
5610 char MacPathname[MAXPATHLEN+1];
5611
5612 if (Unix2MacPathname (dirname, MacPathname, MAXPATHLEN+1) == 0)
5613 return -1;
5614
5615 c2pstr (MacPathname);
5616 hfpb.ioNamePtr = MacPathname;
5617 hfpb.ioVRefNum = 0; /*ignored unless name is invalid */
5618 hfpb.ioDirID = 0; /*parent is the root */
5619
5620 errno = PBHDelete ((HParmBlkPtr) &hfpb, false);
5621 return errno == noErr ? 0 : -1;
5622 }
5623
5624 #ifdef __MRC__
5625
5626 /* No implementation yet. */
5627 int
5628 execvp (const char *path, ...)
5629 {
5630 return -1;
5631 }
5632
5633 #endif /* __MRC__ */
5634
5635 int
5636 utime (const char *path, const struct utimbuf *times)
5637 {
5638 char MacPathname[MAXPATHLEN+1];
5639 CInfoPBRec cipb;
5640
5641 if (Unix2MacPathname (path, MacPathname, MAXPATHLEN+1) == 0)
5642 return -1;
5643
5644 c2pstr (MacPathname);
5645 cipb.hFileInfo.ioNamePtr = MacPathname;
5646 cipb.hFileInfo.ioVRefNum = 0;
5647 cipb.hFileInfo.ioDirID = 0;
5648 /* Set to 0 to get information about specific dir or file. */
5649 cipb.hFileInfo.ioFDirIndex = 0;
5650
5651 errno = PBGetCatInfo (&cipb, false);
5652 if (errno != noErr)
5653 return -1;
5654
5655 if (cipb.hFileInfo.ioFlAttrib & 0x10)
5656 { /* bit 4 = 1 for directories */
5657 if (times)
5658 cipb.dirInfo.ioDrMdDat = times->modtime + MAC_UNIX_EPOCH_DIFF;
5659 else
5660 GetDateTime (&cipb.dirInfo.ioDrMdDat);
5661 }
5662 else
5663 {
5664 if (times)
5665 cipb.hFileInfo.ioFlMdDat = times->modtime + MAC_UNIX_EPOCH_DIFF;
5666 else
5667 GetDateTime (&cipb.hFileInfo.ioFlMdDat);
5668 }
5669
5670 errno = PBSetCatInfo (&cipb, false);
5671 return errno == noErr ? 0 : -1;
5672 }
5673
5674 #define F_OK 0
5675 #define X_OK 1
5676 #define W_OK 2
5677
5678 /* Like stat, but test for access mode in hfpb.ioFlAttrib. */
5679 int
5680 access (const char *path, int mode)
5681 {
5682 char MacPathname[MAXPATHLEN+1];
5683 CInfoPBRec cipb;
5684
5685 if (Unix2MacPathname (path, MacPathname, MAXPATHLEN+1) == 0)
5686 return -1;
5687
5688 c2pstr (MacPathname);
5689 cipb.hFileInfo.ioNamePtr = MacPathname;
5690 cipb.hFileInfo.ioVRefNum = 0;
5691 cipb.hFileInfo.ioDirID = 0;
5692 cipb.hFileInfo.ioFDirIndex = 0; /* set to 0 to get information about specific dir or file */
5693
5694 errno = PBGetCatInfo (&cipb, false);
5695 if (errno != noErr)
5696 return -1;
5697
5698 if (mode == F_OK) /* got this far, file exists */
5699 return 0;
5700
5701 if (mode & X_OK)
5702 if (cipb.hFileInfo.ioFlAttrib & 0x10) /* path refers to a directory */
5703 return 0;
5704 else
5705 {
5706 if (cipb.hFileInfo.ioFlFndrInfo.fdType == 'APPL')
5707 return 0;
5708 else
5709 return -1;
5710 }
5711
5712 if (mode & W_OK)
5713 return (cipb.hFileInfo.ioFlAttrib & 0x1) ? -1 : 0; /* don't allow if lock bit on */
5714
5715 return -1;
5716 }
5717
5718 #define DEV_NULL_FD 0x10000
5719
5720 #undef open
5721 int
5722 sys_open (const char *path, int oflag)
5723 {
5724 char MacPathname[MAXPATHLEN+1];
5725
5726 if (strcmp (path, "/dev/null") == 0)
5727 return DEV_NULL_FD; /* some bogus fd to be ignored in write */
5728
5729 if (Unix2MacPathname (path, MacPathname, MAXPATHLEN+1) == 0)
5730 return -1;
5731 else
5732 return open (MacPathname, oflag);
5733 }
5734
5735 #undef creat
5736 int
5737 sys_creat (const char *path, mode_t mode)
5738 {
5739 char MacPathname[MAXPATHLEN+1];
5740
5741 if (Unix2MacPathname (path, MacPathname, MAXPATHLEN+1) == 0)
5742 return -1;
5743 else
5744 return creat (MacPathname, mode);
5745 }
5746
5747 #undef unlink
5748 int
5749 sys_unlink (const char *path)
5750 {
5751 char MacPathname[MAXPATHLEN+1];
5752
5753 if (Unix2MacPathname (path, MacPathname, MAXPATHLEN+1) == 0)
5754 return -1;
5755 else
5756 return unlink (MacPathname);
5757 }
5758
5759 #undef read
5760 int
5761 sys_read (int fildes, char *buf, int count)
5762 {
5763 if (fildes == 0)
5764 { /* if stdin, call (non-echoing) "getch" in console.h */
5765 if (MacKeyPending ())
5766 { /* don't wait for a key if none has been pressed */
5767 *buf = MacGetChar ();
5768 return 1;
5769 }
5770 else
5771 return 0;
5772 }
5773 else
5774 return read (fildes, buf, count);
5775 }
5776
5777 #undef write
5778 int
5779 sys_write (int fildes, char *buf, int count)
5780 {
5781 if (fildes == DEV_NULL_FD)
5782 return count;
5783 else
5784 return write (fildes, buf, count);
5785 }
5786
5787 #undef rename
5788 int
5789 sys_rename (const char * old_name, const char * new_name)
5790 {
5791 char MacOldName[MAXPATHLEN+1], MacNewName[MAXPATHLEN+1];
5792
5793 if (strcmp (old_name, new_name) == 0)
5794 return 0;
5795
5796 if (Unix2MacPathname (old_name, MacOldName, MAXPATHLEN+1) == 0)
5797 return 1;
5798
5799 if (Unix2MacPathname (new_name, MacNewName, MAXPATHLEN+1) == 0)
5800 return 1;
5801
5802 return rename (MacOldName, MacNewName);
5803 }
5804
5805 #undef fopen
5806 extern FILE *fopen (const char *name, const char *mode);
5807 FILE
5808 sys_fopen (const char *name, const char *mode)
5809 {
5810 char MacPathname[MAXPATHLEN+1];
5811
5812 if (Unix2MacPathname (name, MacPathname, MAXPATHLEN+1) == 0)
5813 return 0;
5814 else
5815 return fopen (MacPathname, mode);
5816 }
5817
5818 #include <Events.h>
5819
5820 long targetTicks = 0;
5821
5822 #ifdef __MRC__
5823 __sigfun alarm_signal_func = (__sigfun) 0;
5824 #elif __MWERKS__
5825 __signal_func_ptr alarm_signal_func = (__signal_func_ptr) 0;
5826 #else
5827 You lose!!!
5828 #endif
5829
5830 /* These functions simulate SIG_ALRM. The stub for function signal
5831 stores the signal handler function in alarm_signal_func if a
5832 SIG_ALRM is encountered. CheckAlarm is called in mac_read_socket,
5833 which emacs calls periodically. A pending alarm is represented by
5834 a non-zero targetTicks value. CheckAlarm calls the handler
5835 function pointed to by alarm_signal_func if one has been set up and
5836 an alarm is pending. */
5837 void
5838 CheckAlarm ()
5839 {
5840 if (targetTicks && TickCount () > targetTicks)
5841 {
5842 targetTicks = 0;
5843 if (alarm_signal_func)
5844 (*alarm_signal_func)(SIGALRM);
5845 }
5846 }
5847
5848 /* Called in sys_select to wait for an alarm signal to arrive. */
5849 int
5850 pause ()
5851 {
5852 unsigned long finalTick;
5853
5854 if (!targetTicks) /* no alarm pending */
5855 return -1;
5856
5857 while (TickCount () <= targetTicks)
5858 Delay (1UL, &finalTick); /* wait for 1/60 second before trying again */
5859
5860 targetTicks = 0;
5861 if (alarm_signal_func)
5862 (*alarm_signal_func)(SIGALRM);
5863
5864 return 0;
5865 }
5866
5867 int
5868 alarm (int seconds)
5869 {
5870 long remaining = targetTicks ? (TickCount () - targetTicks) / 60 : 0;
5871
5872 targetTicks = seconds ? TickCount () + 60 * seconds : 0;
5873
5874 return (remaining < 0) ? 0 : (unsigned int) remaining;
5875 }
5876
5877 #undef signal
5878 #ifdef __MRC__
5879 extern __sigfun signal (int signal, __sigfun signal_func);
5880 __sigfun
5881 sys_signal (int signal_num, __sigfun signal_func)
5882 #elif __MWERKS__
5883 extern __signal_func_ptr signal (int signal, __signal_func_ptr signal_func);
5884 __signal_func_ptr
5885 sys_signal (int signal_num, __signal_func_ptr signal_func)
5886 #else
5887 You lose!!!
5888 #endif
5889 {
5890 if (signal_num != SIGALRM)
5891 return signal (signal_num, signal_func);
5892 else
5893 {
5894 #ifdef __MRC__
5895 __sigfun old_signal_func;
5896 #elif __MWERKS__
5897 __signal_func_ptr old_signal_func;
5898 #else
5899 You lose!!!
5900 #endif
5901 old_signal_func = alarm_signal_func;
5902 alarm_signal_func = signal_func;
5903 return old_signal_func;
5904 }
5905 }
5906
5907 /* The time functions adjust time values according to the difference
5908 between the Unix and CW epoches. */
5909
5910 #undef gmtime
5911 extern struct tm *gmtime (const time_t *);
5912 struct tm
5913 sys_gmtime (const time_t *timer)
5914 {
5915 time_t unixTime = *timer + CW_UNIX_EPOCH_DIFF;
5916
5917 return gmtime (&unixTime);
5918 }
5919
5920 #undef localtime
5921 extern struct tm *localtime (const time_t *);
5922 struct tm *
5923 sys_localtime (const time_t *timer)
5924 {
5925 time_t unixTime = *timer + CW_UNIX_EPOCH_DIFF;
5926
5927 return localtime (&unixTime);
5928 }
5929
5930 #undef ctime
5931 extern char *ctime (const time_t *);
5932 char *
5933 sys_ctime (const time_t *timer)
5934 {
5935 time_t unixTime = *timer + CW_UNIX_EPOCH_DIFF;
5936
5937 return ctime (&unixTime);
5938 }
5939
5940 #undef time
5941 extern time_t time (time_t *);
5942 time_t
5943 sys_time (time_t *timer)
5944 {
5945 time_t macTime = time (NULL) - CW_UNIX_EPOCH_DIFF;
5946
5947 if (timer)
5948 *timer = macTime;
5949
5950 return macTime;
5951 }
5952
5953 /* no subprocesses, empty wait */
5954 int
5955 wait (int pid)
5956 {
5957 return 0;
5958 }
5959
5960 void
5961 croak (char *badfunc)
5962 {
5963 printf ("%s not yet implemented\r\n", badfunc);
5964 exit (1);
5965 }
5966
5967 char *
5968 index (const char * str, int chr)
5969 {
5970 return strchr (str, chr);
5971 }
5972
5973 char *e[] = { 0 };
5974 char **environ = &e[0];
5975
5976 char *
5977 mktemp (char *template)
5978 {
5979 int len, k;
5980 static seqnum = 0;
5981
5982 len = strlen (template);
5983 k = len - 1;
5984 while (k >= 0 && template[k] == 'X')
5985 k--;
5986
5987 k++; /* make k index of first 'X' */
5988
5989 if (k < len)
5990 {
5991 /* Zero filled, number of digits equal to the number of X's. */
5992 sprintf (&template[k], "%0*d", len-k, seqnum++);
5993
5994 return template;
5995 }
5996 else
5997 return 0;
5998 }
5999
6000 /* Emulate getpwuid, getpwnam and others. */
6001
6002 #define PASSWD_FIELD_SIZE 256
6003
6004 static char myPasswdName[PASSWD_FIELD_SIZE];
6005 static char myPasswdDir[MAXPATHLEN+1];
6006
6007 static struct passwd myPasswd =
6008 {
6009 myPasswdName,
6010 myPasswdDir,
6011 };
6012
6013 /* Initialized by main () in macterm.c to pathname of emacs directory. */
6014 char emacsPasswdDir[MAXPATHLEN+1];
6015
6016 void
6017 InitEmacsPasswdDir ()
6018 {
6019 int found = false;
6020
6021 if (getwd (emacsPasswdDir) && getwd (myPasswdDir))
6022 {
6023 /* Need pathname of first ancestor that begins with `emacs' since
6024 Mac emacs application is somewhere in the emacs-20.3 tree. */
6025 int len = strlen (emacsPasswdDir);
6026 /* J points to the "/" following the directory name being compared. */
6027 int j = len - 1;
6028 int i = j - 1;
6029 while (i >= 0 && !found)
6030 {
6031 while (i >= 0 && emacsPasswdDir[i] != '/')
6032 i--;
6033 if (emacsPasswdDir[i] == '/' && i+5 < len)
6034 found = (strncmp (&(emacsPasswdDir[i+1]), "emacs", 5) == 0);
6035 if (found)
6036 emacsPasswdDir[j+1] = '\0';
6037 else
6038 {
6039 j = i;
6040 i = j - 1;
6041 }
6042 }
6043 }
6044
6045 if (!found)
6046 { /* setting to "/" probably won't work,
6047 but set it to something anyway. */
6048 strcpy (emacsPasswdDir, "/");
6049 strcpy (myPasswdDir, "/");
6050 }
6051 }
6052
6053 static struct passwd emacsPasswd =
6054 {
6055 "emacs",
6056 emacsPasswdDir,
6057 };
6058
6059 static int myPasswdInited = 0;
6060
6061 static void
6062 InitMyPasswd ()
6063 {
6064 char **ownerName;
6065
6066 /* Note: myPasswdDir initialized in InitEmacsPasswdDir to directory
6067 where Emacs was started. */
6068
6069 ownerName = (char **) GetResource ('STR ',-16096);
6070 if (ownerName)
6071 {
6072 HLock (ownerName);
6073 BlockMove ((unsigned char *) *ownerName,
6074 (unsigned char *) myPasswdName, *ownerName[0] + 1);
6075 HUnlock (ownerName);
6076 p2cstr ((unsigned char *) myPasswdName);
6077 }
6078 else
6079 myPasswdName[0] = 0;
6080 }
6081
6082 struct passwd *
6083 getpwuid (uid_t uid)
6084 {
6085 if (!myPasswdInited)
6086 {
6087 InitMyPasswd ();
6088 myPasswdInited = 1;
6089 }
6090
6091 return &myPasswd;
6092 }
6093
6094 struct passwd *
6095 getpwnam (const char *name)
6096 {
6097 if (strcmp (name, "emacs") == 0)
6098 return &emacsPasswd;
6099
6100 if (!myPasswdInited)
6101 {
6102 InitMyPasswd ();
6103 myPasswdInited = 1;
6104 }
6105
6106 return &myPasswd;
6107 }
6108
6109 /* The functions fork, kill, sigsetmask, sigblock, request_sigio,
6110 setpgrp, setpriority, and unrequest_sigio are defined to be empty
6111 as in msdos.c. */
6112
6113 int
6114 fork ()
6115 {
6116 return -1;
6117 }
6118
6119 int
6120 kill (int x, int y)
6121 {
6122 return -1;
6123 }
6124
6125 int
6126 sigsetmask (int x)
6127 {
6128 return 0;
6129 }
6130
6131 int
6132 sigblock (int mask)
6133 {
6134 return 0;
6135 }
6136
6137 void
6138 request_sigio (void)
6139 {
6140 }
6141
6142 int
6143 setpgrp ()
6144 {
6145 return 0;
6146 }
6147
6148 void
6149 unrequest_sigio (void)
6150 {
6151 }
6152
6153 /* djgpp does not implement pipe either. */
6154 int
6155 pipe (int _fildes[2])
6156 {
6157 errno = EACCES;
6158 return -1;
6159 }
6160
6161 /* Hard and symbolic links. */
6162 int
6163 symlink (const char *name1, const char *name2)
6164 {
6165 errno = ENOENT;
6166 return -1;
6167 }
6168
6169 int
6170 link (const char *name1, const char *name2)
6171 {
6172 errno = ENOENT;
6173 return -1;
6174 }
6175
6176 int
6177 lstat (const char *path, struct stat *sb)
6178 {
6179 return stat (path, sb);
6180 }
6181
6182 int
6183 readlink (const char *path, char *buf, int bufsiz)
6184 {
6185 errno = ENOENT;
6186 return -1;
6187 }
6188
6189 mode_t
6190 umask (mode_t numask)
6191 {
6192 static mode_t mask = 022;
6193 mode_t oldmask = mask;
6194 mask = numask;
6195 return oldmask;
6196 }
6197
6198 int
6199 chmod (const char *path, mode_t mode)
6200 {
6201 /* say it always succeed for now */
6202 return 0;
6203 }
6204
6205 int
6206 dup (int oldd)
6207 {
6208 #ifdef __MRC__
6209 return fcntl (oldd, F_DUPFD, 0);
6210 #elif __MWERKS__
6211 /* current implementation of fcntl in fcntl.mac.c simply returns old
6212 descriptor */
6213 return fcntl (oldd, F_DUPFD);
6214 #else
6215 You lose!!!
6216 #endif
6217 }
6218
6219 /* This is from the original sysdep.c. Emulate BSD dup2. First close
6220 newd if it already exists. Then, attempt to dup oldd. If not
6221 successful, call dup2 recursively until we are, then close the
6222 unsuccessful ones. */
6223 int
6224 dup2 (int oldd, int newd)
6225 {
6226 int fd, ret;
6227
6228 close (newd);
6229
6230 fd = dup (oldd);
6231 if (fd == -1)
6232 return -1;
6233 if (fd == newd)
6234 return newd;
6235 ret = dup2 (oldd, newd);
6236 close (fd);
6237 return ret;
6238 }
6239
6240 /* let it fail for now */
6241 char *
6242 sbrk (int incr)
6243 {
6244 return (char *) -1;
6245 }
6246
6247 int
6248 fsync (int fd)
6249 {
6250 return 0;
6251 }
6252
6253 int
6254 ioctl (int d, int request, void *argp)
6255 {
6256 return -1;
6257 }
6258
6259 #ifdef __MRC__
6260 int
6261 isatty (int fildes)
6262 {
6263 if (fildes >=0 && fildes <= 2)
6264 return 1;
6265 else
6266 return 0;
6267 }
6268
6269 int
6270 getgid ()
6271 {
6272 return 100;
6273 }
6274
6275 int
6276 getegid ()
6277 {
6278 return 100;
6279 }
6280
6281 int
6282 getuid ()
6283 {
6284 return 200;
6285 }
6286
6287 int
6288 geteuid ()
6289 {
6290 return 200;
6291 }
6292
6293 unsigned int
6294 sleep (unsigned int seconds)
6295 {
6296 unsigned long finalTick;
6297
6298 Delay (seconds * 60UL, &finalTick);
6299 return (0);
6300 }
6301 #endif /* __MRC__ */
6302
6303 #ifdef __MWERKS__
6304 #undef getpid
6305 int
6306 getpid ()
6307 {
6308 return 9999;
6309 }
6310 #endif /* __MWERKS__ */
6311
6312 /* Return the path to the directory in which Emacs can create
6313 temporary files. The MacOS "temporary items" directory cannot be
6314 used because it removes the file written by a process when it
6315 exits. In that sense it's more like "/dev/null" than "/tmp" (but
6316 again not exactly). And of course Emacs needs to read back the
6317 files written by its subprocesses. So here we write the files to a
6318 directory "Emacs" in the Preferences Folder. This directory is
6319 created if it does not exist. */
6320 static char *
6321 GetTempDirName ()
6322 {
6323 static char *TempDirName = NULL;
6324 short vRefNum;
6325 long dirID;
6326 OSErr err;
6327 Str255 dirName, fullPath;
6328 CInfoPBRec cpb;
6329 char unixDirName[MAXPATHLEN+1];
6330 DIR *dir;
6331
6332 /* Cache directory name with pointer TempDirName.
6333 Look for it only the first time. */
6334 if (!TempDirName)
6335 {
6336 err = FindFolder (kOnSystemDisk, kPreferencesFolderType,
6337 kCreateFolder, &vRefNum, &dirID);
6338 if (err != noErr)
6339 return NULL;
6340
6341 *fullPath = '\0';
6342 cpb.dirInfo.ioNamePtr = dirName;
6343 cpb.dirInfo.ioDrParID = dirID;
6344
6345 /* Standard ref num to full path name loop */
6346 do {
6347 cpb.dirInfo.ioVRefNum = vRefNum;
6348 cpb.dirInfo.ioFDirIndex = -1;
6349 cpb.dirInfo.ioDrDirID = cpb.dirInfo.ioDrParID;
6350
6351 err = PBGetCatInfo (&cpb, false);
6352
6353 p2cstr (dirName);
6354 strcat (dirName, ":");
6355 if (strlen (fullPath) + strlen (dirName) <= MAXPATHLEN)
6356 {
6357 strcat (dirName, fullPath);
6358 strcpy (fullPath, dirName);
6359 }
6360 else
6361 return NULL;
6362 }
6363 while (cpb.dirInfo.ioDrDirID != fsRtDirID && err == noErr);
6364
6365 if (strlen (fullPath) + 6 <= MAXPATHLEN)
6366 strcat (fullPath, "Emacs:");
6367 else
6368 return NULL;
6369
6370 if (Mac2UnixPathname (fullPath, unixDirName, MAXPATHLEN+1) == 0)
6371 return NULL;
6372
6373 dir = opendir (unixDirName); /* check whether temp directory exists */
6374 if (dir)
6375 closedir (dir);
6376 else if (mkdir (unixDirName, 0700) != 0) /* create it if not */
6377 return NULL;
6378
6379 TempDirName = (char *) malloc (strlen (unixDirName) + 1);
6380 strcpy (TempDirName, unixDirName);
6381 }
6382
6383 return TempDirName;
6384 }
6385
6386 char *
6387 getenv (const char * name)
6388 {
6389 if (strcmp (name, "TERM") == 0)
6390 return "vt100";
6391 else if (strcmp (name, "TERMCAP") == 0)
6392 /* for debugging purpose when code was still outputting to dumb terminal */
6393 return "d0|vt100|vt100-am|vt100am|dec vt100:do=[do]:co#100:li#32:cl=[cl]:sf=[sf]:km:\
6394 :le=[le]:bs:am:cm=[cm-%d,%d]:nd=[nd]:up=[up]:ce=[ce]:cd=[cd]:so=[so]:se=[se]:\
6395 :us=[us]:ue=[ue]:md=[md]:mr=[mr]:mb=[mb]:me=[me]:is=[is]:\
6396 :rf=/usr/share/lib/tabset/vt100:rs=[rs]:ks=[ks]:ke=[ke]:\
6397 :ku=\\036:kd=\\037:kr=\\035:kl=\\034:kb=[kb]:ho=[ho]:k1=[k1]:k2=[k2]:k3=[k3]:k4=[k4]:\
6398 :pt:sr=[sr]:vt#3:xn:sc=[sc]:rc=[rc]:cs=[cs-%d,%d]";
6399 else if (strcmp (name, "TMPDIR") == 0)
6400 return GetTempDirName ();
6401 else
6402 return (NULL);
6403 }
6404
6405 #ifdef __MRC__
6406 /* see Interfaces&Libraries:Interfaces:CIncludes:signal.h */
6407 char *sys_siglist[] =
6408 {
6409 "Zero is not a signal!!!",
6410 "Abort", /* 1 */
6411 "Interactive user interrupt", /* 2 */ "BAD",
6412 "Floating point exception", /* 4 */ "BAD", "BAD", "BAD",
6413 "Illegal instruction", /* 8 */ "BAD", "BAD", "BAD", "BAD", "BAD", "BAD", "BAD",
6414 "Segment violation", /* 16 */ "BAD", "BAD", "BAD", "BAD", "BAD", "BAD", "BAD", "BAD", "BAD", "BAD", "BAD", "BAD", "BAD", "BAD", "BAD",
6415 "Terminal" /* 32 */
6416 };
6417 #elif __MWERKS__
6418 char *sys_siglist[] =
6419 {
6420 "Zero is not a signal!!!",
6421 "Abort",
6422 "Floating point exception",
6423 "Illegal instruction",
6424 "Interactive user interrupt",
6425 "Segment violation",
6426 "Terminal"
6427 };
6428 #else
6429 You lose!!!
6430 #endif
6431
6432 #ifdef __MRC__
6433 #include <utsname.h>
6434
6435 int
6436 uname (struct utsname *name)
6437 {
6438 char **systemName;
6439 systemName = GetString (-16413); /* IM - Resource Manager Reference */
6440 if (systemName)
6441 {
6442 BlockMove (*systemName, name->nodename, (*systemName)[0]+1);
6443 p2cstr (name->nodename);
6444 }
6445 else
6446 return -1;
6447 }
6448 #endif
6449
6450 #include <Processes.h>
6451 #include <EPPC.h>
6452
6453 /* Event class of HLE sent to subprocess. */
6454 const OSType kEmacsSubprocessSend = 'ESND';
6455 /* Event class of HLE sent back from subprocess. */
6456 const OSType kEmacsSubprocessReply = 'ERPY';
6457
6458 char *
6459 mystrchr (char *s, char c)
6460 {
6461 while (*s && *s != c)
6462 {
6463 if (*s == '\\')
6464 s++;
6465 s++;
6466 }
6467
6468 if (*s)
6469 {
6470 *s = '\0';
6471 return s;
6472 }
6473 else
6474 return NULL;
6475 }
6476
6477 char *
6478 mystrtok (char *s)
6479 {
6480 while (*s)
6481 s++;
6482
6483 return s + 1;
6484 }
6485
6486 void
6487 mystrcpy (char *to, char *from)
6488 {
6489 while (*from)
6490 {
6491 if (*from == '\\')
6492 from++;
6493 *to++ = *from++;
6494 }
6495 *to = '\0';
6496 }
6497
6498 /* Start a Mac subprocess. Arguments for it is passed in argv (null
6499 terminated). The process should run with the default directory
6500 "workdir", read input from "infn", and write output and error to
6501 "outfn" and "errfn", resp. The Process Manager call
6502 LaunchApplication is used to start the subprocess. We use high
6503 level events as the mechanism to pass arguments to the subprocess
6504 and to make Emacs wait for the subprocess to terminate and pass
6505 back a result code. The bulk of the code here packs the arguments
6506 into one message to be passed together with the high level event.
6507 Emacs also sometimes starts a subprocess using a shell to perform
6508 wildcard filename expansion. Since we don't really have a shell on
6509 the Mac, this case is detected and the starting of the shell is
6510 by-passed. We really need to add code here to do filename
6511 expansion to support such functionality. */
6512 int
6513 run_mac_command (argv, workdir, infn, outfn, errfn)
6514 unsigned char **argv;
6515 const char *workdir;
6516 const char *infn, *outfn, errfn;
6517 {
6518 char macappname[MAXPATHLEN+1], macworkdir[MAXPATHLEN+1];
6519 char macinfn[MAXPATHLEN+1], macoutfn[MAXPATHLEN+1], macerrfn[MAXPATHLEN+1];
6520 int paramlen, argc, newargc, j, retries;
6521 char **newargv, *param, *p;
6522 OSErr iErr;
6523 FSSpec spec;
6524 LaunchParamBlockRec lpbr;
6525 EventRecord sendEvent, replyEvent;
6526 RgnHandle cursorRegionHdl;
6527 TargetID targ;
6528 unsigned long refCon, len;
6529
6530 if (Unix2MacPathname (workdir, macworkdir, MAXPATHLEN+1) == 0)
6531 return -1;
6532 if (Unix2MacPathname (infn, macinfn, MAXPATHLEN+1) == 0)
6533 return -1;
6534 if (Unix2MacPathname (outfn, macoutfn, MAXPATHLEN+1) == 0)
6535 return -1;
6536 if (Unix2MacPathname (errfn, macerrfn, MAXPATHLEN+1) == 0)
6537 return -1;
6538
6539 paramlen = strlen (macworkdir) + strlen (macinfn) + strlen (macoutfn) + strlen (macerrfn) + 4;
6540 /* count nulls at end of strings */
6541
6542 argc = 0;
6543 while (argv[argc])
6544 argc++;
6545
6546 if (argc == 0)
6547 return -1;
6548
6549 /* If a subprocess is invoked with a shell, we receive 3 arguments of the form:
6550 "<path to emacs bins>/sh" "-c" "<path to emacs bins>/<command> <command args>" */
6551 j = strlen (argv[0]);
6552 if (j >= 3 && strcmp (argv[0]+j-3, "/sh") == 0 && argc == 3 && strcmp (argv[1], "-c") == 0)
6553 {
6554 char *command, *t, tempmacpathname[MAXPATHLEN+1];
6555
6556 /* The arguments for the command in argv[2] are separated by spaces. Count them and put
6557 the count in newargc. */
6558 command = (char *) alloca (strlen (argv[2])+2);
6559 strcpy (command, argv[2]);
6560 if (command[strlen (command) - 1] != ' ')
6561 strcat (command, " ");
6562
6563 t = command;
6564 newargc = 0;
6565 t = mystrchr (t, ' ');
6566 while (t)
6567 {
6568 newargc++;
6569 t = mystrchr (t+1, ' ');
6570 }
6571
6572 newargv = (char **) alloca (sizeof (char *) * newargc);
6573
6574 t = command;
6575 for (j = 0; j < newargc; j++)
6576 {
6577 newargv[j] = (char *) alloca (strlen (t) + 1);
6578 mystrcpy (newargv[j], t);
6579
6580 t = mystrtok (t);
6581 paramlen += strlen (newargv[j]) + 1;
6582 }
6583
6584 if (strncmp (newargv[0], "~emacs/", 7) == 0)
6585 {
6586 if (Unix2MacPathname (newargv[0], tempmacpathname, MAXPATHLEN+1) == 0)
6587 return -1;
6588 }
6589 else
6590 { /* sometimes Emacs call "sh" without a path for the command */
6591 #if 0
6592 char *t = (char *) alloca (strlen (newargv[0]) + 7 + 1);
6593 strcpy (t, "~emacs/");
6594 strcat (t, newargv[0]);
6595 #endif
6596 Lisp_Object path;
6597 openp (Vexec_path, build_string (newargv[0]), EXEC_SUFFIXES, &path, 1);
6598
6599 if (NILP (path))
6600 return -1;
6601 if (Unix2MacPathname (XSTRING (path)->data, tempmacpathname, MAXPATHLEN+1) == 0)
6602 return -1;
6603 }
6604 strcpy (macappname, tempmacpathname);
6605 }
6606 else
6607 {
6608 if (Unix2MacPathname (argv[0], macappname, MAXPATHLEN+1) == 0)
6609 return -1;
6610
6611 newargv = (char **) alloca (sizeof (char *) * argc);
6612 newargc = argc;
6613 for (j = 1; j < argc; j++)
6614 {
6615 if (strncmp (argv[j], "~emacs/", 7) == 0)
6616 {
6617 char *t = strchr (argv[j], ' ');
6618 if (t)
6619 {
6620 char tempcmdname[MAXPATHLEN+1], tempmaccmdname[MAXPATHLEN+1];
6621 strncpy (tempcmdname, argv[j], t-argv[j]);
6622 tempcmdname[t-argv[j]] = '\0';
6623 if (Unix2MacPathname (tempcmdname, tempmaccmdname, MAXPATHLEN+1) == 0)
6624 return -1;
6625 newargv[j] = (char *) alloca (strlen (tempmaccmdname) + strlen (t) + 1);
6626 strcpy (newargv[j], tempmaccmdname);
6627 strcat (newargv[j], t);
6628 }
6629 else
6630 {
6631 char tempmaccmdname[MAXPATHLEN+1];
6632 if (Unix2MacPathname (argv[j], tempmaccmdname, MAXPATHLEN+1) == 0)
6633 return -1;
6634 newargv[j] = (char *) alloca (strlen (tempmaccmdname)+1);
6635 strcpy (newargv[j], tempmaccmdname);
6636 }
6637 }
6638 else
6639 newargv[j] = argv[j];
6640 paramlen += strlen (newargv[j]) + 1;
6641 }
6642 }
6643
6644 /* After expanding all the arguments, we now know the length of the parameter block to be
6645 sent to the subprocess as a message attached to the HLE. */
6646 param = (char *) malloc (paramlen + 1);
6647 if (!param)
6648 return -1;
6649
6650 p = param;
6651 *p++ = newargc; /* first byte of message contains number of arguments for command */
6652 strcpy (p, macworkdir);
6653 p += strlen (macworkdir);
6654 *p++ = '\0'; /* null terminate strings sent so it's possible to use strcpy over there */
6655 strcpy (p, macinfn);
6656 p += strlen (macinfn);
6657 *p++ = '\0';
6658 strcpy (p, macoutfn);
6659 p += strlen (macoutfn);
6660 *p++ = '\0';
6661 strcpy (p, macerrfn);
6662 p += strlen (macerrfn);
6663 *p++ = '\0';
6664 for (j = 1; j < newargc; j++) {
6665 strcpy (p, newargv[j]);
6666 p += strlen (newargv[j]);
6667 *p++ = '\0';
6668 }
6669
6670 c2pstr (macappname);
6671
6672 iErr = FSMakeFSSpec (0, 0, macappname, &spec);
6673
6674 if (iErr != noErr) {
6675 free (param);
6676 return -1;
6677 }
6678
6679 lpbr.launchBlockID = extendedBlock;
6680 lpbr.launchEPBLength = extendedBlockLen;
6681 lpbr.launchControlFlags = launchContinue + launchNoFileFlags;
6682 lpbr.launchAppSpec = &spec;
6683 lpbr.launchAppParameters = NULL;
6684
6685 iErr = LaunchApplication (&lpbr); /* call the subprocess */
6686 if (iErr != noErr) {
6687 free (param);
6688 return -1;
6689 }
6690
6691 sendEvent.what = kHighLevelEvent;
6692 sendEvent.message = kEmacsSubprocessSend; /* Event ID stored in "where" unused */
6693
6694 retries = 3;
6695 do { /* OS may think current subprocess has terminated if previous one terminated recently */
6696 iErr = PostHighLevelEvent (&sendEvent, &lpbr.launchProcessSN, 0, param, paramlen + 1, receiverIDisPSN);
6697 }
6698 while (iErr == sessClosedErr && retries-- > 0);
6699
6700 if (iErr != noErr) {
6701 free (param);
6702 return -1;
6703 }
6704
6705 cursorRegionHdl = NewRgn ();
6706
6707 /* Wait for the subprocess to finish, when it will send us a ERPY high level event */
6708 while (1)
6709 if (WaitNextEvent (highLevelEventMask, &replyEvent, 180, cursorRegionHdl) && replyEvent.message == kEmacsSubprocessReply)
6710 break;
6711
6712 /* The return code is sent through the refCon */
6713 iErr = AcceptHighLevelEvent (&targ, &refCon, NULL, &len);
6714 if (iErr != noErr) {
6715 DisposeHandle ((Handle) cursorRegionHdl);
6716 free (param);
6717 return -1;
6718 }
6719
6720 DisposeHandle ((Handle) cursorRegionHdl);
6721 free (param);
6722
6723 return refCon;
6724 }
6725
6726 DIR *
6727 opendir (const char *dirname)
6728 {
6729 char MacPathname[MAXPATHLEN+1];
6730 DIR *dirp;
6731 CInfoPBRec cipb;
6732 int len;
6733
6734 dirp = (DIR *) malloc (sizeof (DIR));
6735 if (!dirp)
6736 return 0;
6737
6738 /* Handle special case when dirname is "/": sets up for readir to
6739 get all mount volumes. */
6740 if (strcmp (dirname, "/") == 0) {
6741 dirp->getting_volumes = 1; /* special all mounted volumes DIR struct */
6742 dirp->current_index = 1; /* index for first volume */
6743 return dirp;
6744 }
6745
6746 /* Handle typical cases: not accessing all mounted volumes. */
6747 if (Unix2MacPathname (dirname, MacPathname, MAXPATHLEN+1) == 0)
6748 return 0;
6749
6750 /* Emacs calls opendir without the trailing '/', Mac needs trailing ':' */
6751 len = strlen (MacPathname);
6752 if (MacPathname[len - 1] != ':' && len < MAXPATHLEN)
6753 strcat (MacPathname, ":");
6754
6755 c2pstr (MacPathname);
6756 cipb.hFileInfo.ioNamePtr = MacPathname; /* using full pathname so vRefNum and dirID ignored */
6757 cipb.hFileInfo.ioVRefNum = 0;
6758 cipb.hFileInfo.ioDirID = 0;
6759 cipb.hFileInfo.ioFDirIndex = 0; /* set to 0 to get information about specific dir or file */
6760
6761 errno = PBGetCatInfo (&cipb, false);
6762 if (errno != noErr) {
6763 errno = ENOENT;
6764 return 0;
6765 }
6766
6767 if (!(cipb.hFileInfo.ioFlAttrib & 0x10)) /* bit 4 = 1 for directories */
6768 return 0; /* not a directory */
6769
6770 dirp->dir_id = cipb.dirInfo.ioDrDirID; /* used later in readdir */
6771 dirp->getting_volumes = 0;
6772 dirp->current_index = 1; /* index for first file/directory */
6773
6774 return dirp;
6775 }
6776
6777 int
6778 closedir (DIR *dp)
6779 {
6780 free (dp);
6781
6782 return 0;
6783 }
6784
6785 struct dirent *
6786 readdir (DIR *dp)
6787 {
6788 HParamBlockRec HPBlock;
6789 CInfoPBRec cipb;
6790 static struct dirent s_dirent;
6791 static Str255 s_name;
6792 int done;
6793
6794 /* Handle the root directory containing the mounted volumes. Call
6795 PBHGetVInfo specifying an index to obtain the info for a volume.
6796 PBHGetVInfo returns an error when it receives an index beyond the
6797 last volume, at which time we should return a nil dirent struct
6798 pointer. */
6799 if (dp->getting_volumes) {
6800 HPBlock.volumeParam.ioNamePtr = s_name;
6801 HPBlock.volumeParam.ioVRefNum = 0;
6802 HPBlock.volumeParam.ioVolIndex = dp->current_index;
6803
6804 errno = PBHGetVInfo (&HPBlock, false);
6805 if (errno != noErr) {
6806 errno = ENOENT;
6807 return 0;
6808 }
6809
6810 p2cstr (s_name);
6811 strcat (s_name, "/"); /* need "/" for stat to work correctly */
6812
6813 dp->current_index++;
6814
6815 s_dirent.d_ino = cipb.dirInfo.ioDrDirID;
6816 s_dirent.d_name = s_name;
6817
6818 return &s_dirent;
6819 }
6820 else {
6821 cipb.hFileInfo.ioVRefNum = 0;
6822 cipb.hFileInfo.ioNamePtr = s_name; /* location to receive filename returned */
6823
6824 /* return only visible files */
6825 done = false;
6826 while (!done) {
6827 cipb.hFileInfo.ioDirID = dp->dir_id; /* directory ID found by opendir */
6828 cipb.hFileInfo.ioFDirIndex = dp->current_index;
6829
6830 errno = PBGetCatInfo (&cipb, false);
6831 if (errno != noErr) {
6832 errno = ENOENT;
6833 return 0;
6834 }
6835
6836 /* insist on an visibile entry */
6837 if (cipb.hFileInfo.ioFlAttrib & 0x10) /* directory? */
6838 done = !(cipb.dirInfo.ioDrUsrWds.frFlags & fInvisible);
6839 else
6840 done = !(cipb.hFileInfo.ioFlFndrInfo.fdFlags & fInvisible);
6841
6842 dp->current_index++;
6843 }
6844
6845 p2cstr (s_name);
6846
6847 s_dirent.d_ino = cipb.dirInfo.ioDrDirID; /* value unimportant: non-zero for valid file */
6848 s_dirent.d_name = s_name;
6849
6850 return &s_dirent;
6851 }
6852 }
6853
6854 char *
6855 getwd (char *path)
6856 {
6857 char MacPathname[MAXPATHLEN+1];
6858 Str255 directoryName;
6859 OSErr errno;
6860 CInfoPBRec cipb;
6861
6862 MacPathname[0] = '\0';
6863 directoryName[0] = '\0';
6864 cipb.dirInfo.ioDrParID = 0;
6865 cipb.dirInfo.ioNamePtr = directoryName; /* empty string = default directory */
6866
6867 do {
6868 cipb.dirInfo.ioVRefNum = 0;
6869 cipb.dirInfo.ioFDirIndex = -1;
6870 cipb.dirInfo.ioDrDirID = cipb.dirInfo.ioDrParID; /* go up to parent each time */
6871
6872 errno = PBGetCatInfo (&cipb, false);
6873 if (errno != noErr) {
6874 errno = ENOENT;
6875 return 0;
6876 }
6877
6878 p2cstr (directoryName);
6879 strcat (directoryName, ":");
6880 strcat (directoryName, MacPathname); /* attach to front since going up directory tree */
6881 strcpy (MacPathname, directoryName);
6882 } while (cipb.dirInfo.ioDrDirID != fsRtDirID); /* until volume's root directory */
6883
6884 if (Mac2UnixPathname (MacPathname, path, MAXPATHLEN+1) == 0)
6885 return 0;
6886 else
6887 return path;
6888 }
6889
6890 #endif /* macintosh */