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