Install to the CVS repository what I forgot to install in my
[emacs.git] / src / unexenix.c
blob159c0b2f6d83c4b567562b2ebf022d78b24359ac
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.
9 Copyright (C) 1988, 1994, 2002, 2003, 2004,
10 2005 Free Software Foundation, Inc.
12 This file is part of GNU Emacs.
14 GNU Emacs is free software; you can redistribute it and/or modify
15 it under the terms of the GNU General Public License as published by
16 the Free Software Foundation; either version 2, or (at your option)
17 any later version.
19 GNU Emacs is distributed in the hope that it will be useful,
20 but WITHOUT ANY WARRANTY; without even the implied warranty of
21 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 GNU General Public License for more details.
24 You should have received a copy of the GNU General Public License
25 along with GNU Emacs; see the file COPYING. If not, write to
26 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
27 Boston, MA 02110-1301, USA. */
32 On 80386 Xenix, segmentation screws prevent us from modifying the text
33 segment at all. We basically just plug a new value for "data segment
34 size" into the countless headers and copy the other records straight
35 through. The data segment is ORG'ed at the xs_rbase value of the data
36 segment's xseg record (always @ 0x1880000, thanks to the "sophisticated
37 memory management hardware" of the chip) and extends to sbrk(0), exactly.
38 This code is afraid to malloc (should it be?), and alloca has to be the
39 wimpy, malloc-based version; consequently, data is usually copied in
40 smallish chunks.
42 gb@entity.com
45 #include <config.h>
46 #include <sys/types.h>
47 #include <fcntl.h>
48 #include <sys/file.h>
49 #include <sys/stat.h>
50 #include <stdio.h>
51 #include <varargs.h>
52 #include <a.out.h>
54 static void fatal_unexec ();
56 #define READ(_fd, _buffer, _size, _error_message, _error_arg) \
57 errno = EEOF; \
58 if (read(_fd, _buffer, _size) != _size) \
59 fatal_unexec(_error_message, _error_arg);
61 #define WRITE(_fd, _buffer, _size, _error_message, _error_arg) \
62 if (write(_fd, _buffer, _size) != _size) \
63 fatal_unexec(_error_message, _error_arg);
65 #define SEEK(_fd, _position, _error_message, _error_arg) \
66 errno = EEOF; \
67 if (lseek(_fd, _position, L_SET) != _position) \
68 fatal_unexec(_error_message, _error_arg);
70 extern int errno;
71 extern char *strerror ();
72 #define EEOF -1
74 #ifndef L_SET
75 #define L_SET 0
76 #endif
78 /* Should check the magic number of the old executable;
79 not yet written. */
80 check_exec (x)
81 struct xexec *x;
86 unexec (new_name, a_name, data_start, bss_start, entry_address)
87 char *new_name, *a_name;
88 unsigned data_start, bss_start, entry_address;
90 char *sbrk (), *datalim = sbrk (0), *data_org;
91 long segpos, textseen, textpos, textlen, datapos, datadiff, datalen;
93 struct xexec u_xexec, /* a.out header */
94 *u_xexecp = &u_xexec;
95 struct xext u_xext, /* extended header */
96 *u_xextp = &u_xext;
97 struct xseg u_xseg, /* segment table entry */
98 *u_xsegp = &u_xseg;
99 int i, nsegs, isdata = 0, infd, outfd;
101 infd = open (a_name, O_RDONLY, 0);
102 if (infd < 0) fatal_unexec ("opening %s", a_name);
104 outfd = creat (new_name, 0666);
105 if (outfd < 0) fatal_unexec ("creating %s", new_name);
107 READ (infd, u_xexecp, sizeof (struct xexec),
108 "error reading %s", a_name);
109 check_exec (u_xexecp);
110 READ (infd, u_xextp, sizeof (struct xext),
111 "error reading %s", a_name);
112 segpos = u_xextp->xe_segpos;
113 nsegs = u_xextp->xe_segsize / sizeof (struct xseg);
114 SEEK (infd, segpos, "seek error on %s", a_name);
115 for (i = 0; i < nsegs; i ++)
117 READ (infd, u_xsegp, sizeof (struct xseg),
118 "error reading %s", a_name);
119 switch (u_xsegp->xs_type)
121 case XS_TTEXT:
123 if (i == 0)
125 textpos = u_xsegp->xs_filpos;
126 textlen = u_xsegp->xs_psize;
127 break;
129 fatal_unexec ("invalid text segment in %s", a_name);
131 case XS_TDATA:
133 if (i == 1)
135 datapos = u_xsegp->xs_filpos;
136 datalen = datalim - (data_org = (char *)(u_xsegp->xs_rbase));
137 datadiff = datalen - u_xsegp->xs_psize;
138 break;
140 fatal_unexec ("invalid data segment in %s", a_name);
142 default:
144 if (i > 1) break;
145 fatal_unexec ("invalid segment record in %s", a_name);
149 u_xexecp->x_data = datalen;
150 u_xexecp->x_bss = 0;
151 WRITE (outfd, u_xexecp, sizeof (struct xexec),
152 "error writing %s", new_name);
153 WRITE (outfd, u_xextp, sizeof (struct xext),
154 "error writing %s", new_name);
155 SEEK (infd, segpos, "seek error on %s", a_name);
156 SEEK (outfd, segpos, "seek error on %s", new_name);
158 /* Copy the text segment record verbatim. */
160 copyrec (infd, outfd, sizeof (struct xseg), a_name, new_name);
162 /* Read, modify, write the data segment record. */
164 READ (infd, u_xsegp, sizeof (struct xseg),
165 "error reading %s", a_name);
166 u_xsegp->xs_psize = u_xsegp->xs_vsize = datalen;
167 u_xsegp->xs_attr &= (~XS_AITER & ~XS_ABSS);
168 WRITE (outfd, u_xsegp, sizeof (struct xseg),
169 "error writing %s", new_name);
171 /* Now copy any additional segment records, adjusting their
172 file position field */
174 for (i = 2; i < nsegs; i++)
176 READ (infd, u_xsegp, sizeof (struct xseg),
177 "error reading %s", a_name);
178 u_xsegp->xs_filpos += datadiff;
179 WRITE (outfd, u_xsegp, sizeof (struct xseg),
180 "error writing %s", new_name);
183 SEEK (infd, textpos, "seek error on %s", a_name);
184 SEEK (outfd, textpos, "seek error on %s", new_name);
185 copyrec (infd, outfd, textlen, a_name, new_name);
187 SEEK (outfd, datapos, "seek error on %s", new_name);
188 WRITE (outfd, data_org, datalen,
189 "write error on %s", new_name);
191 for (i = 2, segpos += (2 * sizeof (struct xseg));
192 i < nsegs;
193 i++, segpos += sizeof (struct xseg))
195 SEEK (infd, segpos, "seek error on %s", a_name);
196 READ (infd, u_xsegp, sizeof (struct xseg),
197 "read error on %s", a_name);
198 SEEK (infd, u_xsegp->xs_filpos, "seek error on %s", a_name);
199 /* We should be at eof in the output file here, but we must seek
200 because the xs_filpos and xs_psize fields in symbol table
201 segments are inconsistent. */
202 SEEK (outfd, u_xsegp->xs_filpos + datadiff, "seek error on %s", new_name);
203 copyrec (infd, outfd, u_xsegp->xs_psize, a_name, new_name);
205 close (infd);
206 close (outfd);
207 mark_x (new_name);
208 return 0;
211 copyrec (infd, outfd, len, in_name, out_name)
212 int infd, outfd, len;
213 char *in_name, *out_name;
215 char buf[BUFSIZ];
216 int chunk;
218 while (len)
220 chunk = BUFSIZ;
221 if (chunk > len)
222 chunk = len;
223 READ (infd, buf, chunk, "error reading %s", in_name);
224 WRITE (outfd, buf, chunk, "error writing %s", out_name);
225 len -= chunk;
230 * mark_x
232 * After successfully building the new a.out, mark it executable
234 static
235 mark_x (name)
236 char *name;
238 struct stat sbuf;
239 int um = umask (777);
240 umask (um);
241 if (stat (name, &sbuf) < 0)
242 fatal_unexec ("getting protection on %s", name);
243 sbuf.st_mode |= 0111 & ~um;
244 if (chmod (name, sbuf.st_mode) < 0)
245 fatal_unexec ("setting protection on %s", name);
248 static void
249 fatal_unexec (s, va_alist)
250 va_dcl
252 va_list ap;
253 if (errno == EEOF)
254 fputs ("unexec: unexpected end of file, ", stderr);
255 else
256 fprintf (stderr, "unexec: %s, ", strerror (errno));
257 va_start (ap);
258 _doprnt (s, ap, stderr);
259 fputs (".\n", stderr);
260 exit (1);
263 /* arch-tag: ce26be27-370a-438d-83b4-766059749a02
264 (do not change this comment) */