Mercurial > emacs
annotate src/unexenix.c @ 8275:4fdf77f4e45c
type-break-mode: New variable and function.
type-break-interval: Increase default to 1 hour.
type-break-query-interval: Variable renamed from type-break-delay-interval.
type-break-keystroke-interval: Variable deleted.
type-break-keystroke-threshold: New variable.
type-break-demo-life: Function renamed from type-break-life.
type-break-demo-hanoi: Function renamed from type-break-hanoi.
type-break-alarm-p: Variable renamed from type-break-p.
type-break: Don't query.
type-break-query: (New function) query here.
type-break-check: Call type-break-query, not type-break.
Do nothing if type-break-mode is nil.
Increment type-break-keystroke-count with the length of this-command-keys,
not just 1.
Query for break when keystroke count exceeds cdr of keystroke threshold
variable.
Query for break after an alarm only if keystroke count exceeds car of
keystroke threshold variable.
type-break-select: Function deleted.
type-break: Move that code here.
type-break-cancel-schedule: Function renamed from cancel-type-break.
Reset type-break-alarm-p.
type-break-alarm: Function renamed from type-break-soon.
(top level): Call type-break-mode; don't set up hook explicitly.
author | Noah Friedman <friedman@splode.com> |
---|---|
date | Mon, 18 Jul 1994 07:37:18 +0000 |
parents | d1d144ed5b76 |
children | ee40177f6c68 |
rev | line source |
---|---|
484 | 1 /* Unexec for Xenix. |
2 Note that the GNU project considers support for Xenix operation | |
3 a peripheral activity which should not be allowed to divert effort | |
4 from development of the GNU system. Changes in this code will be | |
5 installed when Xenix users send them in, but aside from that | |
6 we don't plan to think about it, or about whether other Emacs | |
7 maintenance might break it. | |
8 | |
5521
d1d144ed5b76
Don't declare sys_errlist; declare strerror instead.
Roland McGrath <roland@gnu.org>
parents:
4696
diff
changeset
|
9 Copyright (C) 1988, 1994 Free Software Foundation, Inc. |
484 | 10 |
11 This file is part of GNU Emacs. | |
12 | |
13 GNU Emacs is free software; you can redistribute it and/or modify | |
14 it under the terms of the GNU General Public License as published by | |
5521
d1d144ed5b76
Don't declare sys_errlist; declare strerror instead.
Roland McGrath <roland@gnu.org>
parents:
4696
diff
changeset
|
15 the Free Software Foundation; either version 2, or (at your option) |
484 | 16 any later version. |
17 | |
18 GNU Emacs is distributed in the hope that it will be useful, | |
19 but WITHOUT ANY WARRANTY; without even the implied warranty of | |
20 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
21 GNU General Public License for more details. | |
22 | |
23 You should have received a copy of the GNU General Public License | |
24 along with GNU Emacs; see the file COPYING. If not, write to | |
25 the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ | |
26 | |
27 | |
28 | |
29 /* | |
30 On 80386 Xenix, segmentation screws prevent us from modifying the text | |
31 segment at all. We basically just plug a new value for "data segment | |
32 size" into the countless headers and copy the other records straight | |
33 through. The data segment is ORG'ed at the xs_rbase value of the data | |
34 segment's xseg record (always @ 0x1880000, thanks to the "sophisticated | |
35 memory management hardware" of the chip) and extends to sbrk(0), exactly. | |
36 This code is afraid to malloc (should it be?), and alloca has to be the | |
37 wimpy, malloc-based version; consequently, data is usually copied in | |
38 smallish chunks. | |
39 | |
40 gb@entity.com | |
41 */ | |
42 | |
4696
1fc792473491
Include <config.h> instead of "config.h".
Roland McGrath <roland@gnu.org>
parents:
3591
diff
changeset
|
43 #include <config.h> |
484 | 44 #include <sys/types.h> |
45 #include <fcntl.h> | |
46 #include <sys/file.h> | |
47 #include <sys/stat.h> | |
48 #include <stdio.h> | |
49 #include <varargs.h> | |
50 #include <a.out.h> | |
51 | |
52 static void fatal_unexec (); | |
53 | |
54 #define READ(_fd, _buffer, _size, _error_message, _error_arg) \ | |
55 errno = EEOF; \ | |
56 if (read(_fd, _buffer, _size) != _size) \ | |
57 fatal_unexec(_error_message, _error_arg); | |
58 | |
59 #define WRITE(_fd, _buffer, _size, _error_message, _error_arg) \ | |
60 if (write(_fd, _buffer, _size) != _size) \ | |
61 fatal_unexec(_error_message, _error_arg); | |
62 | |
63 #define SEEK(_fd, _position, _error_message, _error_arg) \ | |
64 errno = EEOF; \ | |
65 if (lseek(_fd, _position, L_SET) != _position) \ | |
66 fatal_unexec(_error_message, _error_arg); | |
67 | |
68 extern int errno; | |
5521
d1d144ed5b76
Don't declare sys_errlist; declare strerror instead.
Roland McGrath <roland@gnu.org>
parents:
4696
diff
changeset
|
69 extern char *strerror (); |
484 | 70 #define EEOF -1 |
71 | |
72 #ifndef L_SET | |
73 #define L_SET 0 | |
74 #endif | |
75 | |
76 /* Should check the magic number of the old executable; | |
77 not yet written. */ | |
78 check_exec (x) | |
79 struct xexec *x; | |
80 { | |
81 } | |
82 | |
83 | |
84 unexec (new_name, a_name, data_start, bss_start, entry_address) | |
85 char *new_name, *a_name; | |
86 unsigned data_start, bss_start, entry_address; | |
87 { | |
88 char *sbrk (), *datalim = sbrk (0), *data_org; | |
89 long segpos, textseen, textpos, textlen, datapos, datadiff, datalen; | |
90 | |
91 struct xexec u_xexec, /* a.out header */ | |
92 *u_xexecp = &u_xexec; | |
93 struct xext u_xext, /* extended header */ | |
94 *u_xextp = &u_xext; | |
95 struct xseg u_xseg, /* segment table entry */ | |
96 *u_xsegp = &u_xseg; | |
97 int i, nsegs, isdata = 0, infd, outfd; | |
98 | |
99 infd = open (a_name, O_RDONLY, 0); | |
100 if (infd < 0) fatal_unexec ("opening %s", a_name); | |
101 | |
102 outfd = creat (new_name, 0666); | |
103 if (outfd < 0) fatal_unexec ("creating %s", new_name); | |
104 | |
105 READ (infd, u_xexecp, sizeof (struct xexec), | |
106 "error reading %s", a_name); | |
107 check_exec (u_xexecp); | |
108 READ (infd, u_xextp, sizeof (struct xext), | |
109 "error reading %s", a_name); | |
110 segpos = u_xextp->xe_segpos; | |
111 nsegs = u_xextp->xe_segsize / sizeof (struct xseg); | |
112 SEEK (infd, segpos, "seek error on %s", a_name); | |
113 for (i = 0; i < nsegs; i ++) | |
114 { | |
115 READ (infd, u_xsegp, sizeof (struct xseg), | |
116 "error reading %s", a_name); | |
117 switch (u_xsegp->xs_type) | |
118 { | |
119 case XS_TTEXT: | |
120 { | |
121 if (i == 0) | |
122 { | |
123 textpos = u_xsegp->xs_filpos; | |
124 textlen = u_xsegp->xs_psize; | |
125 break; | |
126 } | |
127 fatal_unexec ("invalid text segment in %s", a_name); | |
128 } | |
129 case XS_TDATA: | |
130 { | |
131 if (i == 1) | |
132 { | |
133 datapos = u_xsegp->xs_filpos; | |
134 datalen = datalim - (data_org = (char *)(u_xsegp->xs_rbase)); | |
135 datadiff = datalen - u_xsegp->xs_psize; | |
136 break; | |
137 } | |
138 fatal_unexec ("invalid data segment in %s", a_name); | |
139 } | |
140 default: | |
141 { | |
142 if (i > 1) break; | |
143 fatal_unexec ("invalid segment record in %s", a_name); | |
144 } | |
145 } | |
146 } | |
147 u_xexecp->x_data = datalen; | |
148 u_xexecp->x_bss = 0; | |
149 WRITE (outfd, u_xexecp, sizeof (struct xexec), | |
150 "error writing %s", new_name); | |
151 WRITE (outfd, u_xextp, sizeof (struct xext), | |
152 "error writing %s", new_name); | |
153 SEEK (infd, segpos, "seek error on %s", a_name); | |
154 SEEK (outfd, segpos, "seek error on %s", new_name); | |
155 | |
156 /* Copy the text segment record verbatim. */ | |
157 | |
158 copyrec (infd, outfd, sizeof (struct xseg), a_name, new_name); | |
159 | |
160 /* Read, modify, write the data segment record. */ | |
161 | |
162 READ (infd, u_xsegp, sizeof (struct xseg), | |
163 "error reading %s", a_name); | |
164 u_xsegp->xs_psize = u_xsegp->xs_vsize = datalen; | |
165 u_xsegp->xs_attr &= (~XS_AITER & ~XS_ABSS); | |
166 WRITE (outfd, u_xsegp, sizeof (struct xseg), | |
167 "error writing %s", new_name); | |
168 | |
169 /* Now copy any additional segment records, adjusting their | |
170 file position field */ | |
171 | |
172 for (i = 2; i < nsegs; i++) | |
173 { | |
174 READ (infd, u_xsegp, sizeof (struct xseg), | |
175 "error reading %s", a_name); | |
176 u_xsegp->xs_filpos += datadiff; | |
177 WRITE (outfd, u_xsegp, sizeof (struct xseg), | |
178 "error writing %s", new_name); | |
179 } | |
180 | |
181 SEEK (infd, textpos, "seek error on %s", a_name); | |
182 SEEK (outfd, textpos, "seek error on %s", new_name); | |
183 copyrec (infd, outfd, textlen, a_name, new_name); | |
184 | |
185 SEEK (outfd, datapos, "seek error on %s", new_name); | |
186 WRITE (outfd, data_org, datalen, | |
187 "write error on %s", new_name); | |
188 | |
189 for (i = 2, segpos += (2 * sizeof (struct xseg)); | |
190 i < nsegs; | |
191 i++, segpos += sizeof (struct xseg)) | |
192 { | |
193 SEEK (infd, segpos, "seek error on %s", a_name); | |
194 READ (infd, u_xsegp, sizeof (struct xseg), | |
195 "read error on %s", a_name); | |
196 SEEK (infd, u_xsegp->xs_filpos, "seek error on %s", a_name); | |
197 /* We should be at eof in the output file here, but we must seek | |
198 because the xs_filpos and xs_psize fields in symbol table | |
199 segments are inconsistent. */ | |
200 SEEK (outfd, u_xsegp->xs_filpos + datadiff, "seek error on %s", new_name); | |
201 copyrec (infd, outfd, u_xsegp->xs_psize, a_name, new_name); | |
202 } | |
203 close (infd); | |
204 close (outfd); | |
205 mark_x (new_name); | |
206 return 0; | |
207 } | |
208 | |
209 copyrec (infd, outfd, len, in_name, out_name) | |
210 int infd, outfd, len; | |
211 char *in_name, *out_name; | |
212 { | |
213 char buf[BUFSIZ]; | |
214 int chunk; | |
215 | |
216 while (len) | |
217 { | |
218 chunk = BUFSIZ; | |
219 if (chunk > len) | |
220 chunk = len; | |
221 READ (infd, buf, chunk, "error reading %s", in_name); | |
222 WRITE (outfd, buf, chunk, "error writing %s", out_name); | |
223 len -= chunk; | |
224 } | |
225 } | |
226 | |
227 /* | |
228 * mark_x | |
229 * | |
3591
507f64624555
Apply typo patches from Paul Eggert.
Jim Blandy <jimb@redhat.com>
parents:
484
diff
changeset
|
230 * After successfully building the new a.out, mark it executable |
484 | 231 */ |
232 static | |
233 mark_x (name) | |
234 char *name; | |
235 { | |
236 struct stat sbuf; | |
237 int um = umask (777); | |
238 umask (um); | |
239 if (stat (name, &sbuf) < 0) | |
240 fatal_unexec ("getting protection on %s", name); | |
241 sbuf.st_mode |= 0111 & ~um; | |
242 if (chmod (name, sbuf.st_mode) < 0) | |
243 fatal_unexec ("setting protection on %s", name); | |
244 } | |
245 | |
246 static void | |
247 fatal_unexec (s, va_alist) | |
248 va_dcl | |
249 { | |
250 va_list ap; | |
251 if (errno == EEOF) | |
252 fputs ("unexec: unexpected end of file, ", stderr); | |
253 else | |
5521
d1d144ed5b76
Don't declare sys_errlist; declare strerror instead.
Roland McGrath <roland@gnu.org>
parents:
4696
diff
changeset
|
254 fprintf (stderr, "unexec: %s, ", strerror (errno)); |
484 | 255 va_start (ap); |
256 _doprnt (s, ap, stderr); | |
257 fputs (".\n", stderr); | |
258 exit (1); | |
259 } |