Mercurial > emacs
annotate src/sysdep.c @ 1687:2bee660c3046
* configure: Don't make the top-level Makefile read-only - people
may want to edit the values of the path variables.
Make path specification conform to GNU coding standards.
* configure (long_usage): Remove all traces of old arguments from
usage messages, and document the options we do accept in more
detail: -with-x... and --srcdir.
(options, boolean_opts): Deleted; we don't have enough options to
make this worthwhile.
(prefix, bindir, lisppath, datadir, libdir, lockdir): Deleted,
along with the code which supported them; these should be set as
arguments to the top-level make.
(config_h_opts): Since this no longer doubles as a list of option
names, make them upper case; this simplifies the code which uses
them to build the sed command to edit src/config.h. Change the
code which sets them.
(cc, g, O): Don't allow the user to set these using options; they
should be specified using `CC=' and `CFLAGS=' arguments to the
top-level make. Just choose reasonable default values for them,
and edit them into Makefile.in's default CC and CONFIG_CFLAGS
values.
(gnu_malloc, rel_alloc): Don't allow the user to set these using
options; use them whenever the configuration files say they're
possible.
Simplify the argument processing loop. Don't accept abbreviations
for option names; these might conflict with other configuration
options in the future.
Add some support for the `--srcdir' option. Check for the sources
in . and .. if `--srcdir' is omitted. If the directories we will
compile in don't exist yet, create them under the current directory.
Note that the rest of the build process doesn't really support
this.
Edit only the top Makefile. That should edit the others. Edit
into the makefile: `version', from lisp/version.el, `configname'
and `srcdir' from the configuration arguments, `CC' and
`CONFIG_CFLAGS' as guessed from the presence or absence of GCC in
the user's path, and LOADLIBES as gleaned from the system
description files.
Simplify the report generated; it doesn't need to include any
description of paths now.
Make `config.status' exec configure instead of just calling it, so
there's no harm in overwriting `config.status'.
* Makefile.in (version, configname): New variables, used to choose
the default values for datadir and libdir.
Path variables rearranged into two clearer groups:
- In the first group are the variables specified by the GNU coding
standards (prefix, bindir, datadir, statedir, libdir, mandir,
manext, infodir, and srcdir).
- In the second are the variables actually used for Emacs's paths
(lispdir, locallisppath, lisppath, buildlisppath, etcdir, lockdir,
archlibdir), which depend on the first category.
datadir and libdir default to directories under
${prefix}/lib/emacs instead of ${prefix}/emacs, by popular
demand.
etcdir and lispdir default to subdirectories of datadir.
archlibdir defaults to libdir.
The new installation tree is a bit deeper than it used to be, so
use the new make-path program in lib-src to build them all.
Always build a new src/paths.h.tmp and then move-if-change it to
src/paths.h, to avoid unnecessary rebuilds while responding to the
right changes.
Remove all mention of arch-lib. Run utility commands from
lib-src, and let the executables be copied into archlibdir when
Emacs is installed.
Add targets for src/Makefile, lib-src/Makefile, and
oldXMenu/Makefile, editing the values of the path variables into
them.
Let lib-src do its own installation.
(datadir): Default to putting data files under
${prefix}/lib/emacs/${version}, not /usr/local/emacs.
(emacsdir): Variable deleted; it would only be confusing to use.
(lispdir, etcdir): Default to ${datadir}/lisp.
(mkdir): Use make-path for this.
(lockdir): Do this in mkdir.
(Makefile): New target.
* configure (usage_message): Rename to long_usage.
author | Jim Blandy <jimb@redhat.com> |
---|---|
date | Sat, 12 Dec 1992 15:42:53 +0000 |
parents | 0e105bd23f44 |
children | c6dc1a37aeb4 |
rev | line source |
---|---|
491 | 1 /* Interfaces to system-dependent kernel and library entries. |
579 | 2 Copyright (C) 1985, 1986, 1987, 1988, 1992 Free Software Foundation, Inc. |
491 | 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 1, 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, 675 Mass Ave, Cambridge, MA 02139, USA. */ | |
19 | |
20 | |
21 #include <signal.h> | |
22 #include <setjmp.h> | |
23 | |
24 #include "config.h" | |
25 #include "lisp.h" | |
26 #undef NULL | |
27 | |
28 #define min(x,y) ((x) > (y) ? (y) : (x)) | |
29 | |
30 /* In this file, open, read and write refer to the system calls, | |
31 not our sugared interfaces sys_open, sys_read and sys_write. | |
32 Contrariwise, for systems where we use the system calls directly, | |
33 define sys_read, etc. here as aliases for them. */ | |
34 #ifndef read | |
35 #define sys_read read | |
36 #define sys_write write | |
37 #endif /* `read' is not a macro */ | |
38 | |
39 #undef read | |
40 #undef write | |
41 | |
42 #ifndef close | |
43 #define sys_close close | |
44 #else | |
45 #undef close | |
46 #endif | |
47 | |
48 #ifndef open | |
49 #define sys_open open | |
50 #else /* `open' is a macro */ | |
51 #undef open | |
52 #endif /* `open' is a macro */ | |
53 | |
1596
0e105bd23f44
* systty.h, process.c, buffer.h, callproc.c, sysdep.c, dired.c:
Jim Blandy <jimb@redhat.com>
parents:
1570
diff
changeset
|
54 /* Does anyone other than VMS need this? */ |
0e105bd23f44
* systty.h, process.c, buffer.h, callproc.c, sysdep.c, dired.c:
Jim Blandy <jimb@redhat.com>
parents:
1570
diff
changeset
|
55 #ifndef fwrite |
0e105bd23f44
* systty.h, process.c, buffer.h, callproc.c, sysdep.c, dired.c:
Jim Blandy <jimb@redhat.com>
parents:
1570
diff
changeset
|
56 #define sys_fwrite fwrite |
0e105bd23f44
* systty.h, process.c, buffer.h, callproc.c, sysdep.c, dired.c:
Jim Blandy <jimb@redhat.com>
parents:
1570
diff
changeset
|
57 #else |
0e105bd23f44
* systty.h, process.c, buffer.h, callproc.c, sysdep.c, dired.c:
Jim Blandy <jimb@redhat.com>
parents:
1570
diff
changeset
|
58 #undef fwrite |
0e105bd23f44
* systty.h, process.c, buffer.h, callproc.c, sysdep.c, dired.c:
Jim Blandy <jimb@redhat.com>
parents:
1570
diff
changeset
|
59 #endif |
0e105bd23f44
* systty.h, process.c, buffer.h, callproc.c, sysdep.c, dired.c:
Jim Blandy <jimb@redhat.com>
parents:
1570
diff
changeset
|
60 |
491 | 61 #include <stdio.h> |
62 #include <sys/types.h> | |
63 #include <sys/stat.h> | |
64 #include <errno.h> | |
65 | |
66 extern int errno; | |
67 #ifndef VMS | |
68 extern char *sys_errlist[]; | |
69 #endif | |
70 | |
71 #ifdef VMS | |
72 #include <rms.h> | |
73 #include <ttdef.h> | |
74 #include <tt2def.h> | |
75 #include <iodef.h> | |
76 #include <ssdef.h> | |
77 #include <descrip.h> | |
78 #include <fibdef.h> | |
79 #include <atrdef.h> | |
80 #include <ctype.h> | |
81 #include <string.h> | |
82 #ifdef __GNUC__ | |
83 #include <sys/file.h> | |
84 #else | |
85 #include <file.h> | |
86 #endif | |
87 #undef F_SETFL | |
88 #ifndef RAB$C_BID | |
89 #include <rab.h> | |
90 #endif | |
91 #define MAXIOSIZE ( 32 * PAGESIZE ) /* Don't I/O more than 32 blocks at a time */ | |
92 #endif /* VMS */ | |
93 | |
94 #ifndef BSD4_1 | |
95 #ifdef BSD /* this is done this way to avoid defined (BSD) || defined (USG) | |
96 because the vms compiler doesn't grok `defined' */ | |
97 #include <fcntl.h> | |
98 #endif | |
99 #ifdef USG | |
1014
6e25f9b75841
* sysdep.c (select): There's no need to cast the return value of
Jim Blandy <jimb@redhat.com>
parents:
766
diff
changeset
|
100 #ifndef USG5 |
491 | 101 #include <fcntl.h> |
102 #endif | |
1014
6e25f9b75841
* sysdep.c (select): There's no need to cast the return value of
Jim Blandy <jimb@redhat.com>
parents:
766
diff
changeset
|
103 #endif |
491 | 104 #endif /* not 4.1 bsd */ |
105 | |
106 /* Get DGUX definition for FASYNC - DJB */ | |
107 #ifdef DGUX | |
108 #include <sys/file.h> | |
109 #endif /* DGUX */ | |
110 | |
111 #include <sys/ioctl.h> | |
1048
9899cb2199af
* sysdep.c (init_baud_rate): Re-arranged order of conditionals -
Jim Blandy <jimb@redhat.com>
parents:
1014
diff
changeset
|
112 #include "systty.h" |
491 | 113 |
114 #ifdef BSD | |
115 #ifdef BSD4_1 | |
116 #include <wait.h> | |
117 #else /* not 4.1 */ | |
118 #include <sys/wait.h> | |
119 #endif /* not 4.1 */ | |
120 #endif /* BSD */ | |
121 | |
122 #ifdef BROKEN_TIOCGWINSZ | |
123 #undef TIOCGWINSZ | |
124 #endif | |
125 | |
126 #ifdef USG | |
127 #include <sys/utsname.h> | |
128 #include <string.h> | |
129 #ifndef MEMORY_IN_STRING_H | |
130 #include <memory.h> | |
131 #endif | |
132 #ifdef TIOCGWINSZ | |
133 #ifdef NEED_SIOCTL | |
134 #include <sys/sioctl.h> | |
135 #endif | |
136 #ifdef NEED_PTEM_H | |
137 #include <sys/stream.h> | |
138 #include <sys/ptem.h> | |
139 #endif | |
140 #endif /* TIOCGWINSZ */ | |
141 #endif /* USG */ | |
142 | |
143 extern int quit_char; | |
144 | |
766 | 145 #include "frame.h" |
491 | 146 #include "window.h" |
147 #include "termhooks.h" | |
148 #include "termchar.h" | |
149 #include "termopts.h" | |
150 #include "dispextern.h" | |
151 #include "process.h" | |
152 | |
153 #ifdef NONSYSTEM_DIR_LIBRARY | |
154 #include "ndir.h" | |
155 #endif /* NONSYSTEM_DIR_LIBRARY */ | |
156 | |
579 | 157 #include "syssignal.h" |
158 #include "systime.h" | |
491 | 159 |
160 static int baud_convert[] = | |
161 #ifdef BAUD_CONVERT | |
162 BAUD_CONVERT; | |
163 #else | |
164 { | |
165 0, 50, 75, 110, 135, 150, 200, 300, 600, 1200, | |
166 1800, 2400, 4800, 9600, 19200, 38400 | |
167 }; | |
168 #endif | |
169 | |
170 extern short ospeed; | |
171 | |
579 | 172 /* The file descriptor for Emacs's input terminal. |
173 Under Unix, this is always left zero; | |
174 under VMS, we place the input channel number here. | |
175 This allows us to write more code that works for both VMS and Unix. */ | |
176 static int input_fd; | |
177 | |
491 | 178 discard_tty_input () |
179 { | |
579 | 180 struct emacs_tty buf; |
491 | 181 |
182 if (noninteractive) | |
183 return; | |
184 | |
185 /* Discarding input is not safe when the input could contain | |
186 replies from the X server. So don't do it. */ | |
187 if (read_socket_hook) | |
188 return; | |
189 | |
190 #ifdef VMS | |
191 end_kbd_input (); | |
579 | 192 SYS$QIOW (0, input_fd, IO$_READVBLK|IO$M_PURGE, input_iosb, 0, 0, |
193 &buf.main, 0, 0, terminator_mask, 0, 0); | |
491 | 194 queue_kbd_input (); |
195 #else /* not VMS */ | |
196 #ifdef APOLLO | |
197 { | |
198 int zero = 0; | |
199 ioctl (0, TIOCFLUSH, &zero); | |
200 } | |
201 #else /* not Apollo */ | |
579 | 202 EMACS_GET_TTY (input_fd, &buf); |
203 EMACS_SET_TTY (input_fd, &buf, 0); | |
491 | 204 #endif /* not Apollo */ |
205 #endif /* not VMS */ | |
206 } | |
207 | |
208 #ifdef SIGTSTP | |
209 | |
210 stuff_char (c) | |
211 char c; | |
212 { | |
213 /* Should perhaps error if in batch mode */ | |
214 #ifdef TIOCSTI | |
215 ioctl (0, TIOCSTI, &c); | |
216 #else /* no TIOCSTI */ | |
217 error ("Cannot stuff terminal input characters in this version of Unix."); | |
218 #endif /* no TIOCSTI */ | |
219 } | |
220 | |
221 #endif /* SIGTSTP */ | |
222 | |
223 init_baud_rate () | |
224 { | |
225 if (noninteractive) | |
226 ospeed = 0; | |
227 else | |
228 { | |
229 #ifdef VMS | |
579 | 230 struct sensemode sg; |
231 | |
232 SYS$QIOW (0, input_fd, IO$_SENSEMODE, &sg, 0, 0, | |
491 | 233 &sg.class, 12, 0, 0, 0, 0 ); |
579 | 234 ospeed = sg.xmit_baud; |
235 #else /* not VMS */ | |
236 #ifdef HAVE_TERMIOS | |
237 struct termios sg; | |
238 | |
239 sg.c_cflag = (sg.c_cflag & ~CBAUD) | B9600; | |
240 tcgetattr (0, &sg); | |
241 ospeed = sg.c_cflag & CBAUD; | |
1048
9899cb2199af
* sysdep.c (init_baud_rate): Re-arranged order of conditionals -
Jim Blandy <jimb@redhat.com>
parents:
1014
diff
changeset
|
242 #else /* neither VMS nor TERMIOS */ |
9899cb2199af
* sysdep.c (init_baud_rate): Re-arranged order of conditionals -
Jim Blandy <jimb@redhat.com>
parents:
1014
diff
changeset
|
243 #ifdef HAVE_TERMIO |
9899cb2199af
* sysdep.c (init_baud_rate): Re-arranged order of conditionals -
Jim Blandy <jimb@redhat.com>
parents:
1014
diff
changeset
|
244 struct termio sg; |
9899cb2199af
* sysdep.c (init_baud_rate): Re-arranged order of conditionals -
Jim Blandy <jimb@redhat.com>
parents:
1014
diff
changeset
|
245 |
9899cb2199af
* sysdep.c (init_baud_rate): Re-arranged order of conditionals -
Jim Blandy <jimb@redhat.com>
parents:
1014
diff
changeset
|
246 sg.c_cflag = (sg.c_cflag & ~CBAUD) | B9600; |
9899cb2199af
* sysdep.c (init_baud_rate): Re-arranged order of conditionals -
Jim Blandy <jimb@redhat.com>
parents:
1014
diff
changeset
|
247 #ifdef HAVE_TCATTR |
9899cb2199af
* sysdep.c (init_baud_rate): Re-arranged order of conditionals -
Jim Blandy <jimb@redhat.com>
parents:
1014
diff
changeset
|
248 tcgetattr (0, &sg); |
9899cb2199af
* sysdep.c (init_baud_rate): Re-arranged order of conditionals -
Jim Blandy <jimb@redhat.com>
parents:
1014
diff
changeset
|
249 #else |
1570
d978f163d9a4
* sysdep.c (init_baud_rate) [HAVE_TERMIO, not HAVE_TCATTR]: Use
Jim Blandy <jimb@redhat.com>
parents:
1496
diff
changeset
|
250 ioctl (fd, TCGETA, &sg); |
1048
9899cb2199af
* sysdep.c (init_baud_rate): Re-arranged order of conditionals -
Jim Blandy <jimb@redhat.com>
parents:
1014
diff
changeset
|
251 #endif |
9899cb2199af
* sysdep.c (init_baud_rate): Re-arranged order of conditionals -
Jim Blandy <jimb@redhat.com>
parents:
1014
diff
changeset
|
252 ospeed = sg.c_cflag & CBAUD; |
9899cb2199af
* sysdep.c (init_baud_rate): Re-arranged order of conditionals -
Jim Blandy <jimb@redhat.com>
parents:
1014
diff
changeset
|
253 #else /* neither VMS nor TERMIOS nor TERMIO */ |
579 | 254 struct sgttyb sg; |
255 | |
256 sg.sg_ospeed = B9600; | |
257 ioctl (0, TIOCGETP, &sg); | |
258 ospeed = sg.sg_ospeed; | |
1048
9899cb2199af
* sysdep.c (init_baud_rate): Re-arranged order of conditionals -
Jim Blandy <jimb@redhat.com>
parents:
1014
diff
changeset
|
259 #endif /* not HAVE_TERMIO */ |
579 | 260 #endif /* not HAVE_TERMIOS */ |
491 | 261 #endif /* not VMS */ |
262 } | |
263 | |
264 baud_rate = (ospeed < sizeof baud_convert / sizeof baud_convert[0] | |
265 ? baud_convert[ospeed] : 9600); | |
266 if (baud_rate == 0) | |
267 baud_rate = 1200; | |
268 } | |
269 | |
270 /*ARGSUSED*/ | |
271 set_exclusive_use (fd) | |
272 int fd; | |
273 { | |
274 #ifdef FIOCLEX | |
275 ioctl (fd, FIOCLEX, 0); | |
276 #endif | |
277 /* Ok to do nothing if this feature does not exist */ | |
278 } | |
279 | |
280 #ifndef subprocesses | |
281 | |
282 wait_without_blocking () | |
283 { | |
284 #ifdef BSD | |
285 wait3 (0, WNOHANG | WUNTRACED, 0); | |
286 #else | |
287 croak ("wait_without_blocking"); | |
288 #endif | |
289 synch_process_alive = 0; | |
290 } | |
291 | |
292 #endif /* not subprocesses */ | |
293 | |
294 int wait_debugging; /* Set nonzero to make following function work under dbx | |
295 (at least for bsd). */ | |
296 | |
297 SIGTYPE | |
298 wait_for_termination_signal () | |
299 {} | |
300 | |
301 /* Wait for subprocess with process id `pid' to terminate and | |
302 make sure it will get eliminated (not remain forever as a zombie) */ | |
303 | |
304 wait_for_termination (pid) | |
305 int pid; | |
306 { | |
307 while (1) | |
308 { | |
309 #ifdef subprocesses | |
310 #ifdef VMS | |
311 int status; | |
312 | |
1596
0e105bd23f44
* systty.h, process.c, buffer.h, callproc.c, sysdep.c, dired.c:
Jim Blandy <jimb@redhat.com>
parents:
1570
diff
changeset
|
313 status = SYS$FORCEX (&pid, 0, 0); |
491 | 314 break; |
315 #else /* not VMS */ | |
316 | |
317 /* Exit if the process has terminated. */ | |
318 if (!synch_process_alive) | |
319 break; | |
320 /* Otherwise wait 1 second or until a signal comes in. */ | |
321 signal (SIGALRM, wait_for_termination_signal); | |
322 alarm (1); | |
323 pause (); | |
324 alarm (0); | |
325 signal (SIGALRM, SIG_IGN); | |
326 #endif /* not VMS */ | |
327 #else /* not subprocesses */ | |
328 #ifndef BSD4_1 | |
329 if (kill (pid, 0) < 0) | |
330 break; | |
331 wait (0); | |
332 #else /* BSD4_1 */ | |
333 int status; | |
334 status = wait (0); | |
335 if (status == pid || status == -1) | |
336 break; | |
337 #endif /* BSD4_1 */ | |
338 #endif /* not subprocesses */ | |
339 } | |
340 } | |
341 | |
342 #ifdef subprocesses | |
343 | |
344 /* | |
345 * flush any pending output | |
346 * (may flush input as well; it does not matter the way we use it) | |
347 */ | |
348 | |
349 flush_pending_output (channel) | |
350 int channel; | |
351 { | |
352 #ifdef HAVE_TERMIOS | |
353 /* If we try this, we get hit with SIGTTIN, because | |
354 the child's tty belongs to the child's pgrp. */ | |
355 #else | |
356 #ifdef TCFLSH | |
357 ioctl (channel, TCFLSH, 1); | |
358 #else | |
359 #ifdef TIOCFLUSH | |
360 int zero = 0; | |
361 /* 3rd arg should be ignored | |
362 but some 4.2 kernels actually want the address of an int | |
363 and nonzero means something different. */ | |
364 ioctl (channel, TIOCFLUSH, &zero); | |
365 #endif | |
366 #endif | |
367 #endif | |
368 } | |
369 | |
370 #ifndef VMS | |
371 /* Set up the terminal at the other end of a pseudo-terminal that | |
372 we will be controlling an inferior through. | |
373 It should not echo or do line-editing, since that is done | |
374 in Emacs. No padding needed for insertion into an Emacs buffer. */ | |
375 | |
376 child_setup_tty (out) | |
377 int out; | |
378 { | |
579 | 379 struct emacs_tty s; |
380 | |
381 EMACS_GET_TTY (out, &s); | |
382 | |
491 | 383 #ifdef HAVE_TERMIO |
579 | 384 s.main.c_oflag |= OPOST; /* Enable output postprocessing */ |
385 s.main.c_oflag &= ~ONLCR; /* Disable map of NL to CR-NL on output */ | |
386 s.main.c_oflag &= ~(NLDLY|CRDLY|TABDLY|BSDLY|VTDLY|FFDLY); | |
387 /* No output delays */ | |
388 s.main.c_lflag &= ~ECHO; /* Disable echo */ | |
389 s.main.c_lflag |= ISIG; /* Enable signals */ | |
390 s.main.c_iflag &= ~IUCLC; /* Disable map of upper case to lower on | |
391 input */ | |
392 s.main.c_oflag &= ~OLCUC; /* Disable map of lower case to upper on | |
393 output */ | |
394 #if 0 | |
395 /* Said to be unnecesary: */ | |
396 s.main.c_cc[VMIN] = 1; /* minimum number of characters to accept */ | |
397 s.main.c_cc[VTIME] = 0; /* wait forever for at least 1 character */ | |
398 #endif | |
399 | |
400 s.main.c_lflag |= ICANON; /* Enable erase/kill and eof processing */ | |
401 s.main.c_cc[VEOF] = 04; /* insure that EOF is Control-D */ | |
402 s.main.c_cc[VERASE] = 0377; /* disable erase processing */ | |
403 s.main.c_cc[VKILL] = 0377; /* disable kill processing */ | |
404 | |
491 | 405 #ifdef HPUX |
579 | 406 s.main.c_cflag = (s.main.c_cflag & ~CBAUD) | B9600; /* baud rate sanity */ |
491 | 407 #endif /* HPUX */ |
579 | 408 |
491 | 409 #ifdef AIX |
410 /* AIX enhanced edit loses NULs, so disable it */ | |
411 #ifndef IBMR2AIX | |
579 | 412 s.main.c_line = 0; |
413 s.main.c_iflag &= ~ASCEDIT; | |
491 | 414 #endif |
415 /* Also, PTY overloads NUL and BREAK. | |
416 don't ignore break, but don't signal either, so it looks like NUL. */ | |
579 | 417 s.main.c_iflag &= ~IGNBRK; |
418 s.main.c_iflag &= ~BRKINT; | |
419 /* QUIT and INTR work better as signals, so disable character forms */ | |
420 s.main.c_cc[VQUIT] = 0377; | |
421 s.main.c_cc[VINTR] = 0377; | |
422 s.main.c_cc[VEOL] = 0377; | |
423 s.main.c_lflag &= ~ISIG; | |
424 s.main.c_cflag = (s.main.c_cflag & ~CBAUD) | B9600; /* baud rate sanity */ | |
491 | 425 #endif /* AIX */ |
426 | |
427 #else /* not HAVE_TERMIO */ | |
579 | 428 |
429 s.main.sg_flags &= ~(ECHO | CRMOD | ANYP | ALLDELAY | RAW | LCASE | |
430 | CBREAK | TANDEM); | |
431 s.main.sg_erase = 0377; | |
432 s.main.sg_kill = 0377; | |
433 | |
491 | 434 #endif /* not HAVE_TERMIO */ |
435 | |
579 | 436 EMACS_SET_TTY (out, &s, 0); |
491 | 437 |
438 #ifdef BSD4_1 | |
439 if (interrupt_input) | |
440 reset_sigio (); | |
441 #endif /* BSD4_1 */ | |
442 #ifdef RTU | |
443 { | |
444 int zero = 0; | |
445 ioctl (out, FIOASYNC, &zero); | |
446 } | |
447 #endif /* RTU */ | |
448 } | |
449 #endif /* not VMS */ | |
450 | |
451 #endif /* subprocesses */ | |
452 | |
453 /*ARGSUSED*/ | |
454 setpgrp_of_tty (pid) | |
455 int pid; | |
456 { | |
648 | 457 EMACS_SET_TTY_PGRP (input_fd, &pid); |
491 | 458 } |
459 | |
460 /* Record a signal code and the handler for it. */ | |
461 struct save_signal | |
462 { | |
463 int code; | |
464 SIGTYPE (*handler) (); | |
465 }; | |
466 | |
467 /* Suspend the Emacs process; give terminal to its superior. */ | |
468 | |
469 sys_suspend () | |
470 { | |
471 #ifdef VMS | |
1171
5c942f6b2d63
(sys_suspend): Read EMACS_PARENT_PID envvar for parent.
Richard M. Stallman <rms@gnu.org>
parents:
1102
diff
changeset
|
472 /* "Foster" parentage allows emacs to return to a subprocess that attached |
5c942f6b2d63
(sys_suspend): Read EMACS_PARENT_PID envvar for parent.
Richard M. Stallman <rms@gnu.org>
parents:
1102
diff
changeset
|
473 to the current emacs as a cheaper than starting a whole new process. This |
5c942f6b2d63
(sys_suspend): Read EMACS_PARENT_PID envvar for parent.
Richard M. Stallman <rms@gnu.org>
parents:
1102
diff
changeset
|
474 is set up by KEPTEDITOR.COM. */ |
5c942f6b2d63
(sys_suspend): Read EMACS_PARENT_PID envvar for parent.
Richard M. Stallman <rms@gnu.org>
parents:
1102
diff
changeset
|
475 unsigned long parent_id, foster_parent_id; |
5c942f6b2d63
(sys_suspend): Read EMACS_PARENT_PID envvar for parent.
Richard M. Stallman <rms@gnu.org>
parents:
1102
diff
changeset
|
476 char *fpid_string; |
5c942f6b2d63
(sys_suspend): Read EMACS_PARENT_PID envvar for parent.
Richard M. Stallman <rms@gnu.org>
parents:
1102
diff
changeset
|
477 |
5c942f6b2d63
(sys_suspend): Read EMACS_PARENT_PID envvar for parent.
Richard M. Stallman <rms@gnu.org>
parents:
1102
diff
changeset
|
478 fpid_string = getenv ("EMACS_PARENT_PID"); |
5c942f6b2d63
(sys_suspend): Read EMACS_PARENT_PID envvar for parent.
Richard M. Stallman <rms@gnu.org>
parents:
1102
diff
changeset
|
479 if (fpid_string != NULL) |
5c942f6b2d63
(sys_suspend): Read EMACS_PARENT_PID envvar for parent.
Richard M. Stallman <rms@gnu.org>
parents:
1102
diff
changeset
|
480 { |
5c942f6b2d63
(sys_suspend): Read EMACS_PARENT_PID envvar for parent.
Richard M. Stallman <rms@gnu.org>
parents:
1102
diff
changeset
|
481 sscanf (fpid_string, "%x", &foster_parent_id); |
5c942f6b2d63
(sys_suspend): Read EMACS_PARENT_PID envvar for parent.
Richard M. Stallman <rms@gnu.org>
parents:
1102
diff
changeset
|
482 if (foster_parent_id != 0) |
5c942f6b2d63
(sys_suspend): Read EMACS_PARENT_PID envvar for parent.
Richard M. Stallman <rms@gnu.org>
parents:
1102
diff
changeset
|
483 parent_id = foster_parent_id; |
5c942f6b2d63
(sys_suspend): Read EMACS_PARENT_PID envvar for parent.
Richard M. Stallman <rms@gnu.org>
parents:
1102
diff
changeset
|
484 else |
5c942f6b2d63
(sys_suspend): Read EMACS_PARENT_PID envvar for parent.
Richard M. Stallman <rms@gnu.org>
parents:
1102
diff
changeset
|
485 parent_id = getppid (); |
5c942f6b2d63
(sys_suspend): Read EMACS_PARENT_PID envvar for parent.
Richard M. Stallman <rms@gnu.org>
parents:
1102
diff
changeset
|
486 } |
5c942f6b2d63
(sys_suspend): Read EMACS_PARENT_PID envvar for parent.
Richard M. Stallman <rms@gnu.org>
parents:
1102
diff
changeset
|
487 else |
5c942f6b2d63
(sys_suspend): Read EMACS_PARENT_PID envvar for parent.
Richard M. Stallman <rms@gnu.org>
parents:
1102
diff
changeset
|
488 parent_id = getppid (); |
5c942f6b2d63
(sys_suspend): Read EMACS_PARENT_PID envvar for parent.
Richard M. Stallman <rms@gnu.org>
parents:
1102
diff
changeset
|
489 |
5c942f6b2d63
(sys_suspend): Read EMACS_PARENT_PID envvar for parent.
Richard M. Stallman <rms@gnu.org>
parents:
1102
diff
changeset
|
490 free (fpid_string); /* On VMS, this was malloc'd */ |
5c942f6b2d63
(sys_suspend): Read EMACS_PARENT_PID envvar for parent.
Richard M. Stallman <rms@gnu.org>
parents:
1102
diff
changeset
|
491 |
491 | 492 if (parent_id && parent_id != 0xffffffff) |
493 { | |
494 SIGTYPE (*oldsig)() = (int) signal (SIGINT, SIG_IGN); | |
495 int status = LIB$ATTACH (&parent_id) & 1; | |
496 signal (SIGINT, oldsig); | |
497 return status; | |
498 } | |
499 else | |
500 { | |
501 struct { | |
502 int l; | |
503 char *a; | |
504 } d_prompt; | |
505 d_prompt.l = sizeof ("Emacs: "); /* Our special prompt */ | |
506 d_prompt.a = "Emacs: "; /* Just a reminder */ | |
1596
0e105bd23f44
* systty.h, process.c, buffer.h, callproc.c, sysdep.c, dired.c:
Jim Blandy <jimb@redhat.com>
parents:
1570
diff
changeset
|
507 LIB$SPAWN (0, 0, 0, 0, 0, 0, 0, 0, 0, 0, &d_prompt, 0); |
491 | 508 return 1; |
509 } | |
510 return -1; | |
511 #else | |
512 #ifdef SIGTSTP | |
513 | |
579 | 514 EMACS_KILLPG (getpgrp (0), SIGTSTP); |
491 | 515 |
516 #else /* No SIGTSTP */ | |
517 #ifdef USG_JOBCTRL /* If you don't know what this is don't mess with it */ | |
518 ptrace (0, 0, 0, 0); /* set for ptrace - caught by csh */ | |
519 kill (getpid (), SIGQUIT); | |
520 | |
521 #else /* No SIGTSTP or USG_JOBCTRL */ | |
522 | |
523 /* On a system where suspending is not implemented, | |
524 instead fork a subshell and let it talk directly to the terminal | |
525 while we wait. */ | |
526 int pid = fork (); | |
527 struct save_signal saved_handlers[5]; | |
528 | |
529 saved_handlers[0].code = SIGINT; | |
530 saved_handlers[1].code = SIGQUIT; | |
531 saved_handlers[2].code = SIGTERM; | |
532 #ifdef SIGIO | |
533 saved_handlers[3].code = SIGIO; | |
534 saved_handlers[4].code = 0; | |
535 #else | |
536 saved_handlers[3].code = 0; | |
537 #endif | |
538 | |
539 if (pid == -1) | |
540 error ("Can't spawn subshell"); | |
541 if (pid == 0) | |
542 { | |
543 char *sh; | |
544 | |
545 sh = (char *) egetenv ("SHELL"); | |
546 if (sh == 0) | |
547 sh = "sh"; | |
548 /* Use our buffer's default directory for the subshell. */ | |
549 { | |
550 Lisp_Object dir; | |
551 unsigned char *str; | |
552 int len; | |
553 | |
554 /* mentioning current_buffer->buffer would mean including buffer.h, | |
555 which somehow wedges the hp compiler. So instead... */ | |
556 | |
557 dir = intern ("default-directory"); | |
558 /* Can't use NULL */ | |
559 if (XFASTINT (Fboundp (dir)) == XFASTINT (Qnil)) | |
560 goto xyzzy; | |
561 dir = Fsymbol_value (dir); | |
562 if (XTYPE (dir) != Lisp_String) | |
563 goto xyzzy; | |
564 | |
565 str = (unsigned char *) alloca (XSTRING (dir)->size + 2); | |
566 len = XSTRING (dir)->size; | |
567 bcopy (XSTRING (dir)->data, str, len); | |
568 if (str[len - 1] != '/') str[len++] = '/'; | |
569 str[len] = 0; | |
570 chdir (str); | |
571 } | |
572 xyzzy: | |
573 #ifdef subprocesses | |
574 close_process_descs (); /* Close Emacs's pipes/ptys */ | |
575 #endif | |
1203
bc1acd76b294
* sysdep.c (sys_suspend): Don't try to use "nice (- nice (0))" to
Jim Blandy <jimb@redhat.com>
parents:
1171
diff
changeset
|
576 |
bc1acd76b294
* sysdep.c (sys_suspend): Don't try to use "nice (- nice (0))" to
Jim Blandy <jimb@redhat.com>
parents:
1171
diff
changeset
|
577 #ifdef PRIO_PROCESS |
bc1acd76b294
* sysdep.c (sys_suspend): Don't try to use "nice (- nice (0))" to
Jim Blandy <jimb@redhat.com>
parents:
1171
diff
changeset
|
578 { |
bc1acd76b294
* sysdep.c (sys_suspend): Don't try to use "nice (- nice (0))" to
Jim Blandy <jimb@redhat.com>
parents:
1171
diff
changeset
|
579 extern int emacs_priority; |
bc1acd76b294
* sysdep.c (sys_suspend): Don't try to use "nice (- nice (0))" to
Jim Blandy <jimb@redhat.com>
parents:
1171
diff
changeset
|
580 |
bc1acd76b294
* sysdep.c (sys_suspend): Don't try to use "nice (- nice (0))" to
Jim Blandy <jimb@redhat.com>
parents:
1171
diff
changeset
|
581 if (emacs_priority) |
bc1acd76b294
* sysdep.c (sys_suspend): Don't try to use "nice (- nice (0))" to
Jim Blandy <jimb@redhat.com>
parents:
1171
diff
changeset
|
582 nice (-emacs_priority); |
bc1acd76b294
* sysdep.c (sys_suspend): Don't try to use "nice (- nice (0))" to
Jim Blandy <jimb@redhat.com>
parents:
1171
diff
changeset
|
583 } |
bc1acd76b294
* sysdep.c (sys_suspend): Don't try to use "nice (- nice (0))" to
Jim Blandy <jimb@redhat.com>
parents:
1171
diff
changeset
|
584 #endif |
bc1acd76b294
* sysdep.c (sys_suspend): Don't try to use "nice (- nice (0))" to
Jim Blandy <jimb@redhat.com>
parents:
1171
diff
changeset
|
585 |
491 | 586 execlp (sh, sh, 0); |
587 write (1, "Can't execute subshell", 22); | |
588 _exit (1); | |
589 } | |
590 | |
591 save_signal_handlers (saved_handlers); | |
592 wait_for_termination (pid); | |
593 restore_signal_handlers (saved_handlers); | |
594 | |
595 #endif /* no USG_JOBCTRL */ | |
596 #endif /* no SIGTSTP */ | |
597 #endif /* not VMS */ | |
598 } | |
599 | |
600 save_signal_handlers (saved_handlers) | |
601 struct save_signal *saved_handlers; | |
602 { | |
603 while (saved_handlers->code) | |
604 { | |
692 | 605 saved_handlers->handler |
606 = (SIGTYPE (*) ()) signal (saved_handlers->code, SIG_IGN); | |
491 | 607 saved_handlers++; |
608 } | |
609 } | |
610 | |
611 restore_signal_handlers (saved_handlers) | |
612 struct save_signal *saved_handlers; | |
613 { | |
614 while (saved_handlers->code) | |
615 { | |
616 signal (saved_handlers->code, saved_handlers->handler); | |
617 saved_handlers++; | |
618 } | |
619 } | |
620 | |
621 #ifdef F_SETFL | |
622 | |
623 int old_fcntl_flags; | |
624 | |
625 init_sigio () | |
626 { | |
627 #ifdef FASYNC | |
628 old_fcntl_flags = fcntl (0, F_GETFL, 0) & ~FASYNC; | |
629 #endif | |
630 request_sigio (); | |
631 } | |
632 | |
633 reset_sigio () | |
634 { | |
635 unrequest_sigio (); | |
636 } | |
637 | |
638 #ifdef FASYNC /* F_SETFL does not imply existance of FASYNC */ | |
639 | |
640 request_sigio () | |
641 { | |
642 #ifdef SIGWINCH | |
638 | 643 sigunblock (sigmask (SIGWINCH)); |
491 | 644 #endif |
645 fcntl (0, F_SETFL, old_fcntl_flags | FASYNC); | |
646 | |
647 interrupts_deferred = 0; | |
648 } | |
649 | |
650 unrequest_sigio () | |
651 { | |
652 #ifdef SIGWINCH | |
638 | 653 sigblock (sigmask (SIGWINCH)); |
491 | 654 #endif |
655 fcntl (0, F_SETFL, old_fcntl_flags); | |
656 interrupts_deferred = 1; | |
657 } | |
658 | |
659 #else /* no FASYNC */ | |
660 #ifdef STRIDE /* Stride doesn't have FASYNC - use FIOASYNC */ | |
661 | |
662 request_sigio () | |
663 { | |
664 int on = 1; | |
665 ioctl (0, FIOASYNC, &on); | |
666 interrupts_deferred = 0; | |
667 } | |
668 | |
669 unrequest_sigio () | |
670 { | |
671 int off = 0; | |
672 | |
673 ioctl (0, FIOASYNC, &off); | |
674 interrupts_deferred = 1; | |
675 } | |
676 | |
677 #else /* not FASYNC, not STRIDE */ | |
678 | |
679 request_sigio () | |
680 { | |
681 croak ("request_sigio"); | |
682 } | |
683 | |
684 unrequest_sigio () | |
685 { | |
686 croak ("unrequest_sigio"); | |
687 } | |
688 | |
689 #endif /* STRIDE */ | |
690 #endif /* FASYNC */ | |
691 #endif /* F_SETFL */ | |
692 | |
579 | 693 /* The initial tty mode bits */ |
694 struct emacs_tty old_tty; | |
491 | 695 |
696 int term_initted; /* 1 if outer tty status has been recorded */ | |
697 | |
579 | 698 #ifdef BSD4_1 |
699 /* BSD 4.1 needs to keep track of the lmode bits in order to start | |
700 sigio. */ | |
701 int lmode; | |
702 #endif | |
703 | |
491 | 704 #ifdef F_SETOWN |
705 int old_fcntl_owner; | |
706 #endif /* F_SETOWN */ | |
707 | |
708 /* This may also be defined in stdio, | |
709 but if so, this does no harm, | |
710 and using the same name avoids wasting the other one's space. */ | |
711 | |
712 #if defined (USG) || defined (DGUX) | |
713 unsigned char _sobuf[BUFSIZ+8]; | |
714 #else | |
715 char _sobuf[BUFSIZ]; | |
716 #endif | |
717 | |
718 #ifdef TIOCGLTC | |
719 static struct ltchars new_ltchars = {-1,-1,-1,-1,-1,-1}; | |
720 #endif | |
721 #ifdef TIOCGETC | |
722 static struct tchars new_tchars = {-1,-1,-1,-1,-1,-1}; | |
723 #endif | |
724 | |
725 init_sys_modes () | |
726 { | |
579 | 727 struct emacs_tty tty; |
728 | |
491 | 729 #ifdef VMS |
730 #if 0 | |
731 static int oob_chars[2] = {0, 1 << 7}; /* catch C-g's */ | |
732 extern int (*interrupt_signal) (); | |
733 #endif | |
734 #endif | |
735 | |
736 if (noninteractive) | |
737 return; | |
738 | |
739 #ifdef VMS | |
740 if (!input_ef) | |
741 input_ef = get_kbd_event_flag (); | |
742 /* LIB$GET_EF (&input_ef); */ | |
743 SYS$CLREF (input_ef); | |
744 waiting_for_ast = 0; | |
745 if (!timer_ef) | |
746 timer_ef = get_timer_event_flag (); | |
747 /* LIB$GET_EF (&timer_ef); */ | |
748 SYS$CLREF (timer_ef); | |
749 if (!process_ef) | |
750 { | |
751 LIB$GET_EF (&process_ef); | |
752 SYS$CLREF (process_ef); | |
753 } | |
754 if (input_ef / 32 != process_ef / 32) | |
755 croak ("Input and process event flags in different clusters."); | |
756 if (input_ef / 32 != timer_ef / 32) | |
757 croak ("Input and process event flags in different clusters."); | |
758 input_eflist = ((unsigned) 1 << (input_ef % 32)) | | |
759 ((unsigned) 1 << (process_ef % 32)); | |
760 timer_eflist = ((unsigned) 1 << (input_ef % 32)) | | |
761 ((unsigned) 1 << (timer_ef % 32)); | |
762 #ifndef VMS4_4 | |
763 sys_access_reinit (); | |
764 #endif | |
765 #endif /* not VMS */ | |
579 | 766 |
767 EMACS_GET_TTY (input_fd, &old_tty); | |
768 | |
491 | 769 if (!read_socket_hook && EQ (Vwindow_system, Qnil)) |
770 { | |
579 | 771 tty = old_tty; |
491 | 772 |
773 #ifdef HAVE_TERMIO | |
579 | 774 tty.main.c_iflag |= (IGNBRK); /* Ignore break condition */ |
775 tty.main.c_iflag &= ~ICRNL; /* Disable map of CR to NL on input */ | |
491 | 776 #ifdef ISTRIP |
579 | 777 tty.main.c_iflag &= ~ISTRIP; /* don't strip 8th bit on input */ |
491 | 778 #endif |
579 | 779 tty.main.c_lflag &= ~ECHO; /* Disable echo */ |
780 tty.main.c_lflag &= ~ICANON; /* Disable erase/kill processing */ | |
1102
ff73961932eb
(init_sys_modes): Handle VDSUSP like V_DSUSP.
Richard M. Stallman <rms@gnu.org>
parents:
1048
diff
changeset
|
781 #ifdef IEXTEN |
ff73961932eb
(init_sys_modes): Handle VDSUSP like V_DSUSP.
Richard M. Stallman <rms@gnu.org>
parents:
1048
diff
changeset
|
782 tty.main.c_iflag &= ~IEXTEN; /* Disable other editing characters. */ |
ff73961932eb
(init_sys_modes): Handle VDSUSP like V_DSUSP.
Richard M. Stallman <rms@gnu.org>
parents:
1048
diff
changeset
|
783 #endif |
579 | 784 tty.main.c_lflag |= ISIG; /* Enable signals */ |
491 | 785 if (flow_control) |
786 { | |
579 | 787 tty.main.c_iflag |= IXON; /* Enable start/stop output control */ |
491 | 788 #ifdef IXANY |
579 | 789 tty.main.c_iflag &= ~IXANY; |
491 | 790 #endif /* IXANY */ |
791 } | |
792 else | |
579 | 793 tty.main.c_iflag &= ~IXON; /* Disable start/stop output control */ |
794 tty.main.c_oflag &= ~ONLCR; /* Disable map of NL to CR-NL | |
795 on output */ | |
796 tty.main.c_oflag &= ~TAB3; /* Disable tab expansion */ | |
491 | 797 #ifdef CS8 |
798 if (meta_key) | |
799 { | |
579 | 800 tty.main.c_cflag |= CS8; /* allow 8th bit on input */ |
801 tty.main.c_cflag &= ~PARENB;/* Don't check parity */ | |
491 | 802 } |
803 #endif | |
579 | 804 tty.main.c_cc[VINTR] = quit_char; /* C-g (usually) gives SIGINT */ |
491 | 805 /* Set up C-g for both SIGQUIT and SIGINT. |
806 We don't know which we will get, but we handle both alike | |
807 so which one it really gives us does not matter. */ | |
579 | 808 tty.main.c_cc[VQUIT] = quit_char; |
809 tty.main.c_cc[VMIN] = 1; /* Input should wait for at least 1 char */ | |
810 tty.main.c_cc[VTIME] = 0; /* no matter how long that takes. */ | |
491 | 811 #ifdef VSWTCH |
1102
ff73961932eb
(init_sys_modes): Handle VDSUSP like V_DSUSP.
Richard M. Stallman <rms@gnu.org>
parents:
1048
diff
changeset
|
812 tty.main.c_cc[VSWTCH] = CDISABLE; /* Turn off shell layering use |
579 | 813 of C-z */ |
491 | 814 #endif /* VSWTCH */ |
815 #if defined (mips) || defined (HAVE_TCATTR) | |
816 #ifdef VSUSP | |
1102
ff73961932eb
(init_sys_modes): Handle VDSUSP like V_DSUSP.
Richard M. Stallman <rms@gnu.org>
parents:
1048
diff
changeset
|
817 tty.main.c_cc[VSUSP] = CDISABLE; /* Turn off mips handling of C-z. */ |
491 | 818 #endif /* VSUSP */ |
819 #ifdef V_DSUSP | |
1102
ff73961932eb
(init_sys_modes): Handle VDSUSP like V_DSUSP.
Richard M. Stallman <rms@gnu.org>
parents:
1048
diff
changeset
|
820 tty.main.c_cc[V_DSUSP] = CDISABLE; /* Turn off mips handling of C-y. */ |
491 | 821 #endif /* V_DSUSP */ |
1102
ff73961932eb
(init_sys_modes): Handle VDSUSP like V_DSUSP.
Richard M. Stallman <rms@gnu.org>
parents:
1048
diff
changeset
|
822 #ifdef VDSUSP /* Some systems have VDSUSP, some have V_DSUSP. */ |
ff73961932eb
(init_sys_modes): Handle VDSUSP like V_DSUSP.
Richard M. Stallman <rms@gnu.org>
parents:
1048
diff
changeset
|
823 tty.main.c_cc[VDSUSP] = CDISABLE; |
ff73961932eb
(init_sys_modes): Handle VDSUSP like V_DSUSP.
Richard M. Stallman <rms@gnu.org>
parents:
1048
diff
changeset
|
824 #endif /* VDSUSP */ |
491 | 825 #endif /* mips or HAVE_TCATTR */ |
826 #ifdef AIX | |
827 #ifndef IBMR2AIX | |
828 /* AIX enhanced edit loses NULs, so disable it */ | |
579 | 829 tty.main.c_line = 0; |
830 tty.main.c_iflag &= ~ASCEDIT; | |
491 | 831 #else |
579 | 832 tty.main.c_cc[VSTRT] = 255; |
833 tty.main.c_cc[VSTOP] = 255; | |
834 tty.main.c_cc[VSUSP] = 255; | |
835 tty.main.c_cc[VDSUSP] = 255; | |
491 | 836 #endif /* IBMR2AIX */ |
837 /* Also, PTY overloads NUL and BREAK. | |
838 don't ignore break, but don't signal either, so it looks like NUL. | |
839 This really serves a purpose only if running in an XTERM window | |
840 or via TELNET or the like, but does no harm elsewhere. */ | |
579 | 841 tty.main.c_iflag &= ~IGNBRK; |
842 tty.main.c_iflag &= ~BRKINT; | |
491 | 843 #endif |
844 #else /* if not HAVE_TERMIO */ | |
845 #ifdef VMS | |
579 | 846 tty.main.tt_char |= TT$M_NOECHO; |
491 | 847 if (meta_key) |
1596
0e105bd23f44
* systty.h, process.c, buffer.h, callproc.c, sysdep.c, dired.c:
Jim Blandy <jimb@redhat.com>
parents:
1570
diff
changeset
|
848 tty.main.tt_char |= TT$M_EIGHTBIT; |
491 | 849 if (flow_control) |
579 | 850 tty.main.tt_char |= TT$M_TTSYNC; |
491 | 851 else |
579 | 852 tty.main.tt_char &= ~TT$M_TTSYNC; |
853 tty.main.tt2_char |= TT2$M_PASTHRU | TT2$M_XON; | |
491 | 854 #else /* not VMS (BSD, that is) */ |
579 | 855 tty.main.sg_flags &= ~(ECHO | CRMOD | XTABS); |
491 | 856 if (meta_key) |
579 | 857 tty.main.sg_flags |= ANYP; |
858 tty.main.sg_flags |= interrupt_input ? RAW : CBREAK; | |
491 | 859 #endif /* not VMS (BSD, that is) */ |
860 #endif /* not HAVE_TERMIO */ | |
861 | |
579 | 862 /* If going to use CBREAK mode, we must request C-g to interrupt |
863 and turn off start and stop chars, etc. If not going to use | |
864 CBREAK mode, do this anyway so as to turn off local flow | |
865 control for user coming over network on 4.2; in this case, | |
866 only t_stopc and t_startc really matter. */ | |
867 #ifndef HAVE_TERMIO | |
868 #ifdef TIOCGETC | |
869 /* Note: if not using CBREAK mode, it makes no difference how we | |
870 set this */ | |
871 tty.tchars = new_tchars; | |
872 tty.tchars.t_intrc = quit_char; | |
873 if (flow_control) | |
874 { | |
875 tty.tchars.t_startc = '\021'; | |
876 tty.tchars.t_stopc = '\023'; | |
877 } | |
878 | |
879 /* LPASS8 is new in 4.3, and makes cbreak mode provide all 8 bits. */ | |
880 #ifndef LPASS8 | |
881 #define LPASS8 0 | |
491 | 882 #endif |
579 | 883 |
884 #ifdef BSD4_1 | |
885 #define LNOFLSH 0100000 | |
886 #endif | |
887 | |
888 tty.lmode = LDECCTQ | LLITOUT | LPASS8 | LNOFLSH | old_tty.lmode; | |
889 | |
890 #ifdef BSD4_1 | |
891 lmode = tty.lmode; | |
892 #endif | |
893 | |
894 #endif /* TIOCGETC */ | |
895 #endif /* not HAVE_TERMIO */ | |
896 | |
897 #ifdef TIOCGLTC | |
898 tty.ltchars = new_ltchars; | |
899 #endif /* TIOCGLTC */ | |
900 | |
901 EMACS_SET_TTY (input_fd, &tty, 0); | |
491 | 902 |
903 /* This code added to insure that, if flow-control is not to be used, | |
766 | 904 we have an unlocked terminal at the start. */ |
579 | 905 |
491 | 906 #ifdef TCXONC |
907 if (!flow_control) ioctl (0, TCXONC, 1); | |
908 #endif | |
909 #ifndef APOLLO | |
910 #ifdef TIOCSTART | |
911 if (!flow_control) ioctl (0, TIOCSTART, 0); | |
912 #endif | |
913 #endif | |
914 | |
915 #ifdef AIX | |
916 hft_init (); | |
917 #ifdef IBMR2AIX | |
918 { | |
919 /* IBM's HFT device usually thinks a ^J should be LF/CR. We need it | |
920 to be only LF. This is the way that is done. */ | |
921 struct termio tty; | |
922 | |
923 if (ioctl (1, HFTGETID, &tty) != -1) | |
924 write (1, "\033[20l", 5); | |
925 } | |
926 #endif | |
927 #endif | |
928 | |
929 #ifdef VMS | |
930 /* Appears to do nothing when in PASTHRU mode. | |
579 | 931 SYS$QIOW (0, input_fd, IO$_SETMODE|IO$M_OUTBAND, 0, 0, 0, |
491 | 932 interrupt_signal, oob_chars, 0, 0, 0, 0); |
933 */ | |
934 queue_kbd_input (0); | |
935 #endif /* VMS */ | |
936 } | |
937 | |
938 #ifdef F_SETFL | |
939 #ifdef F_GETOWN /* F_SETFL does not imply existance of F_GETOWN */ | |
940 if (interrupt_input) | |
941 { | |
942 old_fcntl_owner = fcntl (0, F_GETOWN, 0); | |
943 fcntl (0, F_SETOWN, getpid ()); | |
944 init_sigio (); | |
945 } | |
946 #endif /* F_GETOWN */ | |
947 #endif /* F_SETFL */ | |
948 | |
949 #ifdef BSD4_1 | |
950 if (interrupt_input) | |
951 init_sigio (); | |
952 #endif | |
953 | |
954 #ifdef VMS /* VMS sometimes has this symbol but lacks setvbuf. */ | |
955 #undef _IOFBF | |
956 #endif | |
957 #ifdef _IOFBF | |
958 /* This symbol is defined on recent USG systems. | |
959 Someone says without this call USG won't really buffer the file | |
960 even with a call to setbuf. */ | |
961 setvbuf (stdout, _sobuf, _IOFBF, sizeof _sobuf); | |
962 #else | |
963 setbuf (stdout, _sobuf); | |
964 #endif | |
965 set_terminal_modes (); | |
966 if (term_initted && no_redraw_on_reenter) | |
967 { | |
968 if (display_completed) | |
969 direct_output_forward_char (0); | |
970 } | |
971 else | |
972 { | |
766 | 973 frame_garbaged = 1; |
974 #ifdef MULTI_FRAME | |
975 if (FRAMEP (Vterminal_frame)) | |
976 FRAME_GARBAGED_P (XFRAME (Vterminal_frame)) = 1; | |
491 | 977 #endif |
978 } | |
579 | 979 |
491 | 980 term_initted = 1; |
981 } | |
982 | |
983 /* Return nonzero if safe to use tabs in output. | |
984 At the time this is called, init_sys_modes has not been done yet. */ | |
985 | |
986 tabs_safe_p () | |
987 { | |
579 | 988 struct emacs_tty tty; |
989 | |
990 EMACS_GET_TTY (input_fd, &tty); | |
991 return EMACS_TTY_TABS_OK (&tty); | |
491 | 992 } |
993 | |
994 /* Get terminal size from system. | |
995 Store number of lines into *heightp and width into *widthp. | |
996 If zero or a negative number is stored, the value is not valid. */ | |
997 | |
766 | 998 get_frame_size (widthp, heightp) |
491 | 999 int *widthp, *heightp; |
1000 { | |
579 | 1001 |
1002 #ifdef TIOCGWINSZ | |
1003 | |
1004 /* BSD-style. */ | |
1005 struct winsize size; | |
1006 | |
1007 if (ioctl (input_fd, TIOCGWINSZ, &size) == -1) | |
1008 *widthp = *heightp = 0; | |
1009 else | |
1010 { | |
1011 *widthp = size.ws_col; | |
1012 *heightp = size.ws_row; | |
1013 } | |
1014 | |
1015 #else | |
491 | 1016 #ifdef TIOCGSIZE |
579 | 1017 |
1018 /* SunOS - style. */ | |
1019 struct ttysize size; | |
1020 | |
1021 if (ioctl (input_fd, TIOCGSIZE, &size) == -1) | |
1022 *widthp = *heightp = 0; | |
1023 else | |
1024 { | |
1025 *widthp = size.ts_cols; | |
1026 *heightp = size.ts_lines; | |
1027 } | |
1028 | |
1029 #else | |
491 | 1030 #ifdef VMS |
579 | 1031 |
1032 struct sensemode tty; | |
1033 | |
1034 SYS$QIOW (0, input_fd, IO$_SENSEMODE, &tty, 0, 0, | |
491 | 1035 &tty.class, 12, 0, 0, 0, 0); |
1036 *widthp = tty.scr_wid; | |
1037 *heightp = tty.scr_len; | |
579 | 1038 |
491 | 1039 #else /* system doesn't know size */ |
579 | 1040 |
491 | 1041 *widthp = 0; |
1042 *heightp = 0; | |
579 | 1043 |
1044 #endif /* not VMS */ | |
1045 #endif /* not SunOS-style */ | |
1046 #endif /* not BSD-style */ | |
491 | 1047 } |
579 | 1048 |
491 | 1049 |
579 | 1050 /* Prepare the terminal for exiting Emacs; move the cursor to the |
766 | 1051 bottom of the frame, turn off interrupt-driven I/O, etc. */ |
491 | 1052 reset_sys_modes () |
1053 { | |
1054 if (noninteractive) | |
1055 { | |
1056 fflush (stdout); | |
1057 return; | |
1058 } | |
1059 if (!term_initted) | |
1060 return; | |
1061 if (read_socket_hook || !EQ (Vwindow_system, Qnil)) | |
1062 return; | |
766 | 1063 cursor_to (FRAME_HEIGHT (selected_frame) - 1, 0); |
1064 clear_end_of_line (FRAME_WIDTH (selected_frame)); | |
491 | 1065 /* clear_end_of_line may move the cursor */ |
766 | 1066 cursor_to (FRAME_HEIGHT (selected_frame) - 1, 0); |
491 | 1067 #ifdef IBMR2AIX |
1068 { | |
1069 /* HFT devices normally use ^J as a LF/CR. We forced it to | |
1070 do the LF only. Now, we need to reset it. */ | |
1071 struct termio tty; | |
1072 | |
1073 if (ioctl (1, HFTGETID, &tty) != -1) | |
1074 write (1, "\033[20h", 5); | |
1075 } | |
1076 #endif | |
1077 | |
1078 reset_terminal_modes (); | |
1079 fflush (stdout); | |
1080 #ifdef BSD | |
1081 #ifndef BSD4_1 | |
1082 /* Avoid possible loss of output when changing terminal modes. */ | |
1083 fsync (fileno (stdout)); | |
1084 #endif | |
1085 #endif | |
579 | 1086 |
491 | 1087 #ifdef F_SETFL |
1088 #ifdef F_SETOWN /* F_SETFL does not imply existance of F_SETOWN */ | |
1089 if (interrupt_input) | |
1090 { | |
1091 reset_sigio (); | |
1092 fcntl (0, F_SETOWN, old_fcntl_owner); | |
1093 } | |
1094 #endif /* F_SETOWN */ | |
1095 #endif /* F_SETFL */ | |
1096 #ifdef BSD4_1 | |
1097 if (interrupt_input) | |
1098 reset_sigio (); | |
1099 #endif /* BSD4_1 */ | |
579 | 1100 |
1101 while (EMACS_SET_TTY (input_fd, &old_tty, 0) < 0 && errno == EINTR) | |
1102 ; | |
491 | 1103 |
1104 #ifdef AIX | |
1105 hft_reset (); | |
1106 #endif | |
1107 } | |
1108 | |
1109 #ifdef HAVE_PTYS | |
1110 | |
1111 /* Set up the proper status flags for use of a pty. */ | |
1112 | |
1113 setup_pty (fd) | |
1114 int fd; | |
1115 { | |
1116 /* I'm told that TOICREMOTE does not mean control chars | |
1117 "can't be sent" but rather that they don't have | |
1118 input-editing or signaling effects. | |
1119 That should be good, because we have other ways | |
1120 to do those things in Emacs. | |
1121 However, telnet mode seems not to work on 4.2. | |
1122 So TIOCREMOTE is turned off now. */ | |
1123 | |
1124 /* Under hp-ux, if TIOCREMOTE is turned on, some calls | |
1125 will hang. In particular, the "timeout" feature (which | |
1126 causes a read to return if there is no data available) | |
1127 does this. Also it is known that telnet mode will hang | |
1128 in such a way that Emacs must be stopped (perhaps this | |
1129 is the same problem). | |
1130 | |
1131 If TIOCREMOTE is turned off, then there is a bug in | |
1132 hp-ux which sometimes loses data. Apparently the | |
1133 code which blocks the master process when the internal | |
1134 buffer fills up does not work. Other than this, | |
1135 though, everything else seems to work fine. | |
1136 | |
1137 Since the latter lossage is more benign, we may as well | |
1138 lose that way. -- cph */ | |
1139 #ifdef FIONBIO | |
1140 #ifdef SYSV_PTYS | |
1141 { | |
1142 int on = 1; | |
1143 ioctl (fd, FIONBIO, &on); | |
1144 } | |
1145 #endif | |
1146 #endif | |
1147 #ifdef IBMRTAIX | |
1148 /* On AIX, the parent gets SIGHUP when a pty attached child dies. So, we */ | |
1149 /* ignore SIGHUP once we've started a child on a pty. Note that this may */ | |
1150 /* cause EMACS not to die when it should, i.e., when its own controlling */ | |
1151 /* tty goes away. I've complained to the AIX developers, and they may */ | |
1152 /* change this behavior, but I'm not going to hold my breath. */ | |
1153 signal (SIGHUP, SIG_IGN); | |
1154 #endif | |
1155 } | |
1156 #endif /* HAVE_PTYS */ | |
1157 | |
1158 #ifdef VMS | |
1159 | |
1160 /* Assigning an input channel is done at the start of Emacs execution. | |
1161 This is called each time Emacs is resumed, also, but does nothing | |
1162 because input_chain is no longer zero. */ | |
1163 | |
1164 init_vms_input () | |
1165 { | |
1166 int status; | |
1167 | |
579 | 1168 if (input_fd == 0) |
491 | 1169 { |
579 | 1170 status = SYS$ASSIGN (&input_dsc, &input_fd, 0, 0); |
491 | 1171 if (! (status & 1)) |
1172 LIB$STOP (status); | |
1173 } | |
1174 } | |
1175 | |
1176 /* Deassigning the input channel is done before exiting. */ | |
1177 | |
1178 stop_vms_input () | |
1179 { | |
579 | 1180 return SYS$DASSGN (input_fd); |
491 | 1181 } |
1182 | |
1183 short input_buffer; | |
1184 | |
1185 /* Request reading one character into the keyboard buffer. | |
1186 This is done as soon as the buffer becomes empty. */ | |
1187 | |
1188 queue_kbd_input () | |
1189 { | |
1190 int status; | |
1191 waiting_for_ast = 0; | |
1192 stop_input = 0; | |
579 | 1193 status = SYS$QIO (0, input_fd, IO$_READVBLK, |
491 | 1194 &input_iosb, kbd_input_ast, 1, |
1195 &input_buffer, 1, 0, terminator_mask, 0, 0); | |
1196 } | |
1197 | |
1198 int input_count; | |
1199 | |
1200 /* Ast routine that is called when keyboard input comes in | |
1201 in accord with the SYS$QIO above. */ | |
1202 | |
1203 kbd_input_ast () | |
1204 { | |
1205 register int c = -1; | |
1206 int old_errno = errno; | |
648 | 1207 extern EMACS_TIME *input_available_clear_time; |
491 | 1208 |
1209 if (waiting_for_ast) | |
1210 SYS$SETEF (input_ef); | |
1211 waiting_for_ast = 0; | |
1212 input_count++; | |
1213 #ifdef ASTDEBUG | |
1214 if (input_count == 25) | |
1215 exit (1); | |
1216 printf ("Ast # %d,", input_count); | |
1217 printf (" iosb = %x, %x, %x, %x", | |
1218 input_iosb.offset, input_iosb.status, input_iosb.termlen, | |
1219 input_iosb.term); | |
1220 #endif | |
1221 if (input_iosb.offset) | |
1222 { | |
1223 c = input_buffer; | |
1224 #ifdef ASTDEBUG | |
1225 printf (", char = 0%o", c); | |
1226 #endif | |
1227 } | |
1228 #ifdef ASTDEBUG | |
1229 printf ("\n"); | |
1230 fflush (stdout); | |
1231 sleep (1); | |
1232 #endif | |
1233 if (! stop_input) | |
1234 queue_kbd_input (); | |
1596
0e105bd23f44
* systty.h, process.c, buffer.h, callproc.c, sysdep.c, dired.c:
Jim Blandy <jimb@redhat.com>
parents:
1570
diff
changeset
|
1235 /* I don't know what this is doing! The variables buf, cbuf and i are |
0e105bd23f44
* systty.h, process.c, buffer.h, callproc.c, sysdep.c, dired.c:
Jim Blandy <jimb@redhat.com>
parents:
1570
diff
changeset
|
1236 not declared. This is new from version 18, what does it do? |
491 | 1237 if (c >= 0) |
1238 { | |
1239 struct input_event e; | |
1240 e.kind = ascii_keystroke; | |
1241 XSET (buf[i].code, Lisp_Int, cbuf[i]); | |
766 | 1242 e.frame = selected_frame; |
491 | 1243 kbd_buffer_store_event (&e); |
1244 } | |
1596
0e105bd23f44
* systty.h, process.c, buffer.h, callproc.c, sysdep.c, dired.c:
Jim Blandy <jimb@redhat.com>
parents:
1570
diff
changeset
|
1245 */ |
648 | 1246 if (input_available_clear_time) |
1247 EMACS_SET_SECS_USECS (*input_available_clear_time, 0, 0); | |
491 | 1248 errno = old_errno; |
1249 } | |
1250 | |
1251 /* Wait until there is something in kbd_buffer. */ | |
1252 | |
1253 wait_for_kbd_input () | |
1254 { | |
1255 extern int have_process_input, process_exited; | |
1256 | |
1257 /* If already something, avoid doing system calls. */ | |
1258 if (detect_input_pending ()) | |
1259 { | |
1260 return; | |
1261 } | |
1262 /* Clear a flag, and tell ast routine above to set it. */ | |
1263 SYS$CLREF (input_ef); | |
1264 waiting_for_ast = 1; | |
1265 /* Check for timing error: ast happened while we were doing that. */ | |
1266 if (!detect_input_pending ()) | |
1267 { | |
1268 /* No timing error: wait for flag to be set. */ | |
1269 set_waiting_for_input (0); | |
1270 SYS$WFLOR (input_ef, input_eflist); | |
1271 clear_waiting_for_input (0); | |
1272 if (!detect_input_pending ()) | |
1273 /* Check for subprocess input availability */ | |
1274 { | |
1275 int dsp = have_process_input || process_exited; | |
1276 | |
1277 SYS$CLREF (process_ef); | |
1278 if (have_process_input) | |
1279 process_command_input (); | |
1280 if (process_exited) | |
1281 process_exit (); | |
1282 if (dsp) | |
1283 { | |
1284 update_mode_lines++; | |
1285 redisplay_preserve_echo_area (); | |
1286 } | |
1287 } | |
1288 } | |
1289 waiting_for_ast = 0; | |
1290 } | |
1291 | |
1292 /* Get rid of any pending QIO, when we are about to suspend | |
1293 or when we want to throw away pending input. | |
1294 We wait for a positive sign that the AST routine has run | |
1295 and therefore there is no I/O request queued when we return. | |
1296 SYS$SETAST is used to avoid a timing error. */ | |
1297 | |
1298 end_kbd_input () | |
1299 { | |
1300 #ifdef ASTDEBUG | |
1301 printf ("At end_kbd_input.\n"); | |
1302 fflush (stdout); | |
1303 sleep (1); | |
1304 #endif | |
1305 if (LIB$AST_IN_PROG ()) /* Don't wait if suspending from kbd_buffer_store_event! */ | |
1306 { | |
579 | 1307 SYS$CANCEL (input_fd); |
491 | 1308 return; |
1309 } | |
1310 | |
1311 SYS$SETAST (0); | |
1312 /* Clear a flag, and tell ast routine above to set it. */ | |
1313 SYS$CLREF (input_ef); | |
1314 waiting_for_ast = 1; | |
1315 stop_input = 1; | |
579 | 1316 SYS$CANCEL (input_fd); |
491 | 1317 SYS$SETAST (1); |
1318 SYS$WAITFR (input_ef); | |
1319 waiting_for_ast = 0; | |
1320 } | |
1321 | |
1322 /* Wait for either input available or time interval expiry. */ | |
1323 | |
1324 input_wait_timeout (timeval) | |
1325 int timeval; /* Time to wait, in seconds */ | |
1326 { | |
1327 int time [2]; | |
1328 static int zero = 0; | |
1329 static int large = -10000000; | |
1330 | |
1331 LIB$EMUL (&timeval, &large, &zero, time); /* Convert to VMS format */ | |
1332 | |
1333 /* If already something, avoid doing system calls. */ | |
1334 if (detect_input_pending ()) | |
1335 { | |
1336 return; | |
1337 } | |
1338 /* Clear a flag, and tell ast routine above to set it. */ | |
1339 SYS$CLREF (input_ef); | |
1340 waiting_for_ast = 1; | |
1341 /* Check for timing error: ast happened while we were doing that. */ | |
1342 if (!detect_input_pending ()) | |
1343 { | |
1344 /* No timing error: wait for flag to be set. */ | |
1345 SYS$CANTIM (1, 0); | |
1346 if (SYS$SETIMR (timer_ef, time, 0, 1) & 1) /* Set timer */ | |
1347 SYS$WFLOR (timer_ef, timer_eflist); /* Wait for timer expiry or input */ | |
1348 } | |
1349 waiting_for_ast = 0; | |
1350 } | |
1351 | |
1352 /* The standard `sleep' routine works some other way | |
1353 and it stops working if you have ever quit out of it. | |
1354 This one continues to work. */ | |
1355 | |
1356 sys_sleep (timeval) | |
1357 int timeval; | |
1358 { | |
1359 int time [2]; | |
1360 static int zero = 0; | |
1361 static int large = -10000000; | |
1362 | |
1363 LIB$EMUL (&timeval, &large, &zero, time); /* Convert to VMS format */ | |
1364 | |
1365 SYS$CANTIM (1, 0); | |
1366 if (SYS$SETIMR (timer_ef, time, 0, 1) & 1) /* Set timer */ | |
1367 SYS$WAITFR (timer_ef); /* Wait for timer expiry only */ | |
1368 } | |
1369 | |
1370 init_sigio () | |
1371 { | |
1372 request_sigio (); | |
1373 } | |
1374 | |
1375 reset_sigio () | |
1376 { | |
1377 unrequest_sigio (); | |
1378 } | |
1379 | |
1380 request_sigio () | |
1381 { | |
1382 croak ("request sigio"); | |
1383 } | |
1384 | |
1385 unrequest_sigio () | |
1386 { | |
1387 croak ("unrequest sigio"); | |
1388 } | |
1389 | |
1390 #endif /* VMS */ | |
1391 | |
1392 /* Note that VMS compiler won't accept defined (CANNOT_DUMP). */ | |
1393 #ifndef CANNOT_DUMP | |
1394 #define NEED_STARTS | |
1395 #endif | |
1396 | |
1397 #ifndef SYSTEM_MALLOC | |
1398 #ifndef NEED_STARTS | |
1399 #define NEED_STARTS | |
1400 #endif | |
1401 #endif | |
1402 | |
1403 #ifdef NEED_STARTS | |
1404 /* Some systems that cannot dump also cannot implement these. */ | |
1405 | |
1406 /* | |
1407 * Return the address of the start of the text segment prior to | |
1408 * doing an unexec. After unexec the return value is undefined. | |
1409 * See crt0.c for further explanation and _start. | |
1410 * | |
1411 */ | |
1412 | |
1413 #ifndef CANNOT_UNEXEC | |
1414 char * | |
1415 start_of_text () | |
1416 { | |
1417 #ifdef TEXT_START | |
1418 return ((char *) TEXT_START); | |
1419 #else | |
1420 #ifdef GOULD | |
1421 extern csrt (); | |
1422 return ((char *) csrt); | |
1423 #else /* not GOULD */ | |
1424 extern int _start (); | |
1425 return ((char *) _start); | |
1426 #endif /* GOULD */ | |
1427 #endif /* TEXT_START */ | |
1428 } | |
1429 #endif /* not CANNOT_UNEXEC */ | |
1430 | |
1431 /* | |
1432 * Return the address of the start of the data segment prior to | |
1433 * doing an unexec. After unexec the return value is undefined. | |
1434 * See crt0.c for further information and definition of data_start. | |
1435 * | |
1436 * Apparently, on BSD systems this is etext at startup. On | |
1437 * USG systems (swapping) this is highly mmu dependent and | |
1438 * is also dependent on whether or not the program is running | |
1439 * with shared text. Generally there is a (possibly large) | |
1440 * gap between end of text and start of data with shared text. | |
1441 * | |
1442 * On Uniplus+ systems with shared text, data starts at a | |
1443 * fixed address. Each port (from a given oem) is generally | |
1444 * different, and the specific value of the start of data can | |
1445 * be obtained via the UniPlus+ specific "uvar" system call, | |
1446 * however the method outlined in crt0.c seems to be more portable. | |
1447 * | |
1448 * Probably what will have to happen when a USG unexec is available, | |
1449 * at least on UniPlus, is temacs will have to be made unshared so | |
1450 * that text and data are contiguous. Then once loadup is complete, | |
1451 * unexec will produce a shared executable where the data can be | |
1452 * at the normal shared text boundry and the startofdata variable | |
1453 * will be patched by unexec to the correct value. | |
1454 * | |
1455 */ | |
1456 | |
1457 char * | |
1458 start_of_data () | |
1459 { | |
1460 #ifdef DATA_START | |
1461 return ((char *) DATA_START); | |
1462 #else | |
1463 extern int data_start; | |
1464 return ((char *) &data_start); | |
1465 #endif | |
1466 } | |
1467 #endif /* NEED_STARTS (not CANNOT_DUMP or not SYSTEM_MALLOC) */ | |
1468 | |
1469 #ifndef CANNOT_DUMP | |
1470 /* Some systems that cannot dump also cannot implement these. */ | |
1471 | |
1472 /* | |
1473 * Return the address of the end of the text segment prior to | |
1474 * doing an unexec. After unexec the return value is undefined. | |
1475 */ | |
1476 | |
1477 char * | |
1478 end_of_text () | |
1479 { | |
1480 #ifdef TEXT_END | |
1481 return ((char *) TEXT_END); | |
1482 #else | |
1483 extern int etext; | |
1484 return ((char *) &etext); | |
1485 #endif | |
1486 } | |
1487 | |
1488 /* | |
1489 * Return the address of the end of the data segment prior to | |
1490 * doing an unexec. After unexec the return value is undefined. | |
1491 */ | |
1492 | |
1493 char * | |
1494 end_of_data () | |
1495 { | |
1496 #ifdef DATA_END | |
1497 return ((char *) DATA_END); | |
1498 #else | |
1499 extern int edata; | |
1500 return ((char *) &edata); | |
1501 #endif | |
1502 } | |
1503 | |
1504 #endif /* not CANNOT_DUMP */ | |
1505 | |
1506 /* Get_system_name returns as its value | |
1507 a string for the Lisp function system-name to return. */ | |
1508 | |
1509 #ifdef BSD4_1 | |
1510 #include <whoami.h> | |
1511 #endif | |
1512 | |
1496
f9010847a5f5
(get_system_name): Use gethostname for USG systems
Richard M. Stallman <rms@gnu.org>
parents:
1203
diff
changeset
|
1513 /* Can't have this within the function since `static' is #defined to |
f9010847a5f5
(get_system_name): Use gethostname for USG systems
Richard M. Stallman <rms@gnu.org>
parents:
1203
diff
changeset
|
1514 nothing for some USG systems. */ |
491 | 1515 #ifdef USG |
1496
f9010847a5f5
(get_system_name): Use gethostname for USG systems
Richard M. Stallman <rms@gnu.org>
parents:
1203
diff
changeset
|
1516 #ifdef HAVE_GETHOSTNAME |
f9010847a5f5
(get_system_name): Use gethostname for USG systems
Richard M. Stallman <rms@gnu.org>
parents:
1203
diff
changeset
|
1517 static char get_system_name_name[256]; |
f9010847a5f5
(get_system_name): Use gethostname for USG systems
Richard M. Stallman <rms@gnu.org>
parents:
1203
diff
changeset
|
1518 #else /* not HAVE_GETHOSTNAME */ |
491 | 1519 static struct utsname get_system_name_name; |
1496
f9010847a5f5
(get_system_name): Use gethostname for USG systems
Richard M. Stallman <rms@gnu.org>
parents:
1203
diff
changeset
|
1520 #endif /* not HAVE_GETHOSTNAME */ |
f9010847a5f5
(get_system_name): Use gethostname for USG systems
Richard M. Stallman <rms@gnu.org>
parents:
1203
diff
changeset
|
1521 #endif /* USG */ |
491 | 1522 |
1523 char * | |
1524 get_system_name () | |
1525 { | |
1526 #ifdef USG | |
1496
f9010847a5f5
(get_system_name): Use gethostname for USG systems
Richard M. Stallman <rms@gnu.org>
parents:
1203
diff
changeset
|
1527 #ifdef HAVE_GETHOSTNAME |
f9010847a5f5
(get_system_name): Use gethostname for USG systems
Richard M. Stallman <rms@gnu.org>
parents:
1203
diff
changeset
|
1528 gethostname (get_system_name_name, sizeof (get_system_name_name)); |
f9010847a5f5
(get_system_name): Use gethostname for USG systems
Richard M. Stallman <rms@gnu.org>
parents:
1203
diff
changeset
|
1529 return get_system_name_name; |
f9010847a5f5
(get_system_name): Use gethostname for USG systems
Richard M. Stallman <rms@gnu.org>
parents:
1203
diff
changeset
|
1530 #else /* not HAVE_GETHOSTNAME */ |
491 | 1531 uname (&get_system_name_name); |
1532 return (get_system_name_name.nodename); | |
1496
f9010847a5f5
(get_system_name): Use gethostname for USG systems
Richard M. Stallman <rms@gnu.org>
parents:
1203
diff
changeset
|
1533 #endif /* not HAVE_GETHOSTNAME */ |
491 | 1534 #else /* Not USG */ |
1535 #ifdef BSD4_1 | |
1536 return sysname; | |
1537 #else /* not USG, not 4.1 */ | |
1538 static char system_name_saved[32]; | |
1539 #ifdef VMS | |
1540 char *sp; | |
1541 if ((sp = egetenv ("SYS$NODE")) == 0) | |
1542 sp = "vax-vms"; | |
1543 else | |
1544 { | |
1545 char *end; | |
1546 | |
1547 if ((end = index (sp, ':')) != 0) | |
1548 *end = '\0'; | |
1549 } | |
1550 strcpy (system_name_saved, sp); | |
1551 #else /* not VMS */ | |
1552 gethostname (system_name_saved, sizeof (system_name_saved)); | |
1553 #endif /* not VMS */ | |
1554 return system_name_saved; | |
1555 #endif /* not USG, not 4.1 */ | |
1556 #endif /* not USG */ | |
1557 } | |
1558 | |
1559 #ifndef VMS | |
1560 #ifndef HAVE_SELECT | |
1561 | |
1562 #ifdef HAVE_X_WINDOWS | |
1563 /* Cause explanatory error message at compile time, | |
1564 since the select emulation is not good enough for X. */ | |
1565 int *x = &x_windows_lose_if_no_select_system_call; | |
1566 #endif | |
1567 | |
1568 /* Emulate as much as select as is possible under 4.1 and needed by Gnu Emacs | |
1569 * Only checks read descriptors. | |
1570 */ | |
1571 /* How long to wait between checking fds in select */ | |
1572 #define SELECT_PAUSE 1 | |
1573 int select_alarmed; | |
1574 | |
1575 /* For longjmp'ing back to read_input_waiting. */ | |
1576 | |
1577 jmp_buf read_alarm_throw; | |
1578 | |
1579 /* Nonzero if the alarm signal should throw back to read_input_waiting. | |
1580 The read_socket_hook function sets this to 1 while it is waiting. */ | |
1581 | |
1582 int read_alarm_should_throw; | |
1583 | |
1584 SIGTYPE | |
1585 select_alarm () | |
1586 { | |
1587 select_alarmed = 1; | |
1588 #ifdef BSD4_1 | |
1589 sigrelse (SIGALRM); | |
1590 #else /* not BSD4_1 */ | |
1591 signal (SIGALRM, SIG_IGN); | |
1592 #endif /* not BSD4_1 */ | |
1593 if (read_alarm_should_throw) | |
1594 longjmp (read_alarm_throw, 1); | |
1595 } | |
1596 | |
1597 /* Only rfds are checked. */ | |
1598 int | |
1599 select (nfds, rfds, wfds, efds, timeout) | |
1600 int nfds; | |
1601 int *rfds, *wfds, *efds, *timeout; | |
1602 { | |
1603 int ravail = 0, orfds = 0, old_alarm; | |
1604 int timeoutval = timeout ? *timeout : 100000; | |
1605 int *local_timeout = &timeoutval; | |
1606 extern int proc_buffered_char[]; | |
1607 #ifndef subprocesses | |
1608 int process_tick = 0, update_tick = 0; | |
1609 #else | |
1610 extern int process_tick, update_tick; | |
1611 #endif | |
1612 SIGTYPE (*old_trap) (); | |
1613 unsigned char buf; | |
1614 | |
1615 if (rfds) | |
1616 { | |
1617 orfds = *rfds; | |
1618 *rfds = 0; | |
1619 } | |
1620 if (wfds) | |
1621 *wfds = 0; | |
1622 if (efds) | |
1623 *efds = 0; | |
1624 | |
1625 /* If we are looking only for the terminal, with no timeout, | |
1626 just read it and wait -- that's more efficient. */ | |
1627 if (orfds == 1 && *local_timeout == 100000 && process_tick == update_tick) | |
1628 { | |
1629 if (! detect_input_pending ()) | |
1630 read_input_waiting (); | |
1631 *rfds = 1; | |
1632 return 1; | |
1633 } | |
1634 | |
1635 /* Once a second, till the timer expires, check all the flagged read | |
1636 * descriptors to see if any input is available. If there is some then | |
1637 * set the corresponding bit in the return copy of rfds. | |
1638 */ | |
1639 while (1) | |
1640 { | |
1641 register int to_check, bit, fd; | |
1642 | |
1643 if (rfds) | |
1644 { | |
1645 for (to_check = nfds, bit = 1, fd = 0; --to_check >= 0; bit <<= 1, fd++) | |
1646 { | |
1647 if (orfds & bit) | |
1648 { | |
1649 int avail = 0, status = 0; | |
1650 | |
1651 if (bit == 1) | |
1652 avail = detect_input_pending (); /* Special keyboard handler */ | |
1653 else | |
1654 { | |
1655 #ifdef FIONREAD | |
1656 status = ioctl (fd, FIONREAD, &avail); | |
1657 #else /* no FIONREAD */ | |
1658 /* Hoping it will return -1 if nothing available | |
1659 or 0 if all 0 chars requested are read. */ | |
1660 if (proc_buffered_char[fd] >= 0) | |
1661 avail = 1; | |
1662 else | |
1663 { | |
1664 avail = read (fd, &buf, 1); | |
1665 if (avail > 0) | |
1666 proc_buffered_char[fd] = buf; | |
1667 } | |
1668 #endif /* no FIONREAD */ | |
1669 } | |
1670 if (status >= 0 && avail > 0) | |
1671 { | |
1672 (*rfds) |= bit; | |
1673 ravail++; | |
1674 } | |
1675 } | |
1676 } | |
1677 } | |
1678 if (*local_timeout == 0 || ravail != 0 || process_tick != update_tick) | |
1679 break; | |
1680 old_alarm = alarm (0); | |
1014
6e25f9b75841
* sysdep.c (select): There's no need to cast the return value of
Jim Blandy <jimb@redhat.com>
parents:
766
diff
changeset
|
1681 old_trap = signal (SIGALRM, select_alarm); |
491 | 1682 select_alarmed = 0; |
1683 alarm (SELECT_PAUSE); | |
1684 /* Wait for a SIGALRM (or maybe a SIGTINT) */ | |
1685 while (select_alarmed == 0 && *local_timeout != 0 | |
1686 && process_tick == update_tick) | |
1687 { | |
1688 /* If we are interested in terminal input, | |
1689 wait by reading the terminal. | |
1690 That makes instant wakeup for terminal input at least. */ | |
1691 if (orfds & 1) | |
1692 { | |
1693 read_input_waiting (); | |
1694 if (detect_input_pending ()) | |
1695 select_alarmed = 1; | |
1696 } | |
1697 else | |
1698 pause (); | |
1699 } | |
1700 (*local_timeout) -= SELECT_PAUSE; | |
1701 /* Reset the old alarm if there was one */ | |
1702 alarm (0); | |
1703 signal (SIGALRM, old_trap); | |
1704 if (old_alarm != 0) | |
1705 { | |
1706 /* Reset or forge an interrupt for the original handler. */ | |
1707 old_alarm -= SELECT_PAUSE; | |
1708 if (old_alarm <= 0) | |
1709 kill (getpid (), SIGALRM); /* Fake an alarm with the orig' handler */ | |
1710 else | |
1711 alarm (old_alarm); | |
1712 } | |
1713 if (*local_timeout == 0) /* Stop on timer being cleared */ | |
1714 break; | |
1715 } | |
1716 return ravail; | |
1717 } | |
1718 | |
1719 /* Read keyboard input into the standard buffer, | |
1720 waiting for at least one character. */ | |
1721 | |
1722 /* Make all keyboard buffers much bigger when using X windows. */ | |
1723 #ifdef HAVE_X_WINDOWS | |
1724 #define BUFFER_SIZE_FACTOR 16 | |
1725 #else | |
1726 #define BUFFER_SIZE_FACTOR 1 | |
1727 #endif | |
1728 | |
1729 read_input_waiting () | |
1730 { | |
1731 char buf[256 * BUFFER_SIZE_FACTOR]; | |
1732 struct input_event e; | |
1014
6e25f9b75841
* sysdep.c (select): There's no need to cast the return value of
Jim Blandy <jimb@redhat.com>
parents:
766
diff
changeset
|
1733 int nread, i; |
6e25f9b75841
* sysdep.c (select): There's no need to cast the return value of
Jim Blandy <jimb@redhat.com>
parents:
766
diff
changeset
|
1734 extern int quit_char; |
491 | 1735 |
1736 if (read_socket_hook) | |
1737 { | |
1738 read_alarm_should_throw = 0; | |
1739 if (! setjmp (read_alarm_throw)) | |
1740 nread = (*read_socket_hook) (0, buf, 256 * BUFFER_SIZE_FACTOR, 1, 0); | |
1741 else | |
1742 nread = -1; | |
1743 } | |
1744 else | |
1745 nread = read (fileno (stdin), buf, 1); | |
1746 | |
1747 /* Scan the chars for C-g and store them in kbd_buffer. */ | |
1748 e.kind = ascii_keystroke; | |
766 | 1749 e.frame = selected_frame; |
491 | 1750 for (i = 0; i < nread; i++) |
1751 { | |
1752 XSET (e.code, Lisp_Int, buf[i]); | |
1753 kbd_buffer_store_event (&e); | |
1754 /* Don't look at input that follows a C-g too closely. | |
1755 This reduces lossage due to autorepeat on C-g. */ | |
1014
6e25f9b75841
* sysdep.c (select): There's no need to cast the return value of
Jim Blandy <jimb@redhat.com>
parents:
766
diff
changeset
|
1756 if (buf[i] == quit_char) |
491 | 1757 break; |
1758 } | |
1759 } | |
1760 | |
1761 #endif /* not HAVE_SELECT */ | |
1762 #endif /* not VMS */ | |
1763 | |
1764 #ifdef BSD4_1 | |
1765 /* | |
1766 * Partially emulate 4.2 open call. | |
1767 * open is defined as this in 4.1. | |
1768 * | |
1769 * - added by Michael Bloom @ Citicorp/TTI | |
1770 * | |
1771 */ | |
1772 | |
1773 int | |
1774 sys_open (path, oflag, mode) | |
1775 char *path; | |
1776 int oflag, mode; | |
1777 { | |
1778 if (oflag & O_CREAT) | |
1779 return creat (path, mode); | |
1780 else | |
1781 return open (path, oflag); | |
1782 } | |
1783 | |
1784 init_sigio () | |
1785 { | |
1786 if (noninteractive) | |
1787 return; | |
1788 lmode = LINTRUP | lmode; | |
1789 ioctl (0, TIOCLSET, &lmode); | |
1790 } | |
1791 | |
1792 reset_sigio () | |
1793 { | |
1794 if (noninteractive) | |
1795 return; | |
1796 lmode = ~LINTRUP & lmode; | |
1797 ioctl (0, TIOCLSET, &lmode); | |
1798 } | |
1799 | |
1800 request_sigio () | |
1801 { | |
1802 sigrelse (SIGTINT); | |
1803 | |
1804 interrupts_deferred = 0; | |
1805 } | |
1806 | |
1807 unrequest_sigio () | |
1808 { | |
1809 sighold (SIGTINT); | |
1810 | |
1811 interrupts_deferred = 1; | |
1812 } | |
1813 | |
1814 /* still inside #ifdef BSD4_1 */ | |
1815 #ifdef subprocesses | |
1816 | |
1817 int sigheld; /* Mask of held signals */ | |
1818 | |
1819 sigholdx (signum) | |
1820 int signum; | |
1821 { | |
1822 sigheld |= sigbit (signum); | |
1823 sighold (signum); | |
1824 } | |
1825 | |
1826 sigisheld (signum) | |
1827 int signum; | |
1828 { | |
1829 sigheld |= sigbit (signum); | |
1830 } | |
1831 | |
1832 sigunhold (signum) | |
1833 int signum; | |
1834 { | |
1835 sigheld &= ~sigbit (signum); | |
1836 sigrelse (signum); | |
1837 } | |
1838 | |
1839 sigfree () /* Free all held signals */ | |
1840 { | |
1841 int i; | |
1842 for (i = 0; i < NSIG; i++) | |
1843 if (sigheld & sigbit (i)) | |
1844 sigrelse (i); | |
1845 sigheld = 0; | |
1846 } | |
1847 | |
1848 sigbit (i) | |
1849 { | |
1850 return 1 << (i - 1); | |
1851 } | |
1852 #endif /* subprocesses */ | |
1853 #endif /* BSD4_1 */ | |
1854 | |
1855 /* POSIX signals support - DJB */ | |
1856 /* Anyone with POSIX signals should have ANSI C declarations */ | |
1857 | |
1858 #ifdef POSIX_SIGNALS | |
1859 | |
1860 sigset_t old_mask, empty_mask, full_mask, temp_mask; | |
1861 static struct sigaction new_action, old_action; | |
1862 | |
1863 init_signals () | |
1864 { | |
1865 #ifdef POSIX_SIGNALS | |
1866 sigemptyset (&signal_empty_mask); | |
1867 sigfillset (&signal_full_mask); | |
1868 #endif | |
1869 } | |
1870 | |
1871 int (*signal_handler_t) (); | |
1872 | |
1873 signal_handler_t | |
1874 sys_signal (int signal_number, signal_handler_t action) | |
1875 { | |
1876 #ifdef DGUX | |
1877 /* This gets us restartable system calls for efficiency. | |
1878 The "else" code will works as well. */ | |
1879 return (berk_signal (signal_number, action)); | |
1880 #else | |
1881 sigemptyset (&new_action.sa_mask); | |
1882 new_action.sa_handler = action; | |
1883 new_action.sa_flags = NULL; | |
709 | 1884 sigaction (signal_number, &new_action, &old_action); |
491 | 1885 return (old_action.sa_handler); |
1886 #endif /* DGUX */ | |
1887 } | |
1888 | |
638 | 1889 #ifndef __GNUC__ |
1890 /* If we're compiling with GCC, we don't need this function, since it | |
1891 can be written as a macro. */ | |
1892 sigset_t | |
1893 sys_sigmask (int sig) | |
1894 { | |
1895 sigset_t mask; | |
1896 sigemptyset (&mask); | |
1897 sigaddset (&mask, sig); | |
1898 return mask; | |
1899 } | |
1900 #endif | |
1901 | |
491 | 1902 int |
1903 sys_sigpause (sigset_t new_mask) | |
1904 { | |
1905 /* pause emulating berk sigpause... */ | |
1906 sigsuspend (&new_mask); | |
1907 return (EINTR); | |
1908 } | |
1909 | |
1910 /* I'd like to have these guys return pointers to the mask storage in here, | |
1911 but there'd be trouble if the code was saving multiple masks. I'll be | |
1912 safe and pass the structure. It normally won't be more than 2 bytes | |
1913 anyhow. - DJB */ | |
1914 | |
1915 sigset_t | |
1916 sys_sigblock (sigset_t new_mask) | |
1917 { | |
1918 sigset_t old_mask; | |
1919 sigprocmask (SIG_BLOCK, &new_mask, &old_mask); | |
1920 return (old_mask); | |
1921 } | |
1922 | |
1923 sigset_t | |
1924 sys_sigunblock (sigset_t new_mask) | |
1925 { | |
1926 sigset_t old_mask; | |
1927 sigprocmask (SIG_UNBLOCK, &new_mask, &old_mask); | |
1928 return (old_mask); | |
1929 } | |
1930 | |
1931 sigset_t | |
1932 sys_sigsetmask (sigset_t new_mask) | |
1933 { | |
1934 sigset_t old_mask; | |
1935 sigprocmask (SIG_SETMASK, &new_mask, &old_mask); | |
1936 return (old_mask); | |
1937 } | |
1938 | |
1939 #endif /* POSIX_SIGNALS */ | |
1940 | |
1941 #ifndef BSTRING | |
1942 | |
1943 void | |
1944 bzero (b, length) | |
1945 register char *b; | |
1946 register int length; | |
1947 { | |
1948 #ifdef VMS | |
1949 short zero = 0; | |
1950 long max_str = 65535; | |
1951 | |
1952 while (length > max_str) { | |
1953 (void) LIB$MOVC5 (&zero, &zero, &zero, &max_str, b); | |
1954 length -= max_str; | |
1955 b += max_str; | |
1956 } | |
1957 max_str = length; | |
1958 (void) LIB$MOVC5 (&zero, &zero, &zero, &max_str, b); | |
1959 #else | |
1960 while (length-- > 0) | |
1961 *b++ = 0; | |
1962 #endif /* not VMS */ | |
1963 } | |
1964 | |
1965 /* Saying `void' requires a declaration, above, where bcopy is used | |
1966 and that declaration causes pain for systems where bcopy is a macro. */ | |
1967 bcopy (b1, b2, length) | |
1968 register char *b1; | |
1969 register char *b2; | |
1970 register int length; | |
1971 { | |
1972 #ifdef VMS | |
1973 long max_str = 65535; | |
1974 | |
1975 while (length > max_str) { | |
1976 (void) LIB$MOVC3 (&max_str, b1, b2); | |
1977 length -= max_str; | |
1978 b1 += max_str; | |
1979 b2 += max_str; | |
1980 } | |
1981 max_str = length; | |
1982 (void) LIB$MOVC3 (&length, b1, b2); | |
1983 #else | |
1984 while (length-- > 0) | |
1985 *b2++ = *b1++; | |
1986 #endif /* not VMS */ | |
1987 } | |
1988 | |
1989 int | |
1990 bcmp (b1, b2, length) /* This could be a macro! */ | |
1991 register char *b1; | |
1992 register char *b2; | |
1993 register int length; | |
1994 { | |
1995 #ifdef VMS | |
1996 struct dsc$descriptor_s src1 = {length, DSC$K_DTYPE_T, DSC$K_CLASS_S, b1}; | |
1997 struct dsc$descriptor_s src2 = {length, DSC$K_DTYPE_T, DSC$K_CLASS_S, b2}; | |
1998 | |
1999 return STR$COMPARE (&src1, &src2); | |
2000 #else | |
2001 while (length-- > 0) | |
2002 if (*b1++ != *b2++) | |
2003 return 1; | |
2004 | |
2005 return 0; | |
2006 #endif /* not VMS */ | |
2007 } | |
2008 #endif /* not BSTRING */ | |
2009 | |
2010 #ifdef USG | |
2011 /* | |
2012 * The BSD random returns numbers in the range of | |
2013 * 0 to 2e31 - 1. The USG rand returns numbers in the | |
2014 * range of 0 to 2e15 - 1. This is probably not significant | |
2015 * in this usage. | |
2016 */ | |
2017 | |
2018 long | |
2019 random () | |
2020 { | |
2021 /* Arrange to return a range centered on zero. */ | |
2022 return (rand () << 15) + rand () - (1 << 29); | |
2023 } | |
2024 | |
2025 srandom (arg) | |
2026 int arg; | |
2027 { | |
2028 srand (arg); | |
2029 } | |
2030 | |
2031 #endif /* USG */ | |
2032 | |
2033 #ifdef BSD4_1 | |
2034 long random () | |
2035 { | |
2036 /* Arrange to return a range centered on zero. */ | |
2037 return (rand () << 15) + rand () - (1 << 29); | |
2038 } | |
2039 | |
2040 srandom (arg) | |
2041 int arg; | |
2042 { | |
2043 srand (arg); | |
2044 } | |
2045 #endif /* BSD4_1 */ | |
2046 | |
2047 #ifdef WRONG_NAME_INSQUE | |
2048 | |
2049 insque (q,p) | |
2050 caddr_t q,p; | |
2051 { | |
2052 _insque (q,p); | |
2053 } | |
2054 | |
2055 #endif | |
2056 | |
2057 #ifdef VMS | |
2058 | |
2059 #ifdef getenv | |
2060 /* If any place else asks for the TERM variable, | |
2061 allow it to be overridden with the EMACS_TERM variable | |
2062 before attempting to translate the logical name TERM. As a last | |
2063 resort, ask for VAX C's special idea of the TERM variable. */ | |
2064 #undef getenv | |
2065 char * | |
2066 sys_getenv (name) | |
2067 char *name; | |
2068 { | |
2069 register char *val; | |
2070 static char buf[256]; | |
2071 static struct dsc$descriptor_s equiv | |
2072 = {sizeof (buf), DSC$K_DTYPE_T, DSC$K_CLASS_S, buf}; | |
2073 static struct dsc$descriptor_s d_name | |
2074 = {0, DSC$K_DTYPE_T, DSC$K_CLASS_S, 0}; | |
2075 short eqlen; | |
2076 | |
2077 if (!strcmp (name, "TERM")) | |
2078 { | |
2079 val = (char *) getenv ("EMACS_TERM"); | |
2080 if (val) | |
2081 return val; | |
2082 } | |
2083 | |
2084 d_name.dsc$w_length = strlen (name); | |
2085 d_name.dsc$a_pointer = name; | |
1596
0e105bd23f44
* systty.h, process.c, buffer.h, callproc.c, sysdep.c, dired.c:
Jim Blandy <jimb@redhat.com>
parents:
1570
diff
changeset
|
2086 if (LIB$SYS_TRNLOG (&d_name, &eqlen, &equiv) == 1) |
491 | 2087 { |
2088 char *str = (char *) xmalloc (eqlen + 1); | |
2089 bcopy (buf, str, eqlen); | |
2090 str[eqlen] = '\0'; | |
2091 /* This is a storage leak, but a pain to fix. With luck, | |
2092 no one will ever notice. */ | |
2093 return str; | |
2094 } | |
2095 return (char *) getenv (name); | |
2096 } | |
2097 #endif /* getenv */ | |
2098 | |
2099 #ifdef abort | |
2100 /* Since VMS doesn't believe in core dumps, the only way to debug this beast is | |
2101 to force a call on the debugger from within the image. */ | |
2102 #undef abort | |
2103 sys_abort () | |
2104 { | |
2105 reset_sys_modes (); | |
2106 LIB$SIGNAL (SS$_DEBUG); | |
2107 } | |
2108 #endif /* abort */ | |
2109 #endif /* VMS */ | |
2110 | |
2111 #ifdef VMS | |
2112 #ifdef LINK_CRTL_SHARE | |
2113 #ifdef SHAREABLE_LIB_BUG | |
2114 /* Variables declared noshare and initialized in shareable libraries | |
2115 cannot be shared. The VMS linker incorrectly forces you to use a private | |
2116 version which is uninitialized... If not for this "feature", we | |
2117 could use the C library definition of sys_nerr and sys_errlist. */ | |
2118 int sys_nerr = 35; | |
2119 char *sys_errlist[] = | |
2120 { | |
2121 "error 0", | |
2122 "not owner", | |
2123 "no such file or directory", | |
2124 "no such process", | |
2125 "interrupted system call", | |
2126 "i/o error", | |
2127 "no such device or address", | |
2128 "argument list too long", | |
2129 "exec format error", | |
2130 "bad file number", | |
2131 "no child process", | |
2132 "no more processes", | |
2133 "not enough memory", | |
2134 "permission denied", | |
2135 "bad address", | |
2136 "block device required", | |
2137 "mount devices busy", | |
2138 "file exists", | |
2139 "cross-device link", | |
2140 "no such device", | |
2141 "not a directory", | |
2142 "is a directory", | |
2143 "invalid argument", | |
2144 "file table overflow", | |
2145 "too many open files", | |
2146 "not a typewriter", | |
2147 "text file busy", | |
2148 "file too big", | |
2149 "no space left on device", | |
2150 "illegal seek", | |
2151 "read-only file system", | |
2152 "too many links", | |
2153 "broken pipe", | |
2154 "math argument", | |
2155 "result too large", | |
2156 "I/O stream empty", | |
2157 "vax/vms specific error code nontranslatable error" | |
2158 }; | |
2159 #endif /* SHAREABLE_LIB_BUG */ | |
2160 #endif /* LINK_CRTL_SHARE */ | |
2161 #endif /* VMS */ | |
2162 | |
2163 #ifdef INTERRUPTIBLE_OPEN | |
2164 | |
2165 int | |
2166 /* VARARGS 2 */ | |
2167 sys_open (path, oflag, mode) | |
2168 char *path; | |
2169 int oflag, mode; | |
2170 { | |
2171 register int rtnval; | |
2172 | |
2173 while ((rtnval = open (path, oflag, mode)) == -1 | |
2174 && (errno == EINTR)); | |
2175 return (rtnval); | |
2176 } | |
2177 | |
2178 #endif /* INTERRUPTIBLE_OPEN */ | |
2179 | |
2180 #ifdef INTERRUPTIBLE_CLOSE | |
2181 | |
2182 sys_close (fd) | |
2183 int fd; | |
2184 { | |
2185 register int rtnval; | |
2186 | |
2187 while ((rtnval = close (fd)) == -1 | |
2188 && (errno == EINTR)); | |
2189 return rtnval; | |
2190 } | |
2191 | |
2192 #endif /* INTERRUPTIBLE_CLOSE */ | |
2193 | |
2194 #ifdef INTERRUPTIBLE_IO | |
2195 | |
2196 int | |
2197 sys_read (fildes, buf, nbyte) | |
2198 int fildes; | |
2199 char *buf; | |
2200 unsigned int nbyte; | |
2201 { | |
2202 register int rtnval; | |
2203 | |
2204 while ((rtnval = read (fildes, buf, nbyte)) == -1 | |
2205 && (errno == EINTR)); | |
2206 return (rtnval); | |
2207 } | |
2208 | |
2209 int | |
2210 sys_write (fildes, buf, nbyte) | |
2211 int fildes; | |
2212 char *buf; | |
2213 unsigned int nbyte; | |
2214 { | |
2215 register int rtnval; | |
2216 | |
2217 while ((rtnval = write (fildes, buf, nbyte)) == -1 | |
2218 && (errno == EINTR)); | |
2219 return (rtnval); | |
2220 } | |
2221 | |
2222 #endif /* INTERRUPTIBLE_IO */ | |
2223 | |
2224 #ifdef USG | |
2225 /* | |
2226 * All of the following are for USG. | |
2227 * | |
2228 * On USG systems the system calls are INTERRUPTIBLE by signals | |
2229 * that the user program has elected to catch. Thus the system call | |
2230 * must be retried in these cases. To handle this without massive | |
2231 * changes in the source code, we remap the standard system call names | |
2232 * to names for our own functions in sysdep.c that do the system call | |
2233 * with retries. Actually, for portability reasons, it is good | |
2234 * programming practice, as this example shows, to limit all actual | |
2235 * system calls to a single occurance in the source. Sure, this | |
2236 * adds an extra level of function call overhead but it is almost | |
2237 * always negligible. Fred Fish, Unisoft Systems Inc. | |
2238 */ | |
2239 | |
2240 char *sys_siglist[NSIG + 1] = | |
2241 { | |
2242 #ifdef AIX | |
2243 /* AIX has changed the signals a bit */ | |
2244 "bogus signal", /* 0 */ | |
2245 "hangup", /* 1 SIGHUP */ | |
2246 "interrupt", /* 2 SIGINT */ | |
2247 "quit", /* 3 SIGQUIT */ | |
2248 "illegal instruction", /* 4 SIGILL */ | |
2249 "trace trap", /* 5 SIGTRAP */ | |
2250 "IOT instruction", /* 6 SIGIOT */ | |
2251 "crash likely", /* 7 SIGDANGER */ | |
2252 "floating point exception", /* 8 SIGFPE */ | |
2253 "kill", /* 9 SIGKILL */ | |
2254 "bus error", /* 10 SIGBUS */ | |
2255 "segmentation violation", /* 11 SIGSEGV */ | |
2256 "bad argument to system call", /* 12 SIGSYS */ | |
2257 "write on a pipe with no one to read it", /* 13 SIGPIPE */ | |
2258 "alarm clock", /* 14 SIGALRM */ | |
2259 "software termination signum", /* 15 SIGTERM */ | |
2260 "user defined signal 1", /* 16 SIGUSR1 */ | |
2261 "user defined signal 2", /* 17 SIGUSR2 */ | |
2262 "death of a child", /* 18 SIGCLD */ | |
2263 "power-fail restart", /* 19 SIGPWR */ | |
2264 "bogus signal", /* 20 */ | |
2265 "bogus signal", /* 21 */ | |
2266 "bogus signal", /* 22 */ | |
2267 "bogus signal", /* 23 */ | |
2268 "bogus signal", /* 24 */ | |
2269 "LAN I/O interrupt", /* 25 SIGAIO */ | |
2270 "PTY I/O interrupt", /* 26 SIGPTY */ | |
2271 "I/O intervention required", /* 27 SIGIOINT */ | |
2272 "HFT grant", /* 28 SIGGRANT */ | |
2273 "HFT retract", /* 29 SIGRETRACT */ | |
2274 "HFT sound done", /* 30 SIGSOUND */ | |
2275 "HFT input ready", /* 31 SIGMSG */ | |
2276 #else /* not AIX */ | |
2277 "bogus signal", /* 0 */ | |
2278 "hangup", /* 1 SIGHUP */ | |
2279 "interrupt", /* 2 SIGINT */ | |
2280 "quit", /* 3 SIGQUIT */ | |
2281 "illegal instruction", /* 4 SIGILL */ | |
2282 "trace trap", /* 5 SIGTRAP */ | |
2283 "IOT instruction", /* 6 SIGIOT */ | |
2284 "EMT instruction", /* 7 SIGEMT */ | |
2285 "floating point exception", /* 8 SIGFPE */ | |
2286 "kill", /* 9 SIGKILL */ | |
2287 "bus error", /* 10 SIGBUS */ | |
2288 "segmentation violation", /* 11 SIGSEGV */ | |
2289 "bad argument to system call", /* 12 SIGSYS */ | |
2290 "write on a pipe with no one to read it", /* 13 SIGPIPE */ | |
2291 "alarm clock", /* 14 SIGALRM */ | |
2292 "software termination signum", /* 15 SIGTERM */ | |
2293 "user defined signal 1", /* 16 SIGUSR1 */ | |
2294 "user defined signal 2", /* 17 SIGUSR2 */ | |
2295 "death of a child", /* 18 SIGCLD */ | |
2296 "power-fail restart", /* 19 SIGPWR */ | |
2297 #endif /* not AIX */ | |
2298 0 | |
2299 }; | |
2300 | |
2301 /* | |
2302 * Warning, this function may not duplicate 4.2 action properly | |
2303 * under error conditions. | |
2304 */ | |
2305 | |
2306 #ifndef MAXPATHLEN | |
2307 /* In 4.1, param.h fails to define this. */ | |
2308 #define MAXPATHLEN 1024 | |
2309 #endif | |
2310 | |
2311 #ifndef HAVE_GETWD | |
2312 | |
2313 char * | |
2314 getwd (pathname) | |
2315 char *pathname; | |
2316 { | |
2317 char *npath, *spath; | |
2318 extern char *getcwd (); | |
2319 | |
2320 spath = npath = getcwd ((char *) 0, MAXPATHLEN); | |
2321 /* On Altos 3068, getcwd can return @hostname/dir, so discard | |
2322 up to first slash. Should be harmless on other systems. */ | |
2323 while (*npath && *npath != '/') | |
2324 npath++; | |
2325 strcpy (pathname, npath); | |
2326 free (spath); /* getcwd uses malloc */ | |
2327 return pathname; | |
2328 } | |
2329 | |
2330 #endif /* HAVE_GETWD */ | |
2331 | |
2332 /* | |
2333 * Emulate rename using unlink/link. Note that this is | |
2334 * only partially correct. Also, doesn't enforce restriction | |
2335 * that files be of same type (regular->regular, dir->dir, etc). | |
2336 */ | |
2337 | |
621 | 2338 #ifndef HAVE_RENAME |
2339 | |
491 | 2340 rename (from, to) |
2341 char *from; | |
2342 char *to; | |
2343 { | |
2344 if (access (from, 0) == 0) | |
2345 { | |
2346 unlink (to); | |
2347 if (link (from, to) == 0) | |
2348 if (unlink (from) == 0) | |
2349 return (0); | |
2350 } | |
2351 return (-1); | |
2352 } | |
2353 | |
621 | 2354 #endif |
2355 | |
491 | 2356 #ifndef HAVE_VFORK |
2357 | |
2358 /* | |
2359 * Substitute fork for vfork on USG flavors. | |
2360 */ | |
2361 | |
2362 vfork () | |
2363 { | |
2364 return (fork ()); | |
2365 } | |
2366 | |
2367 #endif /* not HAVE_VFORK */ | |
2368 | |
2369 #ifdef MISSING_UTIMES | |
2370 | |
2371 /* HPUX (among others) sets HAVE_TIMEVAL but does not implement utimes. */ | |
2372 | |
2373 utimes () | |
2374 { | |
2375 } | |
2376 #endif | |
2377 | |
2378 #ifdef IRIS_UTIME | |
2379 | |
2380 /* The IRIS (3.5) has timevals, but uses sys V utime, and doesn't have the | |
2381 utimbuf structure defined anywhere but in the man page. */ | |
2382 | |
2383 struct utimbuf | |
2384 { | |
2385 long actime; | |
2386 long modtime; | |
2387 }; | |
2388 | |
2389 utimes (name, tvp) | |
2390 char *name; | |
2391 struct timeval tvp[]; | |
2392 { | |
2393 struct utimbuf utb; | |
2394 utb.actime = tvp[0].tv_sec; | |
2395 utb.modtime = tvp[1].tv_sec; | |
2396 utime (name, &utb); | |
2397 } | |
2398 #endif /* IRIS_UTIME */ | |
2399 | |
2400 | |
2401 #ifdef HPUX | |
2402 #ifndef HAVE_PERROR | |
2403 | |
2404 /* HPUX curses library references perror, but as far as we know | |
2405 it won't be called. Anyway this definition will do for now. */ | |
2406 | |
2407 perror () | |
2408 { | |
2409 } | |
2410 | |
2411 #endif /* not HAVE_PERROR */ | |
2412 #endif /* HPUX */ | |
2413 | |
2414 #ifndef HAVE_DUP2 | |
2415 | |
2416 /* | |
2417 * Emulate BSD dup2. First close newd if it already exists. | |
2418 * Then, attempt to dup oldd. If not successful, call dup2 recursively | |
2419 * until we are, then close the unsuccessful ones. | |
2420 */ | |
2421 | |
2422 dup2 (oldd, newd) | |
2423 int oldd; | |
2424 int newd; | |
2425 { | |
2426 register int fd, ret; | |
2427 | |
2428 sys_close (newd); | |
2429 | |
2430 #ifdef F_DUPFD | |
2431 fd = fcntl (oldd, F_DUPFD, newd); | |
2432 if (fd != newd) | |
2433 error ("can't dup2 (%i,%i) : %s", oldd, newd, sys_errlist[errno]); | |
2434 #else | |
2435 fd = dup (old); | |
2436 if (fd == -1) | |
2437 return -1; | |
2438 if (fd == new) | |
2439 return new; | |
2440 ret = dup2 (old,new); | |
2441 sys_close (fd); | |
2442 return ret; | |
2443 #endif | |
2444 } | |
2445 | |
2446 #endif /* not HAVE_DUP2 */ | |
2447 | |
2448 /* | |
2449 * Gettimeofday. Simulate as much as possible. Only accurate | |
2450 * to nearest second. Emacs doesn't use tzp so ignore it for now. | |
2451 * Only needed when subprocesses are defined. | |
2452 */ | |
2453 | |
2454 #ifdef subprocesses | |
2455 #ifndef VMS | |
2456 #ifndef HAVE_GETTIMEOFDAY | |
2457 #ifdef HAVE_TIMEVAL | |
2458 | |
2459 /* ARGSUSED */ | |
2460 gettimeofday (tp, tzp) | |
2461 struct timeval *tp; | |
2462 struct timezone *tzp; | |
2463 { | |
2464 extern long time (); | |
2465 | |
2466 tp->tv_sec = time ((long *)0); | |
2467 tp->tv_usec = 0; | |
2468 tzp->tz_minuteswest = -1; | |
2469 } | |
2470 | |
2471 #endif | |
2472 #endif | |
2473 #endif | |
2474 #endif /* subprocess && !HAVE_GETTIMEOFDAY && HAVE_TIMEVAL && !VMS */ | |
2475 | |
2476 /* | |
2477 * This function will go away as soon as all the stubs fixed. (fnf) | |
2478 */ | |
2479 | |
2480 croak (badfunc) | |
2481 char *badfunc; | |
2482 { | |
2483 printf ("%s not yet implemented\r\n", badfunc); | |
2484 reset_sys_modes (); | |
2485 exit (1); | |
2486 } | |
2487 | |
2488 #endif /* USG */ | |
2489 | |
2490 #ifdef DGUX | |
2491 | |
2492 char *sys_siglist[NSIG + 1] = | |
2493 { | |
2494 "null signal", /* 0 SIGNULL */ | |
2495 "hangup", /* 1 SIGHUP */ | |
2496 "interrupt", /* 2 SIGINT */ | |
2497 "quit", /* 3 SIGQUIT */ | |
2498 "illegal instruction", /* 4 SIGILL */ | |
2499 "trace trap", /* 5 SIGTRAP */ | |
2500 "abort termination", /* 6 SIGABRT */ | |
2501 "SIGEMT", /* 7 SIGEMT */ | |
2502 "floating point exception", /* 8 SIGFPE */ | |
2503 "kill", /* 9 SIGKILL */ | |
2504 "bus error", /* 10 SIGBUS */ | |
2505 "segmentation violation", /* 11 SIGSEGV */ | |
2506 "bad argument to system call", /* 12 SIGSYS */ | |
2507 "write on a pipe with no reader", /* 13 SIGPIPE */ | |
2508 "alarm clock", /* 14 SIGALRM */ | |
2509 "software termination signal", /* 15 SIGTERM */ | |
2510 "user defined signal 1", /* 16 SIGUSR1 */ | |
2511 "user defined signal 2", /* 17 SIGUSR2 */ | |
2512 "child stopped or terminated", /* 18 SIGCLD */ | |
2513 "power-fail restart", /* 19 SIGPWR */ | |
2514 "window size changed", /* 20 SIGWINCH */ | |
2515 "undefined", /* 21 */ | |
2516 "pollable event occured", /* 22 SIGPOLL */ | |
2517 "sendable stop signal not from tty", /* 23 SIGSTOP */ | |
2518 "stop signal from tty", /* 24 SIGSTP */ | |
2519 "continue a stopped process", /* 25 SIGCONT */ | |
2520 "attempted background tty read", /* 26 SIGTTIN */ | |
2521 "attempted background tty write", /* 27 SIGTTOU */ | |
2522 "undefined", /* 28 */ | |
2523 "undefined", /* 29 */ | |
2524 "undefined", /* 30 */ | |
2525 "undefined", /* 31 */ | |
2526 "undefined", /* 32 */ | |
2527 "socket (TCP/IP) urgent data arrival", /* 33 SIGURG */ | |
2528 "I/O is possible", /* 34 SIGIO */ | |
2529 "exceeded cpu time limit", /* 35 SIGXCPU */ | |
2530 "exceeded file size limit", /* 36 SIGXFSZ */ | |
2531 "virtual time alarm", /* 37 SIGVTALRM */ | |
2532 "profiling time alarm", /* 38 SIGPROF */ | |
2533 "undefined", /* 39 */ | |
2534 "file record locks revoked", /* 40 SIGLOST */ | |
2535 "undefined", /* 41 */ | |
2536 "undefined", /* 42 */ | |
2537 "undefined", /* 43 */ | |
2538 "undefined", /* 44 */ | |
2539 "undefined", /* 45 */ | |
2540 "undefined", /* 46 */ | |
2541 "undefined", /* 47 */ | |
2542 "undefined", /* 48 */ | |
2543 "undefined", /* 49 */ | |
2544 "undefined", /* 50 */ | |
2545 "undefined", /* 51 */ | |
2546 "undefined", /* 52 */ | |
2547 "undefined", /* 53 */ | |
2548 "undefined", /* 54 */ | |
2549 "undefined", /* 55 */ | |
2550 "undefined", /* 56 */ | |
2551 "undefined", /* 57 */ | |
2552 "undefined", /* 58 */ | |
2553 "undefined", /* 59 */ | |
2554 "undefined", /* 60 */ | |
2555 "undefined", /* 61 */ | |
2556 "undefined", /* 62 */ | |
2557 "undefined", /* 63 */ | |
2558 "notification message in mess. queue", /* 64 SIGDGNOTIFY */ | |
2559 0 | |
2560 }; | |
2561 | |
2562 #endif /* DGUX */ | |
2563 | |
2564 /* Directory routines for systems that don't have them. */ | |
2565 | |
2566 #ifdef SYSV_SYSTEM_DIR | |
2567 | |
2568 #include <dirent.h> | |
2569 | |
2570 #ifndef AIX | |
2571 int | |
2572 closedir (dirp) | |
2573 register DIR *dirp; /* stream from opendir */ | |
2574 { | |
2575 sys_close (dirp->dd_fd); | |
2576 free ((char *) dirp->dd_buf); /* directory block defined in <dirent.h> */ | |
2577 free ((char *) dirp); | |
2578 } | |
2579 #endif /* not AIX */ | |
2580 #endif /* SYSV_SYSTEM_DIR */ | |
2581 | |
2582 #ifdef NONSYSTEM_DIR_LIBRARY | |
2583 | |
2584 DIR * | |
2585 opendir (filename) | |
2586 char *filename; /* name of directory */ | |
2587 { | |
2588 register DIR *dirp; /* -> malloc'ed storage */ | |
2589 register int fd; /* file descriptor for read */ | |
2590 struct stat sbuf; /* result of fstat */ | |
2591 | |
2592 fd = sys_open (filename, 0); | |
2593 if (fd < 0) | |
2594 return 0; | |
2595 | |
2596 if (fstat (fd, &sbuf) < 0 | |
2597 || (sbuf.st_mode & S_IFMT) != S_IFDIR | |
2598 || (dirp = (DIR *) malloc (sizeof (DIR))) == 0) | |
2599 { | |
2600 sys_close (fd); | |
2601 return 0; /* bad luck today */ | |
2602 } | |
2603 | |
2604 dirp->dd_fd = fd; | |
2605 dirp->dd_loc = dirp->dd_size = 0; /* refill needed */ | |
2606 | |
2607 return dirp; | |
2608 } | |
2609 | |
2610 void | |
2611 closedir (dirp) | |
2612 register DIR *dirp; /* stream from opendir */ | |
2613 { | |
2614 sys_close (dirp->dd_fd); | |
2615 free ((char *) dirp); | |
2616 } | |
2617 | |
2618 | |
2619 #ifndef VMS | |
2620 #define DIRSIZ 14 | |
2621 struct olddir | |
2622 { | |
2623 ino_t od_ino; /* inode */ | |
2624 char od_name[DIRSIZ]; /* filename */ | |
2625 }; | |
2626 #endif /* not VMS */ | |
2627 | |
2628 struct direct dir_static; /* simulated directory contents */ | |
2629 | |
2630 /* ARGUSED */ | |
2631 struct direct * | |
2632 readdir (dirp) | |
2633 register DIR *dirp; /* stream from opendir */ | |
2634 { | |
2635 #ifndef VMS | |
2636 register struct olddir *dp; /* -> directory data */ | |
2637 #else /* VMS */ | |
2638 register struct dir$_name *dp; /* -> directory data */ | |
2639 register struct dir$_version *dv; /* -> version data */ | |
2640 #endif /* VMS */ | |
2641 | |
2642 for (; ;) | |
2643 { | |
2644 if (dirp->dd_loc >= dirp->dd_size) | |
2645 dirp->dd_loc = dirp->dd_size = 0; | |
2646 | |
2647 if (dirp->dd_size == 0 /* refill buffer */ | |
2648 && (dirp->dd_size = sys_read (dirp->dd_fd, dirp->dd_buf, DIRBLKSIZ)) <= 0) | |
2649 return 0; | |
2650 | |
2651 #ifndef VMS | |
2652 dp = (struct olddir *) &dirp->dd_buf[dirp->dd_loc]; | |
2653 dirp->dd_loc += sizeof (struct olddir); | |
2654 | |
2655 if (dp->od_ino != 0) /* not deleted entry */ | |
2656 { | |
2657 dir_static.d_ino = dp->od_ino; | |
2658 strncpy (dir_static.d_name, dp->od_name, DIRSIZ); | |
2659 dir_static.d_name[DIRSIZ] = '\0'; | |
2660 dir_static.d_namlen = strlen (dir_static.d_name); | |
2661 dir_static.d_reclen = sizeof (struct direct) | |
2662 - MAXNAMLEN + 3 | |
2663 + dir_static.d_namlen - dir_static.d_namlen % 4; | |
2664 return &dir_static; /* -> simulated structure */ | |
2665 } | |
2666 #else /* VMS */ | |
2667 dp = (struct dir$_name *) dirp->dd_buf; | |
2668 if (dirp->dd_loc == 0) | |
2669 dirp->dd_loc = (dp->dir$b_namecount&1) ? dp->dir$b_namecount + 1 | |
2670 : dp->dir$b_namecount; | |
2671 dv = (struct dir$_version *)&dp->dir$t_name[dirp->dd_loc]; | |
2672 dir_static.d_ino = dv->dir$w_fid_num; | |
2673 dir_static.d_namlen = dp->dir$b_namecount; | |
2674 dir_static.d_reclen = sizeof (struct direct) | |
2675 - MAXNAMLEN + 3 | |
2676 + dir_static.d_namlen - dir_static.d_namlen % 4; | |
2677 strncpy (dir_static.d_name, dp->dir$t_name, dp->dir$b_namecount); | |
2678 dir_static.d_name[dir_static.d_namlen] = '\0'; | |
2679 dirp->dd_loc = dirp->dd_size; /* only one record at a time */ | |
2680 return &dir_static; | |
2681 #endif /* VMS */ | |
2682 } | |
2683 } | |
2684 | |
2685 #ifdef VMS | |
2686 /* readdirver is just like readdir except it returns all versions of a file | |
2687 as separate entries. */ | |
2688 | |
2689 /* ARGUSED */ | |
2690 struct direct * | |
2691 readdirver (dirp) | |
2692 register DIR *dirp; /* stream from opendir */ | |
2693 { | |
2694 register struct dir$_name *dp; /* -> directory data */ | |
2695 register struct dir$_version *dv; /* -> version data */ | |
2696 | |
2697 if (dirp->dd_loc >= dirp->dd_size - sizeof (struct dir$_name)) | |
2698 dirp->dd_loc = dirp->dd_size = 0; | |
2699 | |
2700 if (dirp->dd_size == 0 /* refill buffer */ | |
2701 && (dirp->dd_size = sys_read (dirp->dd_fd, dirp->dd_buf, DIRBLKSIZ)) <= 0) | |
2702 return 0; | |
2703 | |
2704 dp = (struct dir$_name *) dirp->dd_buf; | |
2705 if (dirp->dd_loc == 0) | |
2706 dirp->dd_loc = (dp->dir$b_namecount & 1) ? dp->dir$b_namecount + 1 | |
2707 : dp->dir$b_namecount; | |
2708 dv = (struct dir$_version *) &dp->dir$t_name[dirp->dd_loc]; | |
2709 strncpy (dir_static.d_name, dp->dir$t_name, dp->dir$b_namecount); | |
2710 sprintf (&dir_static.d_name[dp->dir$b_namecount], ";%d", dv->dir$w_version); | |
2711 dir_static.d_namlen = strlen (dir_static.d_name); | |
2712 dir_static.d_ino = dv->dir$w_fid_num; | |
2713 dir_static.d_reclen = sizeof (struct direct) - MAXNAMLEN + 3 | |
2714 + dir_static.d_namlen - dir_static.d_namlen % 4; | |
2715 dirp->dd_loc = ((char *) (++dv) - dp->dir$t_name); | |
2716 return &dir_static; | |
2717 } | |
2718 | |
2719 #endif /* VMS */ | |
2720 | |
2721 #endif /* NONSYSTEM_DIR_LIBRARY */ | |
2722 | |
2723 /* Functions for VMS */ | |
2724 #ifdef VMS | |
579 | 2725 #include "vms-pwd.h" |
491 | 2726 #include <acldef.h> |
2727 #include <chpdef.h> | |
2728 #include <jpidef.h> | |
2729 | |
2730 /* Return as a string the VMS error string pertaining to STATUS. | |
2731 Reuses the same static buffer each time it is called. */ | |
2732 | |
2733 char * | |
2734 vmserrstr (status) | |
2735 int status; /* VMS status code */ | |
2736 { | |
2737 int bufadr[2]; | |
2738 short len; | |
2739 static char buf[257]; | |
2740 | |
2741 bufadr[0] = sizeof buf - 1; | |
2742 bufadr[1] = (int) buf; | |
2743 if (! (SYS$GETMSG (status, &len, bufadr, 0x1, 0) & 1)) | |
2744 return "untranslatable VMS error status"; | |
2745 buf[len] = '\0'; | |
2746 return buf; | |
2747 } | |
2748 | |
2749 #ifdef access | |
2750 #undef access | |
2751 | |
2752 /* The following is necessary because 'access' emulation by VMS C (2.0) does | |
2753 * not work correctly. (It also doesn't work well in version 2.3.) | |
2754 */ | |
2755 | |
2756 #ifdef VMS4_4 | |
2757 | |
2758 #define DESCRIPTOR(name,string) struct dsc$descriptor_s name = \ | |
2759 { strlen (string), DSC$K_DTYPE_T, DSC$K_CLASS_S, string } | |
2760 | |
2761 typedef union { | |
2762 struct { | |
2763 unsigned short s_buflen; | |
2764 unsigned short s_code; | |
2765 char *s_bufadr; | |
2766 unsigned short *s_retlenadr; | |
2767 } s; | |
2768 int end; | |
2769 } item; | |
2770 #define buflen s.s_buflen | |
2771 #define code s.s_code | |
2772 #define bufadr s.s_bufadr | |
2773 #define retlenadr s.s_retlenadr | |
2774 | |
2775 #define R_OK 4 /* test for read permission */ | |
2776 #define W_OK 2 /* test for write permission */ | |
2777 #define X_OK 1 /* test for execute (search) permission */ | |
2778 #define F_OK 0 /* test for presence of file */ | |
2779 | |
2780 int | |
2781 sys_access (path, mode) | |
2782 char *path; | |
2783 int mode; | |
2784 { | |
2785 static char *user = NULL; | |
2786 char dir_fn[512]; | |
2787 | |
2788 /* translate possible directory spec into .DIR file name, so brain-dead | |
2789 * access can treat the directory like a file. */ | |
2790 if (directory_file_name (path, dir_fn)) | |
2791 path = dir_fn; | |
2792 | |
2793 if (mode == F_OK) | |
2794 return access (path, mode); | |
2795 if (user == NULL && (user = (char *) getenv ("USER")) == NULL) | |
2796 return -1; | |
2797 { | |
2798 int stat; | |
2799 int flags; | |
2800 int acces; | |
2801 unsigned short int dummy; | |
2802 item itemlst[3]; | |
2803 static int constant = ACL$C_FILE; | |
2804 DESCRIPTOR (path_desc, path); | |
2805 DESCRIPTOR (user_desc, user); | |
2806 | |
2807 flags = 0; | |
2808 acces = 0; | |
2809 if ((mode & X_OK) && ((stat = access (path, mode)) < 0 || mode == X_OK)) | |
2810 return stat; | |
2811 if (mode & R_OK) | |
2812 acces |= CHP$M_READ; | |
2813 if (mode & W_OK) | |
2814 acces |= CHP$M_WRITE; | |
2815 itemlst[0].buflen = sizeof (int); | |
2816 itemlst[0].code = CHP$_FLAGS; | |
2817 itemlst[0].bufadr = (char *) &flags; | |
2818 itemlst[0].retlenadr = &dummy; | |
2819 itemlst[1].buflen = sizeof (int); | |
2820 itemlst[1].code = CHP$_ACCESS; | |
2821 itemlst[1].bufadr = (char *) &acces; | |
2822 itemlst[1].retlenadr = &dummy; | |
2823 itemlst[2].end = CHP$_END; | |
2824 stat = SYS$CHECK_ACCESS (&constant, &path_desc, &user_desc, itemlst); | |
2825 return stat == SS$_NORMAL ? 0 : -1; | |
2826 } | |
2827 } | |
2828 | |
2829 #else /* not VMS4_4 */ | |
2830 | |
2831 #include <prvdef.h> | |
2832 #define ACE$M_WRITE 2 | |
2833 #define ACE$C_KEYID 1 | |
2834 | |
2835 static unsigned short memid, grpid; | |
2836 static unsigned int uic; | |
2837 | |
2838 /* Called from init_sys_modes, so it happens not very often | |
2839 but at least each time Emacs is loaded. */ | |
2840 sys_access_reinit () | |
2841 { | |
2842 uic = 0; | |
2843 } | |
2844 | |
2845 int | |
2846 sys_access (filename, type) | |
2847 char * filename; | |
2848 int type; | |
2849 { | |
2850 struct FAB fab; | |
2851 struct XABPRO xab; | |
2852 int status, size, i, typecode, acl_controlled; | |
2853 unsigned int *aclptr, *aclend, aclbuf[60]; | |
2854 union prvdef prvmask; | |
2855 | |
2856 /* Get UIC and GRP values for protection checking. */ | |
2857 if (uic == 0) | |
2858 { | |
2859 status = LIB$GETJPI (&JPI$_UIC, 0, 0, &uic, 0, 0); | |
2860 if (! (status & 1)) | |
2861 return -1; | |
2862 memid = uic & 0xFFFF; | |
2863 grpid = uic >> 16; | |
2864 } | |
2865 | |
2866 if (type != 2) /* not checking write access */ | |
2867 return access (filename, type); | |
2868 | |
2869 /* Check write protection. */ | |
2870 | |
2871 #define CHECKPRIV(bit) (prvmask.bit) | |
2872 #define WRITEABLE(field) (! ((xab.xab$w_pro >> field) & XAB$M_NOWRITE)) | |
2873 | |
2874 /* Find privilege bits */ | |
1596
0e105bd23f44
* systty.h, process.c, buffer.h, callproc.c, sysdep.c, dired.c:
Jim Blandy <jimb@redhat.com>
parents:
1570
diff
changeset
|
2875 status = SYS$SETPRV (0, 0, 0, prvmask); |
491 | 2876 if (! (status & 1)) |
2877 error ("Unable to find privileges: %s", vmserrstr (status)); | |
2878 if (CHECKPRIV (PRV$V_BYPASS)) | |
2879 return 0; /* BYPASS enabled */ | |
2880 fab = cc$rms_fab; | |
2881 fab.fab$b_fac = FAB$M_GET; | |
2882 fab.fab$l_fna = filename; | |
2883 fab.fab$b_fns = strlen (filename); | |
2884 fab.fab$l_xab = &xab; | |
2885 xab = cc$rms_xabpro; | |
2886 xab.xab$l_aclbuf = aclbuf; | |
2887 xab.xab$w_aclsiz = sizeof (aclbuf); | |
1596
0e105bd23f44
* systty.h, process.c, buffer.h, callproc.c, sysdep.c, dired.c:
Jim Blandy <jimb@redhat.com>
parents:
1570
diff
changeset
|
2888 status = SYS$OPEN (&fab, 0, 0); |
491 | 2889 if (! (status & 1)) |
2890 return -1; | |
1596
0e105bd23f44
* systty.h, process.c, buffer.h, callproc.c, sysdep.c, dired.c:
Jim Blandy <jimb@redhat.com>
parents:
1570
diff
changeset
|
2891 SYS$CLOSE (&fab, 0, 0); |
491 | 2892 /* Check system access */ |
2893 if (CHECKPRIV (PRV$V_SYSPRV) && WRITEABLE (XAB$V_SYS)) | |
2894 return 0; | |
2895 /* Check ACL entries, if any */ | |
2896 acl_controlled = 0; | |
2897 if (xab.xab$w_acllen > 0) | |
2898 { | |
2899 aclptr = aclbuf; | |
2900 aclend = &aclbuf[xab.xab$w_acllen / 4]; | |
2901 while (*aclptr && aclptr < aclend) | |
2902 { | |
2903 size = (*aclptr & 0xff) / 4; | |
2904 typecode = (*aclptr >> 8) & 0xff; | |
2905 if (typecode == ACE$C_KEYID) | |
2906 for (i = size - 1; i > 1; i--) | |
2907 if (aclptr[i] == uic) | |
2908 { | |
2909 acl_controlled = 1; | |
2910 if (aclptr[1] & ACE$M_WRITE) | |
2911 return 0; /* Write access through ACL */ | |
2912 } | |
2913 aclptr = &aclptr[size]; | |
2914 } | |
2915 if (acl_controlled) /* ACL specified, prohibits write access */ | |
2916 return -1; | |
2917 } | |
2918 /* No ACL entries specified, check normal protection */ | |
2919 if (WRITEABLE (XAB$V_WLD)) /* World writeable */ | |
2920 return 0; | |
2921 if (WRITEABLE (XAB$V_GRP) && | |
2922 (unsigned short) (xab.xab$l_uic >> 16) == grpid) | |
2923 return 0; /* Group writeable */ | |
2924 if (WRITEABLE (XAB$V_OWN) && | |
2925 (xab.xab$l_uic & 0xFFFF) == memid) | |
2926 return 0; /* Owner writeable */ | |
2927 | |
2928 return -1; /* Not writeable */ | |
2929 } | |
2930 #endif /* not VMS4_4 */ | |
2931 #endif /* access */ | |
2932 | |
2933 static char vtbuf[NAM$C_MAXRSS+1]; | |
2934 | |
2935 /* translate a vms file spec to a unix path */ | |
2936 char * | |
2937 sys_translate_vms (vfile) | |
2938 char * vfile; | |
2939 { | |
2940 char * p; | |
2941 char * targ; | |
2942 | |
2943 if (!vfile) | |
2944 return 0; | |
2945 | |
2946 targ = vtbuf; | |
2947 | |
2948 /* leading device or logical name is a root directory */ | |
2949 if (p = strchr (vfile, ':')) | |
2950 { | |
2951 *targ++ = '/'; | |
2952 while (vfile < p) | |
2953 *targ++ = *vfile++; | |
2954 vfile++; | |
2955 *targ++ = '/'; | |
2956 } | |
2957 p = vfile; | |
2958 if (*p == '[' || *p == '<') | |
2959 { | |
2960 while (*++vfile != *p + 2) | |
2961 switch (*vfile) | |
2962 { | |
2963 case '.': | |
2964 if (vfile[-1] == *p) | |
2965 *targ++ = '.'; | |
2966 *targ++ = '/'; | |
2967 break; | |
2968 | |
2969 case '-': | |
2970 *targ++ = '.'; | |
2971 *targ++ = '.'; | |
2972 break; | |
2973 | |
2974 default: | |
2975 *targ++ = *vfile; | |
2976 break; | |
2977 } | |
2978 vfile++; | |
2979 *targ++ = '/'; | |
2980 } | |
2981 while (*vfile) | |
2982 *targ++ = *vfile++; | |
2983 | |
2984 return vtbuf; | |
2985 } | |
2986 | |
2987 static char utbuf[NAM$C_MAXRSS+1]; | |
2988 | |
2989 /* translate a unix path to a VMS file spec */ | |
2990 char * | |
2991 sys_translate_unix (ufile) | |
2992 char * ufile; | |
2993 { | |
2994 int slash_seen = 0; | |
2995 char *p; | |
2996 char * targ; | |
2997 | |
2998 if (!ufile) | |
2999 return 0; | |
3000 | |
3001 targ = utbuf; | |
3002 | |
3003 if (*ufile == '/') | |
3004 { | |
3005 ufile++; | |
3006 } | |
3007 | |
3008 while (*ufile) | |
3009 { | |
3010 switch (*ufile) | |
3011 { | |
3012 case '/': | |
3013 if (slash_seen) | |
3014 if (index (&ufile[1], '/')) | |
3015 *targ++ = '.'; | |
3016 else | |
3017 *targ++ = ']'; | |
3018 else | |
3019 { | |
3020 *targ++ = ':'; | |
3021 if (index (&ufile[1], '/')) | |
3022 *targ++ = '['; | |
3023 slash_seen = 1; | |
3024 } | |
3025 break; | |
3026 | |
3027 case '.': | |
3028 if (strncmp (ufile, "./", 2) == 0) | |
3029 { | |
3030 if (!slash_seen) | |
3031 { | |
3032 *targ++ = '['; | |
3033 slash_seen = 1; | |
3034 } | |
3035 ufile++; /* skip the dot */ | |
3036 if (index (&ufile[1], '/')) | |
3037 *targ++ = '.'; | |
3038 else | |
3039 *targ++ = ']'; | |
3040 } | |
3041 else if (strncmp (ufile, "../", 3) == 0) | |
3042 { | |
3043 if (!slash_seen) | |
3044 { | |
3045 *targ++ = '['; | |
3046 slash_seen = 1; | |
3047 } | |
3048 *targ++ = '-'; | |
3049 ufile += 2; /* skip the dots */ | |
3050 if (index (&ufile[1], '/')) | |
3051 *targ++ = '.'; | |
3052 else | |
3053 *targ++ = ']'; | |
3054 } | |
3055 else | |
3056 *targ++ = *ufile; | |
3057 break; | |
3058 | |
3059 default: | |
3060 *targ++ = *ufile; | |
3061 break; | |
3062 } | |
3063 ufile++; | |
3064 } | |
3065 *targ = '\0'; | |
3066 | |
3067 return utbuf; | |
3068 } | |
3069 | |
3070 char * | |
3071 getwd (pathname) | |
3072 char *pathname; | |
3073 { | |
3074 char *ptr; | |
3075 strcpy (pathname, egetenv ("PATH")); | |
3076 | |
3077 ptr = pathname; | |
3078 while (*ptr) | |
3079 { | |
3080 if ('a' <= *ptr && *ptr <= 'z') | |
3081 *ptr -= 040; | |
3082 ptr++; | |
3083 } | |
3084 return pathname; | |
3085 } | |
3086 | |
3087 getppid () | |
3088 { | |
3089 long item_code = JPI$_OWNER; | |
3090 unsigned long parent_id; | |
3091 int status; | |
3092 | |
3093 if (((status = LIB$GETJPI (&item_code, 0, 0, &parent_id)) & 1) == 0) | |
3094 { | |
3095 errno = EVMSERR; | |
3096 vaxc$errno = status; | |
3097 return -1; | |
3098 } | |
3099 return parent_id; | |
3100 } | |
3101 | |
3102 #undef getuid | |
3103 unsigned | |
3104 sys_getuid () | |
3105 { | |
3106 return (getgid () << 16) | getuid (); | |
3107 } | |
3108 | |
3109 int | |
3110 sys_read (fildes, buf, nbyte) | |
3111 int fildes; | |
3112 char *buf; | |
3113 unsigned int nbyte; | |
3114 { | |
3115 return read (fildes, buf, (nbyte < MAXIOSIZE ? nbyte : MAXIOSIZE)); | |
3116 } | |
3117 | |
3118 #if 0 | |
3119 int | |
3120 sys_write (fildes, buf, nbyte) | |
3121 int fildes; | |
3122 char *buf; | |
3123 unsigned int nbyte; | |
3124 { | |
3125 register int nwrote, rtnval = 0; | |
3126 | |
3127 while (nbyte > MAXIOSIZE && (nwrote = write (fildes, buf, MAXIOSIZE)) > 0) { | |
3128 nbyte -= nwrote; | |
3129 buf += nwrote; | |
3130 rtnval += nwrote; | |
3131 } | |
3132 if (nwrote < 0) | |
3133 return rtnval ? rtnval : -1; | |
3134 if ((nwrote = write (fildes, buf, nbyte)) < 0) | |
3135 return rtnval ? rtnval : -1; | |
3136 return (rtnval + nwrote); | |
3137 } | |
3138 #endif /* 0 */ | |
3139 | |
3140 /* | |
3141 * VAX/VMS VAX C RTL really loses. It insists that records | |
3142 * end with a newline (carriage return) character, and if they | |
3143 * don't it adds one (nice of it isn't it!) | |
3144 * | |
3145 * Thus we do this stupidity below. | |
3146 */ | |
3147 | |
3148 int | |
3149 sys_write (fildes, buf, nbytes) | |
3150 int fildes; | |
3151 char *buf; | |
3152 unsigned int nbytes; | |
3153 { | |
3154 register char *p; | |
3155 register char *e; | |
525 | 3156 int sum = 0; |
3157 struct stat st; | |
3158 | |
3159 fstat (fildes, &st); | |
491 | 3160 p = buf; |
3161 while (nbytes > 0) | |
3162 { | |
525 | 3163 int len, retval; |
3164 | |
3165 /* Handle fixed-length files with carriage control. */ | |
3166 if (st.st_fab_rfm == FAB$C_FIX | |
3167 && ((st.st_fab_rat & (FAB$M_FTN | FAB$M_CR)) != 0)) | |
3168 { | |
3169 len = st.st_fab_mrs; | |
3170 retval = write (fildes, p, min (len, nbytes)); | |
3171 if (retval != len) | |
3172 return -1; | |
3173 retval++; /* This skips the implied carriage control */ | |
3174 } | |
3175 else | |
3176 { | |
3177 e = p + min (MAXIOSIZE, nbytes) - 1; | |
3178 while (*e != '\n' && e > p) e--; | |
3179 if (p == e) /* Ok.. so here we add a newline... sigh. */ | |
3180 e = p + min (MAXIOSIZE, nbytes) - 1; | |
3181 len = e + 1 - p; | |
3182 retval = write (fildes, p, len); | |
3183 if (retval != len) | |
3184 return -1; | |
3185 } | |
3186 p += retval; | |
3187 sum += retval; | |
491 | 3188 nbytes -= retval; |
3189 } | |
3190 return sum; | |
3191 } | |
3192 | |
3193 /* Create file NEW copying its attributes from file OLD. If | |
3194 OLD is 0 or does not exist, create based on the value of | |
3195 vms_stmlf_recfm. */ | |
3196 | |
3197 /* Protection value the file should ultimately have. | |
3198 Set by create_copy_attrs, and use by rename_sansversions. */ | |
3199 static unsigned short int fab_final_pro; | |
3200 | |
3201 int | |
3202 creat_copy_attrs (old, new) | |
3203 char *old, *new; | |
3204 { | |
3205 struct FAB fab = cc$rms_fab; | |
3206 struct XABPRO xabpro; | |
3207 char aclbuf[256]; /* Choice of size is arbitrary. See below. */ | |
3208 extern int vms_stmlf_recfm; | |
3209 | |
3210 if (old) | |
3211 { | |
3212 fab.fab$b_fac = FAB$M_GET; | |
3213 fab.fab$l_fna = old; | |
3214 fab.fab$b_fns = strlen (old); | |
3215 fab.fab$l_xab = (char *) &xabpro; | |
3216 xabpro = cc$rms_xabpro; | |
3217 xabpro.xab$l_aclbuf = aclbuf; | |
3218 xabpro.xab$w_aclsiz = sizeof aclbuf; | |
3219 /* Call $OPEN to fill in the fab & xabpro fields. */ | |
1596
0e105bd23f44
* systty.h, process.c, buffer.h, callproc.c, sysdep.c, dired.c:
Jim Blandy <jimb@redhat.com>
parents:
1570
diff
changeset
|
3220 if (SYS$OPEN (&fab, 0, 0) & 1) |
491 | 3221 { |
1596
0e105bd23f44
* systty.h, process.c, buffer.h, callproc.c, sysdep.c, dired.c:
Jim Blandy <jimb@redhat.com>
parents:
1570
diff
changeset
|
3222 SYS$CLOSE (&fab, 0, 0); |
491 | 3223 fab.fab$l_alq = 0; /* zero the allocation quantity */ |
3224 if (xabpro.xab$w_acllen > 0) | |
3225 { | |
3226 if (xabpro.xab$w_acllen > sizeof aclbuf) | |
3227 /* If the acl buffer was too short, redo open with longer one. | |
3228 Wouldn't need to do this if there were some system imposed | |
3229 limit on the size of an ACL, but I can't find any such. */ | |
3230 { | |
3231 xabpro.xab$l_aclbuf = (char *) alloca (xabpro.xab$w_acllen); | |
3232 xabpro.xab$w_aclsiz = xabpro.xab$w_acllen; | |
1596
0e105bd23f44
* systty.h, process.c, buffer.h, callproc.c, sysdep.c, dired.c:
Jim Blandy <jimb@redhat.com>
parents:
1570
diff
changeset
|
3233 if (SYS$OPEN (&fab, 0, 0) & 1) |
0e105bd23f44
* systty.h, process.c, buffer.h, callproc.c, sysdep.c, dired.c:
Jim Blandy <jimb@redhat.com>
parents:
1570
diff
changeset
|
3234 SYS$CLOSE (&fab, 0, 0); |
491 | 3235 else |
3236 old = 0; | |
3237 } | |
3238 } | |
3239 else | |
3240 xabpro.xab$l_aclbuf = 0; | |
3241 } | |
3242 else | |
3243 old = 0; | |
3244 } | |
3245 fab.fab$l_fna = new; | |
3246 fab.fab$b_fns = strlen (new); | |
3247 if (!old) | |
3248 { | |
3249 fab.fab$l_xab = 0; | |
3250 fab.fab$b_rfm = vms_stmlf_recfm ? FAB$C_STMLF : FAB$C_VAR; | |
3251 fab.fab$b_rat = FAB$M_CR; | |
3252 } | |
3253 | |
3254 /* Set the file protections such that we will be able to manipulate | |
3255 this file. Once we are done writing and renaming it, we will set | |
3256 the protections back. */ | |
3257 if (old) | |
3258 fab_final_pro = xabpro.xab$w_pro; | |
3259 else | |
1596
0e105bd23f44
* systty.h, process.c, buffer.h, callproc.c, sysdep.c, dired.c:
Jim Blandy <jimb@redhat.com>
parents:
1570
diff
changeset
|
3260 SYS$SETDFPROT (0, &fab_final_pro); |
491 | 3261 xabpro.xab$w_pro &= 0xff0f; /* set O:rewd for now. This is set back later. */ |
3262 | |
3263 /* Create the new file with either default attrs or attrs copied | |
3264 from old file. */ | |
3265 if (!(SYS$CREATE (&fab, 0, 0) & 1)) | |
3266 return -1; | |
1596
0e105bd23f44
* systty.h, process.c, buffer.h, callproc.c, sysdep.c, dired.c:
Jim Blandy <jimb@redhat.com>
parents:
1570
diff
changeset
|
3267 SYS$CLOSE (&fab, 0, 0); |
491 | 3268 /* As this is a "replacement" for creat, return a file descriptor |
3269 opened for writing. */ | |
3270 return open (new, O_WRONLY); | |
3271 } | |
3272 | |
3273 #ifdef creat | |
3274 #undef creat | |
3275 #include <varargs.h> | |
3276 #ifdef __GNUC__ | |
3277 #ifndef va_count | |
3278 #define va_count(X) ((X) = *(((int *) &(va_alist)) - 1)) | |
3279 #endif | |
3280 #endif | |
3281 | |
3282 sys_creat (va_alist) | |
3283 va_dcl | |
3284 { | |
3285 va_list list_incrementor; | |
3286 char *name; | |
3287 int mode; | |
3288 int rfd; /* related file descriptor */ | |
3289 int fd; /* Our new file descriptor */ | |
3290 int count; | |
3291 struct stat st_buf; | |
3292 char rfm[12]; | |
3293 char rat[15]; | |
3294 char mrs[13]; | |
3295 char fsz[13]; | |
3296 extern int vms_stmlf_recfm; | |
3297 | |
3298 va_count (count); | |
3299 va_start (list_incrementor); | |
3300 name = va_arg (list_incrementor, char *); | |
3301 mode = va_arg (list_incrementor, int); | |
3302 if (count > 2) | |
3303 rfd = va_arg (list_incrementor, int); | |
3304 va_end (list_incrementor); | |
3305 if (count > 2) | |
3306 { | |
3307 /* Use information from the related file descriptor to set record | |
3308 format of the newly created file. */ | |
3309 fstat (rfd, &st_buf); | |
3310 switch (st_buf.st_fab_rfm) | |
3311 { | |
3312 case FAB$C_FIX: | |
3313 strcpy (rfm, "rfm = fix"); | |
3314 sprintf (mrs, "mrs = %d", st_buf.st_fab_mrs); | |
3315 strcpy (rat, "rat = "); | |
3316 if (st_buf.st_fab_rat & FAB$M_CR) | |
3317 strcat (rat, "cr"); | |
3318 else if (st_buf.st_fab_rat & FAB$M_FTN) | |
3319 strcat (rat, "ftn"); | |
3320 else if (st_buf.st_fab_rat & FAB$M_PRN) | |
3321 strcat (rat, "prn"); | |
3322 if (st_buf.st_fab_rat & FAB$M_BLK) | |
3323 if (st_buf.st_fab_rat & (FAB$M_CR|FAB$M_FTN|FAB$M_PRN)) | |
3324 strcat (rat, ", blk"); | |
3325 else | |
3326 strcat (rat, "blk"); | |
3327 return creat (name, 0, rfm, rat, mrs); | |
3328 | |
3329 case FAB$C_VFC: | |
3330 strcpy (rfm, "rfm = vfc"); | |
3331 sprintf (fsz, "fsz = %d", st_buf.st_fab_fsz); | |
3332 strcpy (rat, "rat = "); | |
3333 if (st_buf.st_fab_rat & FAB$M_CR) | |
3334 strcat (rat, "cr"); | |
3335 else if (st_buf.st_fab_rat & FAB$M_FTN) | |
3336 strcat (rat, "ftn"); | |
3337 else if (st_buf.st_fab_rat & FAB$M_PRN) | |
3338 strcat (rat, "prn"); | |
3339 if (st_buf.st_fab_rat & FAB$M_BLK) | |
3340 if (st_buf.st_fab_rat & (FAB$M_CR|FAB$M_FTN|FAB$M_PRN)) | |
3341 strcat (rat, ", blk"); | |
3342 else | |
3343 strcat (rat, "blk"); | |
3344 return creat (name, 0, rfm, rat, fsz); | |
3345 | |
3346 case FAB$C_STM: | |
3347 strcpy (rfm, "rfm = stm"); | |
3348 break; | |
3349 | |
3350 case FAB$C_STMCR: | |
3351 strcpy (rfm, "rfm = stmcr"); | |
3352 break; | |
3353 | |
3354 case FAB$C_STMLF: | |
3355 strcpy (rfm, "rfm = stmlf"); | |
3356 break; | |
3357 | |
3358 case FAB$C_UDF: | |
3359 strcpy (rfm, "rfm = udf"); | |
3360 break; | |
3361 | |
3362 case FAB$C_VAR: | |
3363 strcpy (rfm, "rfm = var"); | |
3364 break; | |
3365 } | |
3366 strcpy (rat, "rat = "); | |
3367 if (st_buf.st_fab_rat & FAB$M_CR) | |
3368 strcat (rat, "cr"); | |
3369 else if (st_buf.st_fab_rat & FAB$M_FTN) | |
3370 strcat (rat, "ftn"); | |
3371 else if (st_buf.st_fab_rat & FAB$M_PRN) | |
3372 strcat (rat, "prn"); | |
3373 if (st_buf.st_fab_rat & FAB$M_BLK) | |
3374 if (st_buf.st_fab_rat & (FAB$M_CR|FAB$M_FTN|FAB$M_PRN)) | |
3375 strcat (rat, ", blk"); | |
3376 else | |
3377 strcat (rat, "blk"); | |
3378 } | |
3379 else | |
3380 { | |
3381 strcpy (rfm, vms_stmlf_recfm ? "rfm = stmlf" : "rfm=var"); | |
3382 strcpy (rat, "rat=cr"); | |
3383 } | |
3384 /* Until the VAX C RTL fixes the many bugs with modes, always use | |
3385 mode 0 to get the user's default protection. */ | |
3386 fd = creat (name, 0, rfm, rat); | |
3387 if (fd < 0 && errno == EEXIST) | |
3388 { | |
3389 if (unlink (name) < 0) | |
3390 report_file_error ("delete", build_string (name)); | |
3391 fd = creat (name, 0, rfm, rat); | |
3392 } | |
3393 return fd; | |
3394 } | |
3395 #endif /* creat */ | |
3396 | |
3397 /* fwrite to stdout is S L O W. Speed it up by using fputc...*/ | |
3398 sys_fwrite (ptr, size, num, fp) | |
3399 register char * ptr; | |
3400 FILE * fp; | |
3401 { | |
3402 register int tot = num * size; | |
3403 | |
3404 while (tot--) | |
3405 fputc (*ptr++, fp); | |
3406 } | |
3407 | |
3408 /* | |
3409 * The VMS C library routine creat actually creates a new version of an | |
3410 * existing file rather than truncating the old version. There are times | |
3411 * when this is not the desired behavior, for instance, when writing an | |
3412 * auto save file (you only want one version), or when you don't have | |
3413 * write permission in the directory containing the file (but the file | |
3414 * itself is writable). Hence this routine, which is equivalent to | |
3415 * "close (creat (fn, 0));" on Unix if fn already exists. | |
3416 */ | |
3417 int | |
3418 vms_truncate (fn) | |
3419 char *fn; | |
3420 { | |
3421 struct FAB xfab = cc$rms_fab; | |
3422 struct RAB xrab = cc$rms_rab; | |
3423 int status; | |
3424 | |
3425 xfab.fab$l_fop = FAB$M_TEF; /* free allocated but unused blocks on close */ | |
3426 xfab.fab$b_fac = FAB$M_TRN | FAB$M_GET; /* allow truncate and get access */ | |
3427 xfab.fab$b_shr = FAB$M_NIL; /* allow no sharing - file must be locked */ | |
3428 xfab.fab$l_fna = fn; | |
3429 xfab.fab$b_fns = strlen (fn); | |
3430 xfab.fab$l_dna = ";0"; /* default to latest version of the file */ | |
3431 xfab.fab$b_dns = 2; | |
3432 xrab.rab$l_fab = &xfab; | |
3433 | |
3434 /* This gibberish opens the file, positions to the first record, and | |
3435 deletes all records from there until the end of file. */ | |
1596
0e105bd23f44
* systty.h, process.c, buffer.h, callproc.c, sysdep.c, dired.c:
Jim Blandy <jimb@redhat.com>
parents:
1570
diff
changeset
|
3436 if ((SYS$OPEN (&xfab) & 01) == 01) |
491 | 3437 { |
1596
0e105bd23f44
* systty.h, process.c, buffer.h, callproc.c, sysdep.c, dired.c:
Jim Blandy <jimb@redhat.com>
parents:
1570
diff
changeset
|
3438 if ((SYS$CONNECT (&xrab) & 01) == 01 && |
0e105bd23f44
* systty.h, process.c, buffer.h, callproc.c, sysdep.c, dired.c:
Jim Blandy <jimb@redhat.com>
parents:
1570
diff
changeset
|
3439 (SYS$FIND (&xrab) & 01) == 01 && |
0e105bd23f44
* systty.h, process.c, buffer.h, callproc.c, sysdep.c, dired.c:
Jim Blandy <jimb@redhat.com>
parents:
1570
diff
changeset
|
3440 (SYS$TRUNCATE (&xrab) & 01) == 01) |
491 | 3441 status = 0; |
3442 else | |
3443 status = -1; | |
3444 } | |
3445 else | |
3446 status = -1; | |
1596
0e105bd23f44
* systty.h, process.c, buffer.h, callproc.c, sysdep.c, dired.c:
Jim Blandy <jimb@redhat.com>
parents:
1570
diff
changeset
|
3447 SYS$CLOSE (&xfab); |
491 | 3448 return status; |
3449 } | |
3450 | |
3451 /* Define this symbol to actually read SYSUAF.DAT. This requires either | |
3452 SYSPRV or a readable SYSUAF.DAT. */ | |
3453 | |
3454 #ifdef READ_SYSUAF | |
3455 /* | |
3456 * getuaf.c | |
3457 * | |
3458 * Routine to read the VMS User Authorization File and return | |
3459 * a specific user's record. | |
3460 */ | |
3461 | |
3462 static struct UAF retuaf; | |
3463 | |
3464 struct UAF * | |
3465 get_uaf_name (uname) | |
3466 char * uname; | |
3467 { | |
3468 register status; | |
3469 struct FAB uaf_fab; | |
3470 struct RAB uaf_rab; | |
3471 | |
3472 uaf_fab = cc$rms_fab; | |
3473 uaf_rab = cc$rms_rab; | |
3474 /* initialize fab fields */ | |
3475 uaf_fab.fab$l_fna = "SYS$SYSTEM:SYSUAF.DAT"; | |
3476 uaf_fab.fab$b_fns = 21; | |
3477 uaf_fab.fab$b_fac = FAB$M_GET; | |
3478 uaf_fab.fab$b_org = FAB$C_IDX; | |
3479 uaf_fab.fab$b_shr = FAB$M_GET|FAB$M_PUT|FAB$M_UPD|FAB$M_DEL; | |
3480 /* initialize rab fields */ | |
3481 uaf_rab.rab$l_fab = &uaf_fab; | |
3482 /* open the User Authorization File */ | |
1596
0e105bd23f44
* systty.h, process.c, buffer.h, callproc.c, sysdep.c, dired.c:
Jim Blandy <jimb@redhat.com>
parents:
1570
diff
changeset
|
3483 status = SYS$OPEN (&uaf_fab); |
491 | 3484 if (!(status&1)) |
3485 { | |
3486 errno = EVMSERR; | |
3487 vaxc$errno = status; | |
3488 return 0; | |
3489 } | |
1596
0e105bd23f44
* systty.h, process.c, buffer.h, callproc.c, sysdep.c, dired.c:
Jim Blandy <jimb@redhat.com>
parents:
1570
diff
changeset
|
3490 status = SYS$CONNECT (&uaf_rab); |
491 | 3491 if (!(status&1)) |
3492 { | |
3493 errno = EVMSERR; | |
3494 vaxc$errno = status; | |
3495 return 0; | |
3496 } | |
3497 /* read the requested record - index is in uname */ | |
3498 uaf_rab.rab$l_kbf = uname; | |
3499 uaf_rab.rab$b_ksz = strlen (uname); | |
3500 uaf_rab.rab$b_rac = RAB$C_KEY; | |
3501 uaf_rab.rab$l_ubf = (char *)&retuaf; | |
3502 uaf_rab.rab$w_usz = sizeof retuaf; | |
1596
0e105bd23f44
* systty.h, process.c, buffer.h, callproc.c, sysdep.c, dired.c:
Jim Blandy <jimb@redhat.com>
parents:
1570
diff
changeset
|
3503 status = SYS$GET (&uaf_rab); |
491 | 3504 if (!(status&1)) |
3505 { | |
3506 errno = EVMSERR; | |
3507 vaxc$errno = status; | |
3508 return 0; | |
3509 } | |
3510 /* close the User Authorization File */ | |
1596
0e105bd23f44
* systty.h, process.c, buffer.h, callproc.c, sysdep.c, dired.c:
Jim Blandy <jimb@redhat.com>
parents:
1570
diff
changeset
|
3511 status = SYS$DISCONNECT (&uaf_rab); |
491 | 3512 if (!(status&1)) |
3513 { | |
3514 errno = EVMSERR; | |
3515 vaxc$errno = status; | |
3516 return 0; | |
3517 } | |
1596
0e105bd23f44
* systty.h, process.c, buffer.h, callproc.c, sysdep.c, dired.c:
Jim Blandy <jimb@redhat.com>
parents:
1570
diff
changeset
|
3518 status = SYS$CLOSE (&uaf_fab); |
491 | 3519 if (!(status&1)) |
3520 { | |
3521 errno = EVMSERR; | |
3522 vaxc$errno = status; | |
3523 return 0; | |
3524 } | |
3525 return &retuaf; | |
3526 } | |
3527 | |
3528 struct UAF * | |
3529 get_uaf_uic (uic) | |
3530 unsigned long uic; | |
3531 { | |
3532 register status; | |
3533 struct FAB uaf_fab; | |
3534 struct RAB uaf_rab; | |
3535 | |
3536 uaf_fab = cc$rms_fab; | |
3537 uaf_rab = cc$rms_rab; | |
3538 /* initialize fab fields */ | |
3539 uaf_fab.fab$l_fna = "SYS$SYSTEM:SYSUAF.DAT"; | |
3540 uaf_fab.fab$b_fns = 21; | |
3541 uaf_fab.fab$b_fac = FAB$M_GET; | |
3542 uaf_fab.fab$b_org = FAB$C_IDX; | |
3543 uaf_fab.fab$b_shr = FAB$M_GET|FAB$M_PUT|FAB$M_UPD|FAB$M_DEL; | |
3544 /* initialize rab fields */ | |
3545 uaf_rab.rab$l_fab = &uaf_fab; | |
3546 /* open the User Authorization File */ | |
1596
0e105bd23f44
* systty.h, process.c, buffer.h, callproc.c, sysdep.c, dired.c:
Jim Blandy <jimb@redhat.com>
parents:
1570
diff
changeset
|
3547 status = SYS$OPEN (&uaf_fab); |
491 | 3548 if (!(status&1)) |
3549 { | |
3550 errno = EVMSERR; | |
3551 vaxc$errno = status; | |
3552 return 0; | |
3553 } | |
1596
0e105bd23f44
* systty.h, process.c, buffer.h, callproc.c, sysdep.c, dired.c:
Jim Blandy <jimb@redhat.com>
parents:
1570
diff
changeset
|
3554 status = SYS$CONNECT (&uaf_rab); |
491 | 3555 if (!(status&1)) |
3556 { | |
3557 errno = EVMSERR; | |
3558 vaxc$errno = status; | |
3559 return 0; | |
3560 } | |
3561 /* read the requested record - index is in uic */ | |
3562 uaf_rab.rab$b_krf = 1; /* 1st alternate key */ | |
3563 uaf_rab.rab$l_kbf = (char *) &uic; | |
3564 uaf_rab.rab$b_ksz = sizeof uic; | |
3565 uaf_rab.rab$b_rac = RAB$C_KEY; | |
3566 uaf_rab.rab$l_ubf = (char *)&retuaf; | |
3567 uaf_rab.rab$w_usz = sizeof retuaf; | |
1596
0e105bd23f44
* systty.h, process.c, buffer.h, callproc.c, sysdep.c, dired.c:
Jim Blandy <jimb@redhat.com>
parents:
1570
diff
changeset
|
3568 status = SYS$GET (&uaf_rab); |
491 | 3569 if (!(status&1)) |
3570 { | |
3571 errno = EVMSERR; | |
3572 vaxc$errno = status; | |
3573 return 0; | |
3574 } | |
3575 /* close the User Authorization File */ | |
1596
0e105bd23f44
* systty.h, process.c, buffer.h, callproc.c, sysdep.c, dired.c:
Jim Blandy <jimb@redhat.com>
parents:
1570
diff
changeset
|
3576 status = SYS$DISCONNECT (&uaf_rab); |
491 | 3577 if (!(status&1)) |
3578 { | |
3579 errno = EVMSERR; | |
3580 vaxc$errno = status; | |
3581 return 0; | |
3582 } | |
1596
0e105bd23f44
* systty.h, process.c, buffer.h, callproc.c, sysdep.c, dired.c:
Jim Blandy <jimb@redhat.com>
parents:
1570
diff
changeset
|
3583 status = SYS$CLOSE (&uaf_fab); |
491 | 3584 if (!(status&1)) |
3585 { | |
3586 errno = EVMSERR; | |
3587 vaxc$errno = status; | |
3588 return 0; | |
3589 } | |
3590 return &retuaf; | |
3591 } | |
3592 | |
3593 static struct passwd retpw; | |
3594 | |
3595 struct passwd * | |
3596 cnv_uaf_pw (up) | |
3597 struct UAF * up; | |
3598 { | |
3599 char * ptr; | |
3600 | |
3601 /* copy these out first because if the username is 32 chars, the next | |
3602 section will overwrite the first byte of the UIC */ | |
3603 retpw.pw_uid = up->uaf$w_mem; | |
3604 retpw.pw_gid = up->uaf$w_grp; | |
3605 | |
3606 /* I suppose this is not the best sytle, to possibly overwrite one | |
3607 byte beyond the end of the field, but what the heck... */ | |
3608 ptr = &up->uaf$t_username[UAF$S_USERNAME]; | |
3609 while (ptr[-1] == ' ') | |
3610 ptr--; | |
3611 *ptr = '\0'; | |
3612 strcpy (retpw.pw_name, up->uaf$t_username); | |
3613 | |
3614 /* the rest of these are counted ascii strings */ | |
3615 strncpy (retpw.pw_gecos, &up->uaf$t_owner[1], up->uaf$t_owner[0]); | |
3616 retpw.pw_gecos[up->uaf$t_owner[0]] = '\0'; | |
3617 strncpy (retpw.pw_dir, &up->uaf$t_defdev[1], up->uaf$t_defdev[0]); | |
3618 retpw.pw_dir[up->uaf$t_defdev[0]] = '\0'; | |
3619 strncat (retpw.pw_dir, &up->uaf$t_defdir[1], up->uaf$t_defdir[0]); | |
3620 retpw.pw_dir[up->uaf$t_defdev[0] + up->uaf$t_defdir[0]] = '\0'; | |
3621 strncpy (retpw.pw_shell, &up->uaf$t_defcli[1], up->uaf$t_defcli[0]); | |
3622 retpw.pw_shell[up->uaf$t_defcli[0]] = '\0'; | |
3623 | |
3624 return &retpw; | |
3625 } | |
3626 #else /* not READ_SYSUAF */ | |
3627 static struct passwd retpw; | |
3628 #endif /* not READ_SYSUAF */ | |
3629 | |
3630 struct passwd * | |
3631 getpwnam (name) | |
3632 char * name; | |
3633 { | |
3634 #ifdef READ_SYSUAF | |
3635 struct UAF *up; | |
3636 #else | |
3637 char * user; | |
3638 char * dir; | |
3639 unsigned char * full; | |
3640 #endif /* READ_SYSUAF */ | |
3641 char *ptr = name; | |
3642 | |
3643 while (*ptr) | |
3644 { | |
3645 if ('a' <= *ptr && *ptr <= 'z') | |
3646 *ptr -= 040; | |
3647 ptr++; | |
3648 } | |
3649 #ifdef READ_SYSUAF | |
3650 if (!(up = get_uaf_name (name))) | |
3651 return 0; | |
3652 return cnv_uaf_pw (up); | |
3653 #else | |
3654 if (strcmp (name, getenv ("USER")) == 0) | |
3655 { | |
3656 retpw.pw_uid = getuid (); | |
3657 retpw.pw_gid = getgid (); | |
3658 strcpy (retpw.pw_name, name); | |
3659 if (full = egetenv ("FULLNAME")) | |
3660 strcpy (retpw.pw_gecos, full); | |
3661 else | |
3662 *retpw.pw_gecos = '\0'; | |
3663 strcpy (retpw.pw_dir, egetenv ("HOME")); | |
3664 *retpw.pw_shell = '\0'; | |
3665 return &retpw; | |
3666 } | |
3667 else | |
3668 return 0; | |
3669 #endif /* not READ_SYSUAF */ | |
3670 } | |
3671 | |
3672 struct passwd * | |
3673 getpwuid (uid) | |
3674 unsigned long uid; | |
3675 { | |
3676 #ifdef READ_SYSUAF | |
3677 struct UAF * up; | |
3678 | |
3679 if (!(up = get_uaf_uic (uid))) | |
3680 return 0; | |
3681 return cnv_uaf_pw (up); | |
3682 #else | |
3683 if (uid == sys_getuid ()) | |
3684 return getpwnam (egetenv ("USER")); | |
3685 else | |
3686 return 0; | |
3687 #endif /* not READ_SYSUAF */ | |
3688 } | |
3689 | |
3690 /* return total address space available to the current process. This is | |
3691 the sum of the current p0 size, p1 size and free page table entries | |
3692 available. */ | |
3693 vlimit () | |
3694 { | |
3695 int item_code; | |
3696 unsigned long free_pages; | |
3697 unsigned long frep0va; | |
3698 unsigned long frep1va; | |
3699 register status; | |
3700 | |
3701 item_code = JPI$_FREPTECNT; | |
3702 if (((status = LIB$GETJPI (&item_code, 0, 0, &free_pages)) & 1) == 0) | |
3703 { | |
3704 errno = EVMSERR; | |
3705 vaxc$errno = status; | |
3706 return -1; | |
3707 } | |
3708 free_pages *= 512; | |
3709 | |
3710 item_code = JPI$_FREP0VA; | |
3711 if (((status = LIB$GETJPI (&item_code, 0, 0, &frep0va)) & 1) == 0) | |
3712 { | |
3713 errno = EVMSERR; | |
3714 vaxc$errno = status; | |
3715 return -1; | |
3716 } | |
3717 item_code = JPI$_FREP1VA; | |
3718 if (((status = LIB$GETJPI (&item_code, 0, 0, &frep1va)) & 1) == 0) | |
3719 { | |
3720 errno = EVMSERR; | |
3721 vaxc$errno = status; | |
3722 return -1; | |
3723 } | |
3724 | |
3725 return free_pages + frep0va + (0x7fffffff - frep1va); | |
3726 } | |
3727 | |
3728 define_logical_name (varname, string) | |
3729 char *varname; | |
3730 char *string; | |
3731 { | |
3732 struct dsc$descriptor_s strdsc = | |
3733 {strlen (string), DSC$K_DTYPE_T, DSC$K_CLASS_S, string}; | |
3734 struct dsc$descriptor_s envdsc = | |
3735 {strlen (varname), DSC$K_DTYPE_T, DSC$K_CLASS_S, varname}; | |
3736 struct dsc$descriptor_s lnmdsc = | |
3737 {7, DSC$K_DTYPE_T, DSC$K_CLASS_S, "LNM$JOB"}; | |
3738 | |
3739 return LIB$SET_LOGICAL (&envdsc, &strdsc, &lnmdsc, 0, 0); | |
3740 } | |
3741 | |
3742 delete_logical_name (varname) | |
3743 char *varname; | |
3744 { | |
3745 struct dsc$descriptor_s envdsc = | |
3746 {strlen (varname), DSC$K_DTYPE_T, DSC$K_CLASS_S, varname}; | |
3747 struct dsc$descriptor_s lnmdsc = | |
3748 {7, DSC$K_DTYPE_T, DSC$K_CLASS_S, "LNM$JOB"}; | |
3749 | |
3750 return LIB$DELETE_LOGICAL (&envdsc, &lnmdsc); | |
3751 } | |
3752 | |
3753 ulimit () | |
3754 {} | |
3755 | |
3756 setpgrp () | |
3757 {} | |
3758 | |
3759 execvp () | |
3760 { | |
3761 error ("execvp system call not implemented"); | |
3762 } | |
3763 | |
3764 int | |
3765 rename (from, to) | |
3766 char *from, *to; | |
3767 { | |
3768 int status; | |
3769 struct FAB from_fab = cc$rms_fab, to_fab = cc$rms_fab; | |
3770 struct NAM from_nam = cc$rms_nam, to_nam = cc$rms_nam; | |
3771 char from_esn[NAM$C_MAXRSS]; | |
3772 char to_esn[NAM$C_MAXRSS]; | |
3773 | |
3774 from_fab.fab$l_fna = from; | |
3775 from_fab.fab$b_fns = strlen (from); | |
3776 from_fab.fab$l_nam = &from_nam; | |
3777 from_fab.fab$l_fop = FAB$M_NAM; | |
3778 | |
3779 from_nam.nam$l_esa = from_esn; | |
3780 from_nam.nam$b_ess = sizeof from_esn; | |
3781 | |
3782 to_fab.fab$l_fna = to; | |
3783 to_fab.fab$b_fns = strlen (to); | |
3784 to_fab.fab$l_nam = &to_nam; | |
3785 to_fab.fab$l_fop = FAB$M_NAM; | |
3786 | |
3787 to_nam.nam$l_esa = to_esn; | |
3788 to_nam.nam$b_ess = sizeof to_esn; | |
3789 | |
3790 status = SYS$RENAME (&from_fab, 0, 0, &to_fab); | |
3791 | |
3792 if (status & 1) | |
3793 return 0; | |
3794 else | |
3795 { | |
3796 if (status == RMS$_DEV) | |
3797 errno = EXDEV; | |
3798 else | |
3799 errno = EVMSERR; | |
3800 vaxc$errno = status; | |
3801 return -1; | |
3802 } | |
3803 } | |
3804 | |
3805 /* This function renames a file like `rename', but it strips | |
3806 the version number from the "to" filename, such that the "to" file is | |
3807 will always be a new version. It also sets the file protection once it is | |
3808 finished. The protection that we will use is stored in fab_final_pro, | |
3809 and was set when we did a creat_copy_attrs to create the file that we | |
3810 are renaming. | |
3811 | |
3812 We could use the chmod function, but Eunichs uses 3 bits per user category | |
3813 to describe the protection, and VMS uses 4 (write and delete are seperate | |
3814 bits). To maintain portability, the VMS implementation of `chmod' wires | |
3815 the W and D bits together. */ | |
3816 | |
3817 | |
3818 static struct fibdef fib; /* We need this initialized to zero */ | |
3819 char vms_file_written[NAM$C_MAXRSS]; | |
3820 | |
3821 int | |
3822 rename_sans_version (from,to) | |
3823 char *from, *to; | |
3824 { | |
3825 short int chan; | |
3826 int stat; | |
3827 short int iosb[4]; | |
3828 int status; | |
3829 struct FAB to_fab = cc$rms_fab; | |
3830 struct NAM to_nam = cc$rms_nam; | |
3831 struct dsc$descriptor fib_d ={sizeof (fib),0,0,(char*) &fib}; | |
3832 struct dsc$descriptor fib_attr[2] | |
3833 = {{sizeof (fab_final_pro),ATR$C_FPRO,0,(char*) &fab_final_pro},{0,0,0,0}}; | |
3834 char to_esn[NAM$C_MAXRSS]; | |
3835 | |
3836 $DESCRIPTOR (disk,to_esn); | |
3837 | |
3838 to_fab.fab$l_fna = to; | |
3839 to_fab.fab$b_fns = strlen (to); | |
3840 to_fab.fab$l_nam = &to_nam; | |
3841 to_fab.fab$l_fop = FAB$M_NAM; | |
3842 | |
3843 to_nam.nam$l_esa = to_esn; | |
3844 to_nam.nam$b_ess = sizeof to_esn; | |
3845 | |
3846 status = SYS$PARSE (&to_fab, 0, 0); /* figure out the full file name */ | |
3847 | |
3848 if (to_nam.nam$l_fnb && NAM$M_EXP_VER) | |
3849 *(to_nam.nam$l_ver) = '\0'; | |
3850 | |
3851 stat = rename (from, to_esn); | |
3852 if (stat < 0) | |
3853 return stat; | |
3854 | |
3855 strcpy (vms_file_written, to_esn); | |
3856 | |
3857 to_fab.fab$l_fna = vms_file_written; /* this points to the versionless name */ | |
3858 to_fab.fab$b_fns = strlen (vms_file_written); | |
3859 | |
3860 /* Now set the file protection to the correct value */ | |
1596
0e105bd23f44
* systty.h, process.c, buffer.h, callproc.c, sysdep.c, dired.c:
Jim Blandy <jimb@redhat.com>
parents:
1570
diff
changeset
|
3861 SYS$OPEN (&to_fab, 0, 0); /* This fills in the nam$w_fid fields */ |
491 | 3862 |
3863 /* Copy these fields into the fib */ | |
3864 fib.fib$r_fid_overlay.fib$w_fid[0] = to_nam.nam$w_fid[0]; | |
3865 fib.fib$r_fid_overlay.fib$w_fid[1] = to_nam.nam$w_fid[1]; | |
3866 fib.fib$r_fid_overlay.fib$w_fid[2] = to_nam.nam$w_fid[2]; | |
3867 | |
1596
0e105bd23f44
* systty.h, process.c, buffer.h, callproc.c, sysdep.c, dired.c:
Jim Blandy <jimb@redhat.com>
parents:
1570
diff
changeset
|
3868 SYS$CLOSE (&to_fab, 0, 0); |
0e105bd23f44
* systty.h, process.c, buffer.h, callproc.c, sysdep.c, dired.c:
Jim Blandy <jimb@redhat.com>
parents:
1570
diff
changeset
|
3869 |
0e105bd23f44
* systty.h, process.c, buffer.h, callproc.c, sysdep.c, dired.c:
Jim Blandy <jimb@redhat.com>
parents:
1570
diff
changeset
|
3870 stat = SYS$ASSIGN (&disk, &chan, 0, 0); /* open a channel to the disk */ |
491 | 3871 if (!stat) |
1596
0e105bd23f44
* systty.h, process.c, buffer.h, callproc.c, sysdep.c, dired.c:
Jim Blandy <jimb@redhat.com>
parents:
1570
diff
changeset
|
3872 LIB$SIGNAL (stat); |
0e105bd23f44
* systty.h, process.c, buffer.h, callproc.c, sysdep.c, dired.c:
Jim Blandy <jimb@redhat.com>
parents:
1570
diff
changeset
|
3873 stat = SYS$QIOW (0, chan, IO$_MODIFY, iosb, 0, 0, &fib_d, |
491 | 3874 0, 0, 0, &fib_attr, 0); |
3875 if (!stat) | |
1596
0e105bd23f44
* systty.h, process.c, buffer.h, callproc.c, sysdep.c, dired.c:
Jim Blandy <jimb@redhat.com>
parents:
1570
diff
changeset
|
3876 LIB$SIGNAL (stat); |
0e105bd23f44
* systty.h, process.c, buffer.h, callproc.c, sysdep.c, dired.c:
Jim Blandy <jimb@redhat.com>
parents:
1570
diff
changeset
|
3877 stat = SYS$DASSGN (chan); |
491 | 3878 if (!stat) |
1596
0e105bd23f44
* systty.h, process.c, buffer.h, callproc.c, sysdep.c, dired.c:
Jim Blandy <jimb@redhat.com>
parents:
1570
diff
changeset
|
3879 LIB$SIGNAL (stat); |
766 | 3880 strcpy (vms_file_written, to_esn); /* We will write this to the terminal*/ |
491 | 3881 return 0; |
3882 } | |
3883 | |
3884 link (file, new) | |
3885 char * file, * new; | |
3886 { | |
3887 register status; | |
3888 struct FAB fab; | |
3889 struct NAM nam; | |
3890 unsigned short fid[3]; | |
3891 char esa[NAM$C_MAXRSS]; | |
3892 | |
3893 fab = cc$rms_fab; | |
3894 fab.fab$l_fop = FAB$M_OFP; | |
3895 fab.fab$l_fna = file; | |
3896 fab.fab$b_fns = strlen (file); | |
3897 fab.fab$l_nam = &nam; | |
3898 | |
3899 nam = cc$rms_nam; | |
3900 nam.nam$l_esa = esa; | |
3901 nam.nam$b_ess = NAM$C_MAXRSS; | |
3902 | |
3903 status = SYS$PARSE (&fab); | |
3904 if ((status & 1) == 0) | |
3905 { | |
3906 errno = EVMSERR; | |
3907 vaxc$errno = status; | |
3908 return -1; | |
3909 } | |
3910 status = SYS$SEARCH (&fab); | |
3911 if ((status & 1) == 0) | |
3912 { | |
3913 errno = EVMSERR; | |
3914 vaxc$errno = status; | |
3915 return -1; | |
3916 } | |
3917 | |
3918 fid[0] = nam.nam$w_fid[0]; | |
3919 fid[1] = nam.nam$w_fid[1]; | |
3920 fid[2] = nam.nam$w_fid[2]; | |
3921 | |
3922 fab.fab$l_fna = new; | |
3923 fab.fab$b_fns = strlen (new); | |
3924 | |
3925 status = SYS$PARSE (&fab); | |
3926 if ((status & 1) == 0) | |
3927 { | |
3928 errno = EVMSERR; | |
3929 vaxc$errno = status; | |
3930 return -1; | |
3931 } | |
3932 | |
3933 nam.nam$w_fid[0] = fid[0]; | |
3934 nam.nam$w_fid[1] = fid[1]; | |
3935 nam.nam$w_fid[2] = fid[2]; | |
3936 | |
3937 nam.nam$l_esa = nam.nam$l_name; | |
3938 nam.nam$b_esl = nam.nam$b_name + nam.nam$b_type + nam.nam$b_ver; | |
3939 | |
3940 status = SYS$ENTER (&fab); | |
3941 if ((status & 1) == 0) | |
3942 { | |
3943 errno = EVMSERR; | |
3944 vaxc$errno = status; | |
3945 return -1; | |
3946 } | |
3947 | |
3948 return 0; | |
3949 } | |
3950 | |
3951 croak (badfunc) | |
3952 char *badfunc; | |
3953 { | |
3954 printf ("%s not yet implemented\r\n", badfunc); | |
3955 reset_sys_modes (); | |
3956 exit (1); | |
3957 } | |
3958 | |
3959 long | |
3960 random () | |
3961 { | |
3962 /* Arrange to return a range centered on zero. */ | |
3963 return rand () - (1 << 30); | |
3964 } | |
3965 | |
3966 srandom (seed) | |
3967 { | |
3968 srand (seed); | |
3969 } | |
3970 #endif /* VMS */ | |
3971 | |
3972 #ifdef AIX | |
3973 | |
3974 /* Called from init_sys_modes. */ | |
3975 hft_init () | |
3976 { | |
3977 int junk; | |
3978 | |
3979 /* If we're not on an HFT we shouldn't do any of this. We determine | |
3980 if we are on an HFT by trying to get an HFT error code. If this | |
3981 call fails, we're not on an HFT. */ | |
3982 #ifdef IBMR2AIX | |
3983 if (ioctl (0, HFQERROR, &junk) < 0) | |
3984 return; | |
3985 #else /* not IBMR2AIX */ | |
3986 if (ioctl (0, HFQEIO, 0) < 0) | |
3987 return; | |
3988 #endif /* not IBMR2AIX */ | |
3989 | |
3990 /* On AIX the default hft keyboard mapping uses backspace rather than delete | |
3991 as the rubout key's ASCII code. Here this is changed. The bug is that | |
3992 there's no way to determine the old mapping, so in reset_sys_modes | |
3993 we need to assume that the normal map had been present. Of course, this | |
3994 code also doesn't help if on a terminal emulator which doesn't understand | |
3995 HFT VTD's. */ | |
3996 { | |
3997 struct hfbuf buf; | |
3998 struct hfkeymap keymap; | |
3999 | |
4000 buf.hf_bufp = (char *)&keymap; | |
4001 buf.hf_buflen = sizeof (keymap); | |
4002 keymap.hf_nkeys = 2; | |
4003 keymap.hfkey[0].hf_kpos = 15; | |
4004 keymap.hfkey[0].hf_kstate = HFMAPCHAR | HFSHFNONE; | |
4005 #ifdef IBMR2AIX | |
4006 keymap.hfkey[0].hf_keyidh = '<'; | |
4007 #else /* not IBMR2AIX */ | |
4008 keymap.hfkey[0].hf_page = '<'; | |
4009 #endif /* not IBMR2AIX */ | |
4010 keymap.hfkey[0].hf_char = 127; | |
4011 keymap.hfkey[1].hf_kpos = 15; | |
4012 keymap.hfkey[1].hf_kstate = HFMAPCHAR | HFSHFSHFT; | |
4013 #ifdef IBMR2AIX | |
4014 keymap.hfkey[1].hf_keyidh = '<'; | |
4015 #else /* not IBMR2AIX */ | |
4016 keymap.hfkey[1].hf_page = '<'; | |
4017 #endif /* not IBMR2AIX */ | |
4018 keymap.hfkey[1].hf_char = 127; | |
4019 hftctl (0, HFSKBD, &buf); | |
4020 } | |
4021 /* The HFT system on AIX doesn't optimize for scrolling, so it's really ugly | |
4022 at times. */ | |
4023 line_ins_del_ok = char_ins_del_ok = 0; | |
4024 } | |
4025 | |
4026 /* Reset the rubout key to backspace. */ | |
4027 | |
4028 hft_reset () | |
4029 { | |
4030 struct hfbuf buf; | |
4031 struct hfkeymap keymap; | |
4032 int junk; | |
4033 | |
4034 #ifdef IBMR2AIX | |
4035 if (ioctl (0, HFQERROR, &junk) < 0) | |
4036 return; | |
4037 #else /* not IBMR2AIX */ | |
4038 if (ioctl (0, HFQEIO, 0) < 0) | |
4039 return; | |
4040 #endif /* not IBMR2AIX */ | |
4041 | |
4042 buf.hf_bufp = (char *)&keymap; | |
4043 buf.hf_buflen = sizeof (keymap); | |
4044 keymap.hf_nkeys = 2; | |
4045 keymap.hfkey[0].hf_kpos = 15; | |
4046 keymap.hfkey[0].hf_kstate = HFMAPCHAR | HFSHFNONE; | |
4047 #ifdef IBMR2AIX | |
4048 keymap.hfkey[0].hf_keyidh = '<'; | |
4049 #else /* not IBMR2AIX */ | |
4050 keymap.hfkey[0].hf_page = '<'; | |
4051 #endif /* not IBMR2AIX */ | |
4052 keymap.hfkey[0].hf_char = 8; | |
4053 keymap.hfkey[1].hf_kpos = 15; | |
4054 keymap.hfkey[1].hf_kstate = HFMAPCHAR | HFSHFSHFT; | |
4055 #ifdef IBMR2AIX | |
4056 keymap.hfkey[1].hf_keyidh = '<'; | |
4057 #else /* not IBMR2AIX */ | |
4058 keymap.hfkey[1].hf_page = '<'; | |
4059 #endif /* not IBMR2AIX */ | |
4060 keymap.hfkey[1].hf_char = 8; | |
4061 hftctl (0, HFSKBD, &buf); | |
4062 } | |
4063 | |
4064 #endif /* AIX */ |