|
|
1.1 root 1: /* Unexec for Xenix.
2: Copyright (C) 1988 Free Software Foundation, Inc.
3:
4: Note that the GNU project considers support for Xenix operation
5: a peripheral activity which should not be allowed to divert effort
6: from development of the GNU system. Changes in this code will be
7: installed when Xenix users send them in, but aside from that
8: we don't plan to think about it, or about whether other Emacs
9: maintenance might break it.
10:
11: This program is free software; you can redistribute it and/or modify
12: it under the terms of the GNU General Public License as published by
13: the Free Software Foundation; either version 1, or (at your option)
14: any later version.
15:
16: This program is distributed in the hope that it will be useful,
17: but WITHOUT ANY WARRANTY; without even the implied warranty of
18: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19: GNU General Public License for more details.
20:
21: You should have received a copy of the GNU General Public License
22: along with this program; if not, write to the Free Software
23: Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24:
25: In other words, you are welcome to use, share and improve this program.
26: You are forbidden to forbid anyone else to use, share and improve
27: what you give them. Help stamp out software-hoarding! */
28:
29:
30: /*
31: On 80386 Xenix, segmentation screws prevent us from modifying the text
32: segment at all. We basically just plug a new value for "data segment
33: size" into the countless headers and copy the other records straight
34: through. The data segment is ORG'ed at the xs_rbase value of the data
35: segment's xseg record (always @ 0x1880000, thanks to the "sophisticated
36: memory management hardware" of the chip) and extends to sbrk(0), exactly.
37: This code is afraid to malloc (should it be?), and alloca has to be the
38: wimpy, malloc-based version; consequently, data is usually copied in
39: smallish chunks.
40:
41: [email protected]
42: */
43:
44: #include "config.h"
45: #include <sys/types.h>
46: #include <fcntl.h>
47: #include <sys/file.h>
48: #include <sys/stat.h>
49: #include <stdio.h>
50: #include <varargs.h>
51: #include <a.out.h>
52:
53: static void fatal_unexec ();
54:
55: #define READ(_fd, _buffer, _size, _error_message, _error_arg) \
56: errno = EEOF; \
57: if (read(_fd, _buffer, _size) != _size) \
58: fatal_unexec(_error_message, _error_arg);
59:
60: #define WRITE(_fd, _buffer, _size, _error_message, _error_arg) \
61: if (write(_fd, _buffer, _size) != _size) \
62: fatal_unexec(_error_message, _error_arg);
63:
64: #define SEEK(_fd, _position, _error_message, _error_arg) \
65: errno = EEOF; \
66: if (lseek(_fd, _position, L_SET) != _position) \
67: fatal_unexec(_error_message, _error_arg);
68:
69: extern int errno;
70: extern int sys_nerr;
71: extern char *sys_errlist[];
72: #define EEOF -1
73:
74: #ifndef L_SET
75: #define L_SET 0
76: #endif
77:
78: /* Should check the magic number of the old executable;
79: not yet written. */
80: check_exec (x)
81: struct xexec *x;
82: {
83: }
84:
85:
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;
89: {
90: char *sbrk (), *datalim = sbrk (0), *data_org;
91: long segpos, textseen, textpos, textlen, datapos, datadiff, datalen;
92:
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;
100:
101: infd = open (a_name, O_RDONLY, 0);
102: if (infd < 0) fatal_unexec ("opening %s", a_name);
103:
104: outfd = creat (new_name, 0666);
105: if (outfd < 0) fatal_unexec ("creating %s", new_name);
106:
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 ++)
116: {
117: READ (infd, u_xsegp, sizeof (struct xseg),
118: "error reading %s", a_name);
119: switch (u_xsegp->xs_type)
120: {
121: case XS_TTEXT:
122: {
123: if (i == 0)
124: {
125: textpos = u_xsegp->xs_filpos;
126: textlen = u_xsegp->xs_psize;
127: break;
128: }
129: fatal_unexec ("invalid text segment in %s", a_name);
130: }
131: case XS_TDATA:
132: {
133: if (i == 1)
134: {
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;
139: }
140: fatal_unexec ("invalid data segment in %s", a_name);
141: }
142: default:
143: {
144: if (i > 1) break;
145: fatal_unexec ("invalid segment record in %s", a_name);
146: }
147: }
148: }
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);
157:
158: /* Copy the text segment record verbatim. */
159:
160: copyrec (infd, outfd, sizeof (struct xseg), a_name, new_name);
161:
162: /* Read, modify, write the data segment record. */
163:
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);
170:
171: /* Now copy any additional segment records, adjusting their
172: file position field */
173:
174: for (i = 2; i < nsegs; i++)
175: {
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);
181: }
182:
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);
186:
187: SEEK (outfd, datapos, "seek error on %s", new_name);
188: WRITE (outfd, data_org, datalen,
189: "write error on %s", new_name);
190:
191: for (i = 2, segpos += (2 * sizeof (struct xseg));
192: i < nsegs;
193: i++, segpos += sizeof (struct xseg))
194: {
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);
204: }
205: close (infd);
206: close (outfd);
207: mark_x (new_name);
208: return 0;
209: }
210:
211: copyrec (infd, outfd, len, in_name, out_name)
212: int infd, outfd, len;
213: char *in_name, *out_name;
214: {
215: char buf[BUFSIZ];
216: int chunk;
217:
218: while (len)
219: {
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;
226: }
227: }
228:
229: /*
230: * mark_x
231: *
232: * After succesfully building the new a.out, mark it executable
233: */
234: static
235: mark_x (name)
236: char *name;
237: {
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);
246: }
247:
248: static void
249: fatal_unexec (s, va_alist)
250: va_dcl
251: {
252: va_list ap;
253: if (errno == EEOF)
254: fputs ("unexec: unexpected end of file, ", stderr);
255: else if (errno < sys_nerr)
256: fprintf (stderr, "unexec: %s, ", sys_errlist[errno]);
257: else
258: fprintf (stderr, "unexec: error code %d, ", errno);
259: va_start (ap);
260: _doprnt (s, ap, stderr);
261: fputs (".\n", stderr);
262: exit (1);
263: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.