Annotation of GNUtools/emacs/src/unexenix.c, revision 1.1.1.1

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: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.