|
|
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.