diff options
Diffstat (limited to 'obsolete/support/undump')
40 files changed, 7756 insertions, 0 deletions
diff --git a/obsolete/support/undump/0UNSUPPORTED b/obsolete/support/undump/0UNSUPPORTED new file mode 100644 index 0000000000..64cacca715 --- /dev/null +++ b/obsolete/support/undump/0UNSUPPORTED @@ -0,0 +1,5 @@ + +The programs in this directory are now unsupported. +For almost all systems, undumped TeX is an inferior approach +and the intrinsic machine dependency of these programs makes +them too costly to maintain with any promise of reliability. diff --git a/obsolete/support/undump/Encore/BU-README b/obsolete/support/undump/Encore/BU-README new file mode 100644 index 0000000000..1708792a51 --- /dev/null +++ b/obsolete/support/undump/Encore/BU-README @@ -0,0 +1,12 @@ + + The files you are looking for are undump.c and unexec.c. If you have + problems with this, please contact me by phone. I will be out of + town from the 12th to the 19th of December 88. + + Tom Meier + Boston Univeristy Info Tech + + 617-353-2780 + + p.s. I included the other files for history. + diff --git a/obsolete/support/undump/Encore/Makefile b/obsolete/support/undump/Encore/Makefile new file mode 100644 index 0000000000..77de95bc65 --- /dev/null +++ b/obsolete/support/undump/Encore/Makefile @@ -0,0 +1,13 @@ +BINDIR=/usr/local + +undump: undump.o scanargs.o + cc -O -o undump undump.o scanargs.o + +undump.o: undump.c + cc -O -c undump.c + +clean: + rm -f *.o + +install: undump + cp undump $(BINDIR) diff --git a/obsolete/support/undump/Encore/dumpcore.c b/obsolete/support/undump/Encore/dumpcore.c new file mode 100644 index 0000000000..e607a95c70 --- /dev/null +++ b/obsolete/support/undump/Encore/dumpcore.c @@ -0,0 +1,43 @@ +#include <stdio.h> +#include <sys/param.h> +#include <sys/file.h> +#include <aouthdr.h> +#include <sys/ptrace.h> + +struct ptrace_user u; + + +main(argc,argv) +int argc; +char *argv[]; +{ + + int fd; + + if (argc < 2) { + printf("give me a break, and a file...\n"); + exit(0); + } + + fd = open(argv[1],O_RDONLY); + read(fd,&u,sizeof (struct ptrace_user)); + printf("sizeof ptrace: %o\n",sizeof(struct ptrace_user)); + printf("dsize: %lo\n",u.pt_dsize); + printf("ssize: %lo\n",u.pt_ssize); + printf("magic: %o\n",u.pt_aouthdr.magic); + printf("vstamp: %o\n",u.pt_aouthdr.vstamp); + printf("tsize: %lo\n",u.pt_aouthdr.tsize); + printf("dsize: %lo\n",u.pt_aouthdr.dsize); + printf("bsize: %lo\n",u.pt_aouthdr.bsize); + printf("msize: %lo\n",u.pt_aouthdr.msize); + printf("mod_start: %lo\n",u.pt_aouthdr.mod_start); + printf("entry: %lo\n",u.pt_aouthdr.entry); + printf("text_start: %lo\n",u.pt_aouthdr.text_start); + printf("data_start: %lo\n",u.pt_aouthdr.data_start); + printf("entry_mod: %lo\n",u.pt_aouthdr.entry_mod); + printf("flags: %o\n",u.pt_aouthdr.flags); + printf("\n"); + close(fd); + } + + diff --git a/obsolete/support/undump/Encore/dumpit.c b/obsolete/support/undump/Encore/dumpit.c new file mode 100644 index 0000000000..3090a83820 --- /dev/null +++ b/obsolete/support/undump/Encore/dumpit.c @@ -0,0 +1,74 @@ +#include <stdio.h> +#include <sys/file.h> +#include <filehdr.h> +#include <aouthdr.h> +#include <scnhdr.h> + + +#define MAXSCNS 16 +struct filehdr hdr; +AOUTHDR shdr; +struct scnhdr scns[MAXSCNS]; +int nscns; + + +main(argc,argv) +int argc; +char *argv[]; +{ + + int fd,i; + + if (argc < 2) { + printf("give me a break, and a file...\n"); + exit(0); + } + fd = open(argv[1],O_RDONLY); + read(fd,&hdr,sizeof(struct filehdr)); + nscns = hdr.f_nscns; + printf("magic: %o\n",hdr.f_magic); + printf("sections: %o\n",hdr.f_nscns); + printf("timestamp: %lo\n",hdr.f_timdat); + printf("sym ptr: %lo\n",hdr.f_symptr); + printf("num sym ents: %lo\n",hdr.f_nsyms); + printf("size of syshdr: %o\n",hdr.f_opthdr); + printf("flags: %o\n",hdr.f_flags); + printf("\n"); + if (hdr.f_opthdr != 0) { + read(fd,&shdr,sizeof(AOUTHDR)); + printf("magic: %o\n",shdr.magic); + printf("vstamp: %o\n",shdr.vstamp); + printf("tsize: %lo\n",shdr.tsize); + printf("dsize: %lo\n",shdr.dsize); + printf("bsize: %lo\n",shdr.bsize); + printf("msize: %lo\n",shdr.msize); + printf("mod_start: %lo\n",shdr.mod_start); + printf("entry: %lo\n",shdr.entry); + printf("text_start: %lo\n",shdr.text_start); + printf("data_start: %lo\n",shdr.data_start); + printf("entry_mod: %lo\n",shdr.entry_mod); + printf("flags: %o\n",shdr.flags); + printf("\n"); + } + for(i=0;(i != nscns);i++) { + read(fd,&scns[i],sizeof(struct scnhdr)); + } + for(i=0;(i != nscns);i++) { + printf("name: %s\n",scns[i].s_name); + printf("paddr: %lo\n",scns[i].s_paddr); + printf("vaddr: %lo\n",scns[i].s_vaddr); + printf("size: %lo\n",scns[i].s_size); + printf("scnptr: %lo\n",scns[i].s_scnptr); + printf("relptr: %lo\n",scns[i].s_relptr); + printf("lnnoptr: %lo\n",scns[i].s_lnnoptr); + printf("nreloc: %o\n",scns[i].s_nreloc); + printf("nlnno: %o\n",scns[i].s_nlnno); + printf("flags: %lo\n",scns[i].s_flags); + printf("symptr: %lo\n",scns[i].s_symptr); + printf("modno: %o\n",scns[i].s_modno); + printf("\n"); + } + close(fd); + } + + diff --git a/obsolete/support/undump/Encore/undo.c b/obsolete/support/undump/Encore/undo.c new file mode 100644 index 0000000000..c0ee0dfcf6 --- /dev/null +++ b/obsolete/support/undump/Encore/undo.c @@ -0,0 +1,480 @@ +/* Support routines for the undo facility. + Copyright (C) 1985, 1986 Free Software Foundation, Inc. + +This file is part of GNU Emacs. + +GNU Emacs is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY. No author or distributor +accepts responsibility to anyone for the consequences of using it +or for whether it serves any particular purpose or works at all, +unless he says so in writing. Refer to the GNU Emacs General Public +License for full details. + +Everyone is granted permission to copy, modify and redistribute +GNU Emacs, but only under the conditions described in the +GNU Emacs General Public License. A copy of this license is +supposed to have been given to you along with GNU Emacs so you +can know your rights and responsibilities. It should be in a +file named COPYING. Among other things, the copyright notice +and this notice must be preserved on all copies. */ + + +#include "config.h" +#include "lisp.h" +#include "undo.h" +#include "commands.h" +#include "buffer.h" + +/* Access undo records of current buffer */ +/* These assume that `u' points to the buffer's undodata */ +#define UndoRQ (u->undorecs) +#define UndoCQ (u->undochars) +#define FillRQ (u->nextrec) +#define FillCQ (u->nextchar) + +/* Record last undo record made, and what buffer made in */ +static struct UndoRec *LastUndoRec; +static struct buffer *LastUndoBuf; + +/* Record progress of undoing */ +static NUndone; +static NCharsLeft; +static LastUndoneC; +static LastUndone; +static struct buffer *LastUndoneBuf; + +Lisp_Object Fundo_boundary (); + +make_undo_records (b) + struct buffer *b; +{ + register struct UndoData *u; + b->undodata = u = (struct UndoData *) xmalloc (sizeof (struct UndoData)); + u->undorecs + = (struct UndoRec *) xmalloc (sizeof (struct UndoRec) * InitNUndoR); + u->undochars = (char *) xmalloc (InitNUndoC); + u->undorecs[InitNUndoR - 1].kind = Unundoable; + u->nextrec = 0; + u->nextchar = 0; + u->num_undorecs = InitNUndoR; + u->num_undochars = InitNUndoC; +} + +free_undo_records (b) + struct buffer *b; +{ + register struct UndoData *u = b->undodata; + free (u->undorecs); + free (u->undochars); + free (u); +} + +struct UndoRec * +record_undo (kind, pos, len) + enum Ukinds kind; +{ + register struct UndoData *u = bf_cur->undodata; + register struct UndoRec *p = &UndoRQ[FillRQ]; + register struct UndoRec *np; + + FillRQ++; + if (FillRQ >= NUndoR) + FillRQ = 0; + else if (FillRQ >= u->num_undorecs) + { + np = (struct UndoRec *) xrealloc (UndoRQ, NUndoR * sizeof *p); + if (np) + { + UndoRQ = np; + p = &UndoRQ[FillRQ-1]; + u->num_undorecs = NUndoR; + np[NUndoR - 1].kind = Unundoable; + } + else + FillRQ = 0; + } + UndoRQ[FillRQ].kind = Unundoable; + p -> kind = kind; + p -> pos = pos; + p -> len = len; + LastUndoRec = p; + LastUndoBuf = bf_cur; + if (kind != Uboundary) + LastUndone = -1; + return p; +} + +record_insert (pos, n) +{ + register struct UndoRec *p = LastUndoRec; + if (!bf_cur->undodata) + return; + if (LastUndoBuf != bf_cur) + { + Fundo_boundary (); + p = 0; + } + + if (bf_modified <= bf_cur->save_modified) + record_undo (Uunmod, pos, bf_cur->modtime); + + if (p && p -> kind == Udelete && p -> pos + p -> len == pos) + p -> len += n; + else + record_undo (Udelete, pos, n); +} + +record_delete (pos, n) + int pos, n; +{ + register struct UndoRec *p = LastUndoRec; + + if (!bf_cur->undodata) + return; + if (LastUndoBuf != bf_cur) + { + Fundo_boundary (); + p = 0; + } + + if (bf_modified <= bf_cur->save_modified) + record_undo (Uunmod, pos, bf_cur->modtime); + + if (p && p->kind == Uinsert && p->pos == pos && p->len > 0) + p->len += n; + else if (point == pos + n) + record_undo (Uinsert, pos + n, - n); + else + record_undo (Uinsert, pos, n); + + record_chars (pos, n); +} + +record_chars (pos, n) + register int pos, n; +{ + if (pos < bf_s1 + 1 && pos + n > bf_s1 + 1) + { + record_block (&CharAt (pos), bf_s1 + 1 - pos); + n -= bf_s1 + 1 - pos; + pos = bf_s1 + 1; + } + + record_block (&CharAt (pos), n); +} + +record_block (p, n) + register char *p; + register int n; +{ + register char *cp; + register struct UndoData *u = bf_cur->undodata; + register int i; + + NCharsLeft -= n; + cp = &UndoCQ[FillCQ]; + + while (n > 0) + { + i = u->num_undochars - FillCQ; + if (i > n) i = n; + if (i > 0) + { + bcopy (p, cp, i); + p += i; + FillCQ += i; + n -= i; + } + + if (n == 0) + break; + + if (FillCQ >= NUndoC) + { + FillCQ = 0; + cp = UndoCQ; + } + else + { + cp = (char *) xrealloc (UndoCQ, NUndoC); + UndoCQ = cp; + cp += FillCQ; + NCharsLeft += NUndoC - u->num_undochars; + u->num_undochars = NUndoC; + } + } +} + +record_change (pos, n) + int pos, n; +{ + register struct UndoRec *p = LastUndoRec; + if (!bf_cur->undodata) + return; + if (LastUndoBuf != bf_cur) + { + Fundo_boundary (); + p = 0; + } + + if (bf_modified <= bf_cur->save_modified) + record_undo (Uunmod, pos, bf_cur->modtime); + + if (p && p->kind == Uchange && p->len > 0 && p->pos + p->len == pos) + p->len += n; + else if (point == pos + n) + record_undo (Uchange, pos + n, -n); + else + record_undo (Uchange, pos, n); + + record_chars (pos, n); +} + +record_change1 (pos, bufp, n) + int pos; + char *bufp; + int n; +{ + register struct UndoRec *p = LastUndoRec; + if (!bf_cur->undodata) + return; + if (LastUndoBuf != bf_cur) + { + Fundo_boundary (); + p = 0; + } + if (p && p->kind == Uchange && p->len > 0 && p->pos + p->len == pos) + p -> len += n; + else + record_undo (Uchange, pos, n); + + record_block (bufp, n); +} + +DoneIsDone () +{ + register struct UndoData *u = bf_cur->undodata; + register struct UndoRec *p; + + if (!u) + return 0; + + p = &UndoRQ[(FillRQ + u->num_undorecs - 1) % u->num_undorecs]; + if (p->kind != Unundoable) + record_undo (Unundoable, point, 0); + return 0; +} + +DEFUN ("undo-boundary", Fundo_boundary, Sundo_boundary, 0, 0, 0, + "Mark a boundary between units of undo.\n\ +An undo command will stop at this point,\n\ +but another undo command will undo to the previous boundary.") + () +{ + register struct UndoData *u = bf_cur->undodata; + register struct UndoRec *p; + + if (!u) + return Qnil; + + p = &UndoRQ[(FillRQ + u->num_undorecs - 1) % u->num_undorecs]; + if (p->kind != Uboundary) + record_undo (Uboundary, point, 0); + return Qnil; +} + +DEFUN ("undo-more", Fundo_more, Sundo_more, 1, 1, 0, + "Undo back N undo-boundaries beyond what was already undone recently.\n\ +Call undo-start to get ready to undo recent changes,\n\ +then call undo-more one or more times to undo them.") + (pfxarg) + Lisp_Object pfxarg; +{ + register struct UndoData *u = bf_cur->undodata; + register int n = 0; + register int chars; + register int i = LastUndone; + register int arg = XINT (pfxarg); + register int len, pos; + char tembuf[NUndoC]; + + if (!u) + return Qnil; + + if (LastUndoneBuf != bf_cur || + i == -1) + error ("Cannot undo more: changes have been made since the last undo"); + + while (1) + { + while (UndoRQ[i = (!i ? u->num_undorecs-1 : i-1)].kind != Uboundary) + { + len = UndoRQ[i].len; + if (len < 0) len = - len; + if (((UndoRQ[i].kind == Uinsert || UndoRQ[i].kind == Uchange) + && (NCharsLeft -= len) < 0) + || UndoRQ[i].kind == Unundoable || NUndone >= u->num_undorecs) + error ("No further undo information available"); + NUndone++; + n++; + } + NUndone++; + n++; + if (--arg <= 0) + break; + } + + i = LastUndone; + chars = LastUndoneC; + while (--n >= 0) + { + if (!i) + i = u->num_undorecs; + i--; + + len = UndoRQ[i].len; + pos = UndoRQ[i].pos; + + if (UndoRQ[i].kind == Uchange || UndoRQ[i].kind == Uinsert) + if (len < 0) + { + pos += len; + len = - len; + } + +#ifdef SWITCH_ENUM_BUG + switch ((int) UndoRQ[i].kind) +#else + switch (UndoRQ[i].kind) +#endif + { + case Uchange: + case Udelete: + if (pos < FirstCharacter || pos + len > NumCharacters + 1) + error ("Changes to be undone are outside visible portion of buffer"); + SetPoint (pos); + break; + + case Uinsert: + if (pos < FirstCharacter || pos > NumCharacters + 1) + error ("Changes to be undone are outside visible portion of buffer"); + SetPoint (pos); + } + +#ifdef SWITCH_ENUM_BUG + switch ((int) UndoRQ[i].kind) +#else + switch (UndoRQ[i].kind) +#endif + { + case Uboundary: + break; + + case Udelete: + del_range (point, point + len); + break; + + case Uchange: + if (len > NUndoC) + /* Should have already said "No more undo info available" */ + abort (); + save_undone_chars (pos, len, tembuf); + chars -= len; + if (chars < 0) + { + replace_chars (point - chars, len + chars, UndoCQ); + replace_chars (point, - chars, UndoCQ + chars + u->num_undochars); + chars += u->num_undochars; + } + else + replace_chars (point, len, UndoCQ + chars); + record_change1 (point, tembuf, len); + SetPoint (UndoRQ[i].pos); + break; + + case Uinsert: + chars -= len; + if (chars < 0) + { + InsCStr (UndoCQ + chars + u->num_undochars, - chars); + InsCStr (UndoCQ, len + chars); + chars += u->num_undochars; + } + else + InsCStr (UndoCQ + chars, len); + SetPoint (UndoRQ[i].pos); + break; + + case Uunmod: + /* If this Uunmod records an obsolete save + (not matching the actual disk file) + then don't mark unmodified. */ + if (len != bf_cur->modtime) + break; +#ifdef CLASH_DETECTION + Funlock_buffer (); +#endif /* CLASH_DETECTION */ + bf_cur->save_modified = bf_modified; + RedoModes++; + break; + + default: + error ("Something rotten in undo"); + return Qnil; + } + } + LastUndone = i; + LastUndoneC = chars; + return Qnil; +} + +replace_chars (pos, n, string) + register int pos, n; + register unsigned char *string; +{ + modify_region (pos, pos + n); + while (--n >= 0) + { + CharAt (pos) = *string++; + pos++; + } +} + +save_undone_chars (pos, n, p) + register int pos, n; + register char *p; +{ + if (pos < bf_s1 + 1 && pos + n > bf_s1 + 1) + { + bcopy (&CharAt (pos), p, bf_s1 + 1 - pos); + p += bf_s1 + 1 - pos; + n -= bf_s1 + 1 - pos; + pos = bf_s1 + 1; + } + + bcopy (&CharAt (pos), p, n); +} + +DEFUN ("undo-start", Fundo_start, Sundo_start, 0, 0, 0, + "Move undo-pointer to front of undo records.\n\ +The next call to undo-more will undo the most recently made change.") + () +{ + register struct UndoData *u = bf_cur->undodata; + + if (!u) + error ("Undo information not kept for this buffer"); + LastUndoneBuf = bf_cur; + NCharsLeft = u->num_undochars; + NUndone = 0; + LastUndone = FillRQ; + LastUndoneC = FillCQ; + return Qnil; +} + +syms_of_undo () +{ + defsubr (&Sundo_start); + defsubr (&Sundo_boundary); + defsubr (&Sundo_more); +} diff --git a/obsolete/support/undump/Encore/undo.h b/obsolete/support/undump/Encore/undo.h new file mode 100644 index 0000000000..11b3b8cf16 --- /dev/null +++ b/obsolete/support/undump/Encore/undo.h @@ -0,0 +1,70 @@ +/* Definitions of objects used by the GNU Emacs undo facility. + Copyright (C) 1985 Free Software Foundation, Inc. + +This file is part of GNU Emacs. + +GNU Emacs is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY. No author or distributor +accepts responsibility to anyone for the consequences of using it +or for whether it serves any particular purpose or works at all, +unless he says so in writing. Refer to the GNU Emacs General Public +License for full details. + +Everyone is granted permission to copy, modify and redistribute +GNU Emacs, but only under the conditions described in the +GNU Emacs General Public License. A copy of this license is +supposed to have been given to you along with GNU Emacs so you +can know your rights and responsibilities. It should be in a +file named COPYING. Among other things, the copyright notice +and this notice must be preserved on all copies. */ + + +enum Ukinds { /* The events that can exist in the undo + queue. */ + Uboundary, /* A boundary between sets of undoable things + */ + Unundoable, /* What's done is done -- some things can't + be undone */ + Udelete, /* Delete characters to perform the undo */ + Uinsert, /* Insert .... */ + Uchange, /* Replace characters */ + Uunmod, /* Clear modification-flag to perform undo */ +}; + +struct UndoRec { /* A record of a single undo action */ + enum Ukinds kind; /* the kind of action to be undone */ + int pos; /* Where change starts or ends. */ + int len; /* Number of characters to insert, delete or + replace. Negative means they stretch + back from `pos'. */ +}; + +/* Note: in a record of type Uunmod, the `len' field is really + the buffer->modtime associated with the state at that time. + The buffer is marked as unmodified by undoing the Uunmod + only if the modtime field matches. */ + +/* The undo history consists of two circular queues, one of characters and + one of UndoRecs. When Uinsert recs are added to UndoRQ characters get + added to UndoCQ. The position of the characters can be reconstructed by + subtracting len from the fill pointer. */ + +#define NUndoR (((1 << 13) - 4) / sizeof (struct UndoRec)) +#define NUndoC ((1 << 13) - 4) + +/* Initially allocate them these sizes; + if these sizes get filled up, make them full size */ + +#define InitNUndoR 8 +#define InitNUndoC (512 - 4) + +struct UndoData + { + struct UndoRec *undorecs; /* The undo records, NUndoR of them */ + char *undochars; /* And the characters associated, NUndoC in all */ + int nextrec; /* Indices for storing in above two */ + int nextchar; + int num_undorecs; /* Sizes allocated */ + int num_undochars; + }; + diff --git a/obsolete/support/undump/Encore/undump.1 b/obsolete/support/undump/Encore/undump.1 new file mode 100644 index 0000000000..797cdb0377 --- /dev/null +++ b/obsolete/support/undump/Encore/undump.1 @@ -0,0 +1,28 @@ +.TH UNDUMP 1 "University of Utah" +.SH NAME +undump \- convert a core dump to an executable a.out file +.SH SYNOPSIS +undump new-a.out-file [old-a.out-file] [core-file] +.SH DESCRIPTION +Undump takes a core dump file and the executable "a.out" file which +caused it and produces a new executable file with all static +variables initialised to the values they held at the time of the +core dump. It is primarily useful for programs which take a long time +to initialise themselves, e.g. Emacs. The idea is to go through all of +the initialisations and then create a core dump (e.g. with the abort() +call). One then uses undump to make a new executable file with all of it +done. This usually implies the use of a global flag variable which says +whether or not initialisation has been done. +.PP +Undump's arguments, old-a.out-file and core-file, default to "a.out" and +"core", respectively. +.PP +A few things to keep in mind about undump: +.IP +It doesn't preserve open files. +.IP +The program will be re-entered at the beginning of main(), not at the point +where the core dump occurred. +.SH BUGS +Probably should have an option to not require +old-a.out-file if the core came from a 407 file. diff --git a/obsolete/support/undump/Encore/undump.c b/obsolete/support/undump/Encore/undump.c new file mode 100644 index 0000000000..02d8b1d582 --- /dev/null +++ b/obsolete/support/undump/Encore/undump.c @@ -0,0 +1,374 @@ +/* + * This program was advertised on unix-wizards. I have had such a large + * response I'm sending it out to the world. + * + * Here is the source. It works fine under 4.1bsd, I see no fundamental + * reason why it shouldn't work on an 11. (Except possibly small format + * changes in exec header or user structure.) No documentation yet. + * Usage is + * undump new-a.out-file [old-a.out-file] [core-file] + * where old-a.out-file and core-file default to "a.out" and "core", + * respectively. Probably should have an option to not require + * old-a.out-file if the core came from a 407 file. + * + * It doesn't preserve open files, and the program is re-entered at main + * when you run it. It's used locally to dump a lisp and restart it. + * + * It requires a local subroutine called scanargs, somewhat similar to + * getopt (I think). You should be able to easily get around this, though. + * =Spencer + */ + + +/* + * undump.c - Convert a core file to an a.out. + * + * Author: Spencer W. Thomas + * Computer Science Dept. + * University of Utah + * Date: Wed Feb 17 1982 + * Copyright (c) 1982 Spencer W. Thomas + * + * Usage: + * undump new-a.out [a.out] [core] + */ + +#include <stdio.h> +#include <sys/param.h> +#include <sys/dir.h> +#include <sys/stat.h> +#include <aouthdr.h> +#include <filehdr.h> +#include <scnhdr.h> +#include <linenum.h> +#include <sys/ptrace.h> + +#define PSIZE 10240 +#define MAXSCNS 8 + +struct ptrace_user u; +AOUTHDR ahdr, oahdr; +struct filehdr fhdr, ofhdr; +struct scnhdr scns[MAXSCNS]; +int nscns; +long cur_pos, sym_top; + + +main(argc, argv) +char **argv; +{ + char *new_name, *a_out_name = "a.out", *core_name = "core"; + FILE *new, *a_out, *core; + + if (scanargs(argc, argv, "undump new-a.out!s a.out%s core%s", + &new_name, &a_out_name, &core_name) + != 1) + exit(1); + + if ((a_out = fopen(a_out_name, "r")) == NULL) + { + perror(a_out_name); + exit(1); + } + if ((core = fopen(core_name, "r")) == NULL) + { + perror(core_name); + exit(1); + } + if ((new = fopen(new_name, "w")) == NULL) + { + perror(new_name); + exit(1); + } + + read_u(core); + make_hdr(new, a_out); + copy_text(new, a_out); + copy_data(new, core); + copy_sym(new, a_out); + fclose(new); + fclose(core); + fclose(a_out); + mark_x(new_name); +} + +/* + * read the u structure from the core file. + */ +read_u(core) +FILE *core; +{ + if ( fread(&u, sizeof u, 1, core) != 1 ) + { + perror("Couldn't read user structure from core file"); + exit(1); + } +} + +/* + * Make the header in the new a.out from the header in the old one + * modified by the new data size. + */ +make_hdr(new, a_out) +FILE *new, *a_out; +{ + + int i; + +/* sym_top points to the beginning of the line#/sym/str data */ + +/* + * read file header from a.out + */ + + if (fread(&fhdr, sizeof fhdr, 1, a_out) != 1) + { + perror("Couldn't read file header from a.out file"); + exit(1); + } + +/* + * read system header from a.out COFF format + */ + + if (fhdr.f_opthdr > 0) + { + if (fread(&ahdr, sizeof ahdr, 1, a_out) != 1) + { + perror("Couldn't read system file header from a.out file"); + exit(1); + } + +/* + * read section headers from a.out COFF format + */ + + nscns = fhdr.f_nscns; + for(i=0;(i != nscns);i++) { + if (fread(&scns[i], sizeof(struct scnhdr), 1, a_out) != 1) { + perror("Couldn't read section headers from a.out file"); + exit(1); + } + } + } + + +/* if N_BADMAG(hdr) + { + fprintf(stderr, "a.out file doesn't have legal magic number\n"); + exit(1); + } */ + + + + if (ahdr.magic != u.pt_aouthdr.magic || + ahdr.tsize != u.pt_aouthdr.tsize || + ahdr.dsize != u.pt_aouthdr.dsize || + ahdr.entry != u.pt_aouthdr.entry) + { + fprintf(stderr, "Core file didn't come from this a.out\n"); + exit(1); + } + + printf("Data segment size was %u", ahdr.dsize); + ahdr.dsize = u.pt_dsize; + ahdr.bsize = 0; /* all data is inited now! */ + printf(" now is %u\n", ahdr.dsize); + + +/* + * point to top of old line#/symbol/string info if there is any so + * we can find it later... + */ + + sym_top = 0; + if (scns[0].s_nlnno != 0) + sym_top = scns[0].s_lnnoptr; + else if (fhdr.f_nsyms != 0) + sym_top = fhdr.f_symptr; + + scns[1].s_size = u.pt_dsize; + scns[2].s_size = 0; + scns[2].s_vaddr = 0; + scns[2].s_paddr = 0; + + cur_pos = scns[1].s_scnptr + scns[1].s_size; + + if (scns[0].s_nlnno != 0) { + scns[0].s_lnnoptr = cur_pos; + cur_pos += scns[0].s_nlnno * sizeof(struct lineno); + } + if (fhdr.f_nsyms != 0) { + fhdr.f_symptr = cur_pos; + } + + + + + if (fwrite(&fhdr, sizeof fhdr, 1, new) != 1) + { + perror("Couldn't write file header to new a.out file"); + exit(1); + } + if (fhdr.f_opthdr > 0) + { + if (fwrite(&ahdr, sizeof ahdr, 1, new) != 1) + { + perror("Couldn't write system file header to new a.out file"); + exit(1); + } + for(i=0;(i != nscns);i++) { + if (fwrite(&scns[i], sizeof(struct scnhdr), 1, new) != 1) { + perror("Couldn't write section headers to new a.out file"); + exit(1); + } + } + } + +} + +/* + * Copy the text from the a.out to the new a.out + */ +copy_text(new, a_out) +FILE *new, *a_out; +{ + char page[PSIZE]; + int txtcnt; + + txtcnt = ahdr.tsize; + + fseek(new, scns[0].s_scnptr, 0); + fseek(a_out, scns[0].s_scnptr, 0); + +/* if (hdr.a_magic == OMAGIC) + { + printf("a.out file is not shared text, getting text from core file\n"); + fseek(a_out, hdr.a_text, 1); * skip over text * + return; + } */ + + + while (txtcnt >= PSIZE) + { + if (fread(page, PSIZE, 1, a_out) != 1) + { + perror("Read failure on a.out text"); + exit(1); + } + if (fwrite(page, PSIZE, 1, new) != 1) + { + perror("Write failure in text segment"); + exit(1); + } + txtcnt -= PSIZE; + } + if (txtcnt) + { + if (fread(page, txtcnt, 1, a_out) != 1) + { + perror("Read failure on a.out text"); + exit(1); + } + if (fwrite(page, txtcnt, 1, new) != 1) + { + perror("Write failure in text segment"); + exit(1); + } + } +} + +/* + * copy the data from the core file to the new a.out + */ +copy_data(new, core) +FILE *new, *core; +{ + char page[PSIZE]; + int datacnt; + + + datacnt = u.pt_dsize; + +/* if (hdr.a_magic == OMAGIC) + datacnt += u.u_tsize; */ + fseek(core,(long) sizeof(struct ptrace_user), 0); + fseek(new, scns[1].s_scnptr, 0); + while (datacnt >= PSIZE) + { + if (fread(page, PSIZE, 1, core) != 1) + { + perror("Read failure on core data"); + exit(1); + } + if (fwrite(page, PSIZE, 1, new) != 1) + { + perror("Write failure in data segment"); + exit(1); + } + datacnt -= PSIZE; + } + if (datacnt) + { + if (fread(page, datacnt, 1, core) != 1) + { + perror("Read failure on core data"); + exit(1); + } + if (fwrite(page, datacnt, 1, new) != 1) + { + perror("Write failure in data segment"); + exit(1); + } + } +} + +/* + * Copy the relocation information and symbol table from the a.out to the new + */ +copy_sym(new, a_out) +FILE *new, *a_out; +{ + char page[PSIZE]; + int n; + + fseek(a_out, sym_top, 0); /* skip over data segment */ + while ((n = fread(page, 1, PSIZE, a_out)) > 0) + { + if (fwrite(page, 1, n, new) != n) + { + perror("Error writing symbol table to new a.out"); + fprintf(stderr, "new a.out should be ok otherwise\n"); + return; + } + } + if (n < 0) + { + perror("Error reading symbol table from a.out"); + fprintf(stderr, "new a.out should be ok otherwise\n"); + } +} + +/* + * After succesfully building the new a.out, mark it executable + */ +mark_x(name) +char *name; +{ + struct stat sbuf; + int um; + + um = umask(777); + umask(um); + if (stat(name, &sbuf) == -1) + { + perror ("Can't stat new a.out"); + fprintf(stderr, "Setting protection to %o\n", 0777 & ~um); + sbuf.st_mode = 0777; + } + sbuf.st_mode |= 0111 & ~um; + if (chmod(name, sbuf.st_mode) == -1) + perror("Couldn't change mode of new a.out to executable"); + +} + diff --git a/obsolete/support/undump/Encore/unexec.c b/obsolete/support/undump/Encore/unexec.c new file mode 100644 index 0000000000..a4ced6bf69 --- /dev/null +++ b/obsolete/support/undump/Encore/unexec.c @@ -0,0 +1,1143 @@ +/* Copyright (C) 1985, 1986, 1987 Free Software Foundation, Inc. + + NO WARRANTY + + BECAUSE THIS PROGRAM IS LICENSED FREE OF CHARGE, WE PROVIDE ABSOLUTELY +NO WARRANTY, TO THE EXTENT PERMITTED BY APPLICABLE STATE LAW. EXCEPT +WHEN OTHERWISE STATED IN WRITING, FREE SOFTWARE FOUNDATION, INC, +RICHARD M. STALLMAN AND/OR OTHER PARTIES PROVIDE THIS PROGRAM "AS IS" +WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, +BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY +AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE +DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR +CORRECTION. + + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW WILL RICHARD M. +STALLMAN, THE FREE SOFTWARE FOUNDATION, INC., AND/OR ANY OTHER PARTY +WHO MAY MODIFY AND REDISTRIBUTE THIS PROGRAM AS PERMITTED BELOW, BE +LIABLE TO YOU FOR DAMAGES, INCLUDING ANY LOST PROFITS, LOST MONIES, OR +OTHER SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE +USE OR INABILITY TO USE (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR +DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY THIRD PARTIES OR +A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS) THIS +PROGRAM, EVEN IF YOU HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH +DAMAGES, OR FOR ANY CLAIM BY ANY OTHER PARTY. + + GENERAL PUBLIC LICENSE TO COPY + + 1. You may copy and distribute verbatim copies of this source file +as you receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy a valid copyright notice "Copyright +(C) 1987 Free Software Foundation, Inc."; and include following the +copyright notice a verbatim copy of the above disclaimer of warranty +and of this License. You may charge a distribution fee for the +physical act of transferring a copy. + + 2. You may modify your copy or copies of this source file or +any portion of it, and copy and distribute such modifications under +the terms of Paragraph 1 above, provided that you also do the following: + + a) cause the modified files to carry prominent notices stating + that you changed the files and the date of any change; and + + b) cause the whole of any work that you distribute or publish, + that in whole or in part contains or is a derivative of this + program or any part thereof, to be licensed at no charge to all + third parties on terms identical to those contained in this + License Agreement (except that you may choose to grant more + extensive warranty protection to third parties, at your option). + + c) You may charge a distribution fee for the physical act of + transferring a copy, and you may at your option offer warranty + protection in exchange for a fee. + + 3. You may copy and distribute this program or any portion of it in +compiled, executable or object code form under the terms of Paragraphs +1 and 2 above provided that you do the following: + + a) cause each such copy to be accompanied by the + corresponding machine-readable source code, which must + be distributed under the terms of Paragraphs 1 and 2 above; or, + + b) cause each such copy to be accompanied by a + written offer, with no time limit, to give any third party + free (except for a nominal shipping charge) a machine readable + copy of the corresponding source code, to be distributed + under the terms of Paragraphs 1 and 2 above; or, + + c) in the case of a recipient of this program in compiled, executable + or object code form (without the corresponding source code) you + shall cause copies you distribute to be accompanied by a copy + of the written offer of source code which you received along + with the copy you received. + + 4. You may not copy, sublicense, distribute or transfer this program +except as expressly provided under this License Agreement. Any attempt +otherwise to copy, sublicense, distribute or transfer this program is void and +your rights to use the program under this License agreement shall be +automatically terminated. However, parties who have received computer +software programs from you with this License Agreement will not have +their licenses terminated so long as such parties remain in full compliance. + + 5. If you wish to incorporate parts of this program into other free +programs whose distribution conditions are different, write to the Free +Software Foundation at 675 Mass Ave, Cambridge, MA 02139. We have not yet +worked out a simple rule that can be stated here, but we will often permit +this. We will be guided by the two goals of preserving the free status of +all derivatives of our free software and of promoting the sharing and reuse of +software. + + +In other words, you are welcome to use, share and improve this program. +You are forbidden to forbid anyone else to use, share and improve +what you give them. Help stamp out software-hoarding! */ + + +/* + * unexec.c - Convert a running program into an a.out file. + * + * Author: Spencer W. Thomas + * Computer Science Dept. + * University of Utah + * Date: Tue Mar 2 1982 + * Modified heavily since then. + * + * Synopsis: + * unexec (new_name, a_name, data_start, bss_start, entry_address) + * char *new_name, *a_name; + * unsigned data_start, bss_start, entry_address; + * + * Takes a snapshot of the program and makes an a.out format file in the + * file named by the string argument new_name. + * If a_name is non-NULL, the symbol table will be taken from the given file. + * On some machines, an existing a_name file is required. + * + * The boundaries within the a.out file may be adjusted with the data_start + * and bss_start arguments. Either or both may be given as 0 for defaults. + * + * Data_start gives the boundary between the text segment and the data + * segment of the program. The text segment can contain shared, read-only + * program code and literal data, while the data segment is always unshared + * and unprotected. Data_start gives the lowest unprotected address. + * The value you specify may be rounded down to a suitable boundary + * as required by the machine you are using. + * + * Specifying zero for data_start means the boundary between text and data + * should not be the same as when the program was loaded. + * If NO_REMAP is defined, the argument data_start is ignored and the + * segment boundaries are never changed. + * + * Bss_start indicates how much of the data segment is to be saved in the + * a.out file and restored when the program is executed. It gives the lowest + * unsaved address, and is rounded up to a page boundary. The default when 0 + * is given assumes that the entire data segment is to be stored, including + * the previous data and bss as well as any additional storage allocated with + * break (2). + * + * The new file is set up to start at entry_address. + * + * If you make improvements I'd like to get them too. + * harpo!utah-cs!thomas, thomas@Utah-20 + * + */ + +/* There are several compilation parameters affecting unexec: + +* COFF + +Define this if your system uses COFF for executables. +Otherwise we assume you use Berkeley format. + +* NO_REMAP + +Define this if you do not want to try to save Emacs's pure data areas +as part of the text segment. + +Saving them as text is good because it allows users to share more. + +However, on machines that locate the text area far from the data area, +the boundary cannot feasibly be moved. Such machines require +NO_REMAP. + +Also, remapping can cause trouble with the built-in startup routine +/lib/crt0.o, which defines `environ' as an initialized variable. +Dumping `environ' as pure does not work! So, to use remapping, +you must write a startup routine for your machine in Emacs's crt0.c. +If NO_REMAP is defined, Emacs uses the system's crt0.o. + +* SECTION_ALIGNMENT + +Some machines that use COFF executables require that each section +start on a certain boundary *in the COFF file*. Such machines should +define SECTION_ALIGNMENT to a mask of the low-order bits that must be +zero on such a boundary. This mask is used to control padding between +segments in the COFF file. + +If SECTION_ALIGNMENT is not defined, the segments are written +consecutively with no attempt at alignment. This is right for +unmodified system V. + +* SEGMENT_MASK + +Some machines require that the beginnings and ends of segments +*in core* be on certain boundaries. For most machines, a page +boundary is sufficient. That is the default. When a larger +boundary is needed, define SEGMENT_MASK to a mask of +the bits that must be zero on such a boundary. + +* A_TEXT_OFFSET(HDR) + +Some machines count the a.out header as part of the size of the text +segment (a_text); they may actually load the header into core as the +first data in the text segment. Some have additional padding between +the header and the real text of the program that is counted in a_text. + +For these machines, define A_TEXT_OFFSET(HDR) to examine the header +structure HDR and return the number of bytes to add to `a_text' +before writing it (above and beyond the number of bytes of actual +program text). HDR's standard fields are already correct, except that +this adjustment to the `a_text' field has not yet been made; +thus, the amount of offset can depend on the data in the file. + +* A_TEXT_SEEK(HDR) + +If defined, this macro specifies the number of bytes to seek into the +a.out file before starting to write the text segment.a + +* EXEC_MAGIC + +For machines using COFF, this macro, if defined, is a value stored +into the magic number field of the output file. + +* ADJUST_EXEC_HEADER + +This macro can be used to generate statements to adjust or +initialize nonstandard fields in the file header + +* ADDR_CORRECT(ADDR) + +Macro to correct an int which is the bit pattern of a pointer to a byte +into an int which is the number of a byte. + +This macro has a default definition which is usually right. +This default definition is a no-op on most machines (where a +pointer looks like an int) but not on all machines. + +*/ + +#ifndef emacs +#define PERROR(arg) perror (arg); return -1 +#else +#include "config.h" +#define PERROR(file) report_error (file, new) +#endif + +#ifndef CANNOT_DUMP /* all rest of file! */ + +#ifndef CANNOT_UNEXEC /* most of rest of file */ + +#ifndef mips /* mips machine requires completely separate code. */ + +#include <a.out.h> +/* Define getpagesize () if the system does not. + Note that this may depend on symbols defined in a.out.h + */ +#include "getpagesize.h" + +#ifndef makedev /* Try to detect types.h already loaded */ +#include <sys/types.h> +#endif +#include <stdio.h> +#include <sys/stat.h> +#include <errno.h> + +extern char *start_of_text (); /* Start of text */ +extern char *start_of_data (); /* Start of initialized data */ + +#ifdef COFF +#ifndef USG +#ifndef STRIDE +#ifndef UMAX +/* I have a suspicion that these are turned off on all systems + and can be deleted. Try it in version 19. */ +#include <filehdr.h> +#include <aouthdr.h> +#include <scnhdr.h> +#include <syms.h> +#endif /* not UMAX */ +#endif /* Not STRIDE */ +#endif /* not USG */ +static long block_copy_start; /* Old executable start point */ +static struct filehdr f_hdr; /* File header */ +static struct aouthdr f_ohdr; /* Optional file header (a.out) */ +long bias; /* Bias to add for growth */ +long lnnoptr; /* Pointer to line-number info within file */ +#define SYMS_START block_copy_start + +static long text_scnptr; +static long data_scnptr; + +#else /* not COFF */ + +extern char *sbrk (); + +#define SYMS_START ((long) N_SYMOFF (ohdr)) + +#ifdef HPUX +#ifdef HP9000S200_ID +#define MY_ID HP9000S200_ID +#else +#include <model.h> +#define MY_ID MYSYS +#endif /* no HP9000S200_ID */ +static MAGIC OLDMAGIC = {MY_ID, SHARE_MAGIC}; +static MAGIC NEWMAGIC = {MY_ID, DEMAND_MAGIC}; +#define N_TXTOFF(x) TEXT_OFFSET(x) +#define N_SYMOFF(x) LESYM_OFFSET(x) +static struct exec hdr, ohdr; + +#else /* not HPUX */ + +#if defined (USG) && !defined (IRIS) +static struct bhdr hdr, ohdr; +#define a_magic fmagic +#define a_text tsize +#define a_data dsize +#define a_bss bsize +#define a_syms ssize +#define a_trsize rtsize +#define a_drsize rdsize +#define a_entry entry +#define N_BADMAG(x) \ + (((x).fmagic)!=OMAGIC && ((x).fmagic)!=NMAGIC &&\ + ((x).fmagic)!=FMAGIC && ((x).fmagic)!=IMAGIC) +#define NEWMAGIC FMAGIC +#else /* IRIS or not USG */ +static struct exec hdr, ohdr; +#define NEWMAGIC ZMAGIC +#endif /* IRIS or not USG */ +#endif /* not HPUX */ + +static int unexec_text_start; +static int unexec_data_start; + +#endif /* not COFF */ + +static int pagemask; + +/* Correct an int which is the bit pattern of a pointer to a byte + into an int which is the number of a byte. + This is a no-op on ordinary machines, but not on all. */ + +#ifndef ADDR_CORRECT /* Let m-*.h files override this definition */ +#define ADDR_CORRECT(x) ((char *)(x) - (char*)0) +#endif + +#ifdef emacs + +static +report_error (file, fd) + char *file; + int fd; +{ + if (fd) + close (fd); + error ("Failure operating on %s", file); +} +#endif /* emacs */ + +#define ERROR0(msg) report_error_1 (new, msg, 0, 0); return -1 +#define ERROR1(msg,x) report_error_1 (new, msg, x, 0); return -1 +#define ERROR2(msg,x,y) report_error_1 (new, msg, x, y); return -1 + +static +report_error_1 (fd, msg, a1, a2) + int fd; + char *msg; + int a1, a2; +{ + close (fd); +#ifdef emacs + error (msg, a1, a2); +#else + fprintf (stderr, msg, a1, a2); + fprintf (stderr, "\n"); +#endif +} + +/* **************************************************************** + * unexec + * + * driving logic. + */ +unexec (new_name, a_name, data_start, bss_start, entry_address) + char *new_name, *a_name; + unsigned data_start, bss_start, entry_address; +{ + int new, a_out = -1; + + if (a_name && (a_out = open (a_name, 0)) < 0) + { + PERROR (a_name); + } + if ((new = creat (new_name, 0666)) < 0) + { + PERROR (new_name); + } + + if (make_hdr (new, a_out, data_start, bss_start, entry_address, a_name, new_name) < 0 + || copy_text_and_data (new) < 0 + || copy_sym (new, a_out, a_name, new_name) < 0 +#ifdef COFF + || adjust_lnnoptrs (new, a_out, new_name) < 0 +#endif + ) + { + close (new); + /* unlink (new_name); /* Failed, unlink new a.out */ + return -1; + } + + close (new); + if (a_out >= 0) + close (a_out); + mark_x (new_name); + return 0; +} + +/* **************************************************************** + * make_hdr + * + * Make the header in the new a.out from the header in core. + * Modify the text and data sizes. + */ +static int +make_hdr (new, a_out, data_start, bss_start, entry_address, a_name, new_name) + int new, a_out; + unsigned data_start, bss_start, entry_address; + char *a_name; + char *new_name; +{ + int tem; +#ifdef COFF + auto struct scnhdr f_thdr; /* Text section header */ + auto struct scnhdr f_dhdr; /* Data section header */ + auto struct scnhdr f_bhdr; /* Bss section header */ + auto struct scnhdr scntemp; /* Temporary section header */ + register int scns; +#endif /* COFF */ + unsigned int bss_end; +#ifdef UMAX + extern etext; +#endif + + pagemask = getpagesize () - 1; + + /* Adjust text/data boundary. */ +#ifdef NO_REMAP + data_start = (int) start_of_data (); +#else /* not NO_REMAP */ +#ifndef UMAX + if (!data_start) +#endif + data_start = (int) start_of_data (); +#endif /* not NO_REMAP */ + data_start = ADDR_CORRECT (data_start); + +#ifdef SEGMENT_MASK + data_start = data_start & ~SEGMENT_MASK; /* (Down) to segment boundary. */ +#else + data_start = data_start & ~pagemask; /* (Down) to page boundary. */ +#endif + + bss_end = ADDR_CORRECT (sbrk (0)) + pagemask; + bss_end &= ~ pagemask; + + /* Adjust data/bss boundary. */ + if (bss_start != 0) + { + bss_start = (ADDR_CORRECT (bss_start) + pagemask); + /* (Up) to page bdry. */ + bss_start &= ~ pagemask; + if (bss_start > bss_end) + { + ERROR1 ("unexec: Specified bss_start (%u) is past end of program", + bss_start); + } + } + else + bss_start = bss_end; + + if (data_start > bss_start) /* Can't have negative data size. */ + { + ERROR2 ("unexec: data_start (%u) can't be greater than bss_start (%u)", + data_start, bss_start); + } + +#ifdef COFF + /* Salvage as much info from the existing file as possible */ + if (a_out >= 0) + { + if (read (a_out, &f_hdr, sizeof (f_hdr)) != sizeof (f_hdr)) + { + PERROR (a_name); + } + block_copy_start += sizeof (f_hdr); + if (f_hdr.f_opthdr > 0) + { + if (read (a_out, &f_ohdr, sizeof (f_ohdr)) != sizeof (f_ohdr)) + { + PERROR (a_name); + } + block_copy_start += sizeof (f_ohdr); + } + /* Loop through section headers, copying them in */ + for (scns = f_hdr.f_nscns; scns > 0; scns--) { + if (read (a_out, &scntemp, sizeof (scntemp)) != sizeof (scntemp)) + { + PERROR (a_name); + } + if (scntemp.s_scnptr > 0L) + { + if (block_copy_start < scntemp.s_scnptr + scntemp.s_size) + block_copy_start = scntemp.s_scnptr + scntemp.s_size; + } + if (strcmp (scntemp.s_name, ".text") == 0) + { + f_thdr = scntemp; + } + else if (strcmp (scntemp.s_name, ".data") == 0) + { + f_dhdr = scntemp; + } + else if (strcmp (scntemp.s_name, ".bss") == 0) + { + f_bhdr = scntemp; + } + } + } + else + { + ERROR0 ("can't build a COFF file from scratch yet"); + } + + /* Now we alter the contents of all the f_*hdr variables + to correspond to what we want to dump. */ + + f_hdr.f_flags |= (F_RELFLG | F_EXEC); +#ifdef EXEC_MAGIC + f_ohdr.magic = EXEC_MAGIC; +#endif +#ifndef NO_REMAP + f_ohdr.text_start = (long) start_of_text (); +#ifdef UMAX + f_ohdr.tsize = (long) &etext; +#else + f_ohdr.tsize = data_start - f_ohdr.text_start; +#endif + f_ohdr.data_start = data_start; +#endif /* NO_REMAP */ + f_ohdr.dsize = bss_start - f_ohdr.data_start; + f_ohdr.bsize = bss_end - bss_start; + f_thdr.s_size = f_ohdr.tsize; + f_thdr.s_scnptr = sizeof (f_hdr) + sizeof (f_ohdr); + f_thdr.s_scnptr += (f_hdr.f_nscns) * (sizeof (f_thdr)); + lnnoptr = f_thdr.s_lnnoptr; +#ifdef SECTION_ALIGNMENT + /* Some systems require special alignment + of the sections in the file itself. */ + f_thdr.s_scnptr + = (f_thdr.s_scnptr + SECTION_ALIGNMENT) & ~SECTION_ALIGNMENT; +#endif /* SECTION_ALIGNMENT */ + text_scnptr = f_thdr.s_scnptr; + f_dhdr.s_paddr = f_ohdr.data_start; + f_dhdr.s_vaddr = f_ohdr.data_start; + f_dhdr.s_size = f_ohdr.dsize; + f_dhdr.s_scnptr = f_thdr.s_scnptr + f_thdr.s_size; +#ifdef SECTION_ALIGNMENT + /* Some systems require special alignment + of the sections in the file itself. */ + f_dhdr.s_scnptr + = (f_dhdr.s_scnptr + SECTION_ALIGNMENT) & ~SECTION_ALIGNMENT; +#endif /* SECTION_ALIGNMENT */ + data_scnptr = f_dhdr.s_scnptr; + f_bhdr.s_paddr = f_ohdr.data_start + f_ohdr.dsize; + f_bhdr.s_vaddr = f_ohdr.data_start + f_ohdr.dsize; + f_bhdr.s_size = f_ohdr.bsize; + f_bhdr.s_scnptr = 0L; + bias = f_dhdr.s_scnptr + f_dhdr.s_size - block_copy_start; + + if (f_hdr.f_symptr > 0L) + { + f_hdr.f_symptr += bias; + } + + if (f_thdr.s_lnnoptr > 0L) + { + f_thdr.s_lnnoptr += bias; + } + +#ifdef ADJUST_EXEC_HEADER + ADJUST_EXEC_HEADER +#endif /* ADJUST_EXEC_HEADER */ + + if (write (new, &f_hdr, sizeof (f_hdr)) != sizeof (f_hdr)) + { + PERROR (new_name); + } + + if (write (new, &f_ohdr, sizeof (f_ohdr)) != sizeof (f_ohdr)) + { + PERROR (new_name); + } + + if (write (new, &f_thdr, sizeof (f_thdr)) != sizeof (f_thdr)) + { + PERROR (new_name); + } + + if (write (new, &f_dhdr, sizeof (f_dhdr)) != sizeof (f_dhdr)) + { + PERROR (new_name); + } + + if (write (new, &f_bhdr, sizeof (f_bhdr)) != sizeof (f_bhdr)) + { + PERROR (new_name); + } + return (0); + +#else /* if not COFF */ + + /* Get symbol table info from header of a.out file if given one. */ + if (a_out >= 0) + { + if (read (a_out, &ohdr, sizeof hdr) != sizeof hdr) + { + PERROR (a_name); + } + + if N_BADMAG (ohdr) + { + ERROR1 ("invalid magic number in %s", a_name); + } + hdr = ohdr; + } + else + { + bzero (hdr, sizeof hdr); + } + + unexec_text_start = (long) start_of_text (); + unexec_data_start = data_start; + + /* Machine-dependent fixup for header, or maybe for unexec_text_start */ +#ifdef ADJUST_EXEC_HEADER + ADJUST_EXEC_HEADER; +#endif /* ADJUST_EXEC_HEADER */ + + hdr.a_trsize = 0; + hdr.a_drsize = 0; + if (entry_address != 0) + hdr.a_entry = entry_address; + + hdr.a_bss = bss_end - bss_start; + hdr.a_data = bss_start - data_start; +#ifdef NO_REMAP + hdr.a_text = ohdr.a_text; +#else /* not NO_REMAP */ + hdr.a_text = data_start - unexec_text_start; +#endif /* not NO_REMAP */ + +#ifdef A_TEXT_OFFSET + hdr.a_text += A_TEXT_OFFSET (ohdr); +#endif + + if (write (new, &hdr, sizeof hdr) != sizeof hdr) + { + PERROR (new_name); + } + +#ifdef A_TEXT_OFFSET + hdr.a_text -= A_TEXT_OFFSET (ohdr); +#endif + + return 0; + +#endif /* not COFF */ +} + +/* **************************************************************** + * copy_text_and_data + * + * Copy the text and data segments from memory to the new a.out + */ +static int +copy_text_and_data (new) + int new; +{ + register char *end; + register char *ptr; + +#ifdef COFF + lseek (new, (long) text_scnptr, 0); + ptr = (char *) f_ohdr.text_start; + end = ptr + f_ohdr.tsize; + write_segment (new, ptr, end); + + lseek (new, (long) data_scnptr, 0); + ptr = (char *) f_ohdr.data_start; + end = ptr + f_ohdr.dsize; + write_segment (new, ptr, end); + +#else /* if not COFF */ + +/* Some machines count the header as part of the text segment. + That is to say, the header appears in core + just before the address that start_of_text () returns. + For them, N_TXTOFF is the place where the header goes. + We must adjust the seek to the place after the header. + Note that at this point hdr.a_text does *not* count + the extra A_TEXT_OFFSET bytes, only the actual bytes of code. */ + +#ifdef A_TEXT_SEEK + lseek (new, (long) A_TEXT_SEEK (hdr), 0); +#else +#ifdef A_TEXT_OFFSET + /* Note that on the Sequent machine A_TEXT_OFFSET != sizeof (hdr) + and sizeof (hdr) is the correct amount to add here. */ + /* In version 19, eliminate this case and use A_TEXT_SEEK whenever + N_TXTOFF is not right. */ + lseek (new, (long) N_TXTOFF (hdr) + sizeof (hdr), 0); +#else + lseek (new, (long) N_TXTOFF (hdr), 0); +#endif /* no A_TEXT_OFFSET */ +#endif /* no A_TEXT_SEEK */ + + ptr = (char *) unexec_text_start; + end = ptr + hdr.a_text; + write_segment (new, ptr, end); + + ptr = (char *) unexec_data_start; + end = ptr + hdr.a_data; +/* This lseek is certainly incorrect when A_TEXT_OFFSET + and I believe it is a no-op otherwise. + Let's see if its absence ever fails. */ +/* lseek (new, (long) N_TXTOFF (hdr) + hdr.a_text, 0); */ + write_segment (new, ptr, end); + +#endif /* not COFF */ + + return 0; +} + +write_segment (new, ptr, end) + int new; + register char *ptr, *end; +{ + register int i, nwrite, ret; + char buf[80]; + extern int errno; + char zeros[128]; + + bzero (zeros, sizeof zeros); + + for (i = 0; ptr < end;) + { + /* distance to next multiple of 128. */ + nwrite = (((int) ptr + 128) & -128) - (int) ptr; + /* But not beyond specified end. */ + if (nwrite > end - ptr) nwrite = end - ptr; + ret = write (new, ptr, nwrite); + /* If write gets a page fault, it means we reached + a gap between the old text segment and the old data segment. + This gap has probably been remapped into part of the text segment. + So write zeros for it. */ + if (ret == -1 && errno == EFAULT) + write (new, zeros, nwrite); + else if (nwrite != ret) + { + sprintf (buf, + "unexec write failure: addr 0x%x, fileno %d, size 0x%x, wrote 0x%x, errno %d", + ptr, new, nwrite, ret, errno); + PERROR (buf); + } + i += nwrite; + ptr += nwrite; + } +} + +/* **************************************************************** + * copy_sym + * + * Copy the relocation information and symbol table from the a.out to the new + */ +static int +copy_sym (new, a_out, a_name, new_name) + int new, a_out; + char *a_name, *new_name; +{ + char page[1024]; + int n; + + if (a_out < 0) + return 0; + +#ifdef COFF + if (SYMS_START == 0L) + return 0; +#endif /* COFF */ + +#ifdef COFF + if (lnnoptr) /* if there is line number info */ + lseek (a_out, lnnoptr, 0); /* start copying from there */ + else +#endif /* COFF */ + lseek (a_out, SYMS_START, 0); /* Position a.out to symtab. */ + + while ((n = read (a_out, page, sizeof page)) > 0) + { + if (write (new, page, n) != n) + { + PERROR (new_name); + } + } + if (n < 0) + { + PERROR (a_name); + } + return 0; +} + +/* **************************************************************** + * mark_x + * + * After succesfully building the new a.out, mark it executable + */ +static +mark_x (name) + char *name; +{ + struct stat sbuf; + int um; + int new = 0; /* for PERROR */ + + um = umask (777); + umask (um); + if (stat (name, &sbuf) == -1) + { + PERROR (name); + } + sbuf.st_mode |= 0111 & ~um; + if (chmod (name, sbuf.st_mode) == -1) + PERROR (name); +} + +/* + * If the COFF file contains a symbol table and a line number section, + * then any auxiliary entries that have values for x_lnnoptr must + * be adjusted by the amount that the line number section has moved + * in the file (bias computed in make_hdr). The #@$%&* designers of + * the auxiliary entry structures used the absolute file offsets for + * the line number entry rather than an offset from the start of the + * line number section! + * + * When I figure out how to scan through the symbol table and pick out + * the auxiliary entries that need adjustment, this routine will + * be fixed. As it is now, all such entries are wrong and sdb + * will complain. Fred Fish, UniSoft Systems Inc. + */ + +#ifdef COFF + +/* This function is probably very slow. Instead of reopening the new + file for input and output it should copy from the old to the new + using the two descriptors already open (WRITEDESC and READDESC). + Instead of reading one small structure at a time it should use + a reasonable size buffer. But I don't have time to work on such + things, so I am installing it as submitted to me. -- RMS. */ + +adjust_lnnoptrs (writedesc, readdesc, new_name) + int writedesc; + int readdesc; + char *new_name; +{ + register int nsyms; + register int new; +#ifdef amdahl_uts + SYMENT symentry; + AUXENT auxentry; +#else + struct syment symentry; + struct auxent auxentry; +#endif + + if (!lnnoptr || !f_hdr.f_symptr) + return 0; + + if ((new = open (new_name, 2)) < 0) + { + PERROR (new_name); + return -1; + } + + lseek (new, f_hdr.f_symptr, 0); + for (nsyms = 0; nsyms < f_hdr.f_nsyms; nsyms++) + { + read (new, &symentry, SYMESZ); + if (symentry.n_numaux) + { + read (new, &auxentry, AUXESZ); + nsyms++; + if (ISFCN (symentry.n_type)) { + auxentry.x_sym.x_fcnary.x_fcn.x_lnnoptr += bias; + lseek (new, -AUXESZ, 1); + write (new, &auxentry, AUXESZ); + } + } + } + close (new); +} + +#endif /* COFF */ + + +#else /* mips */ + +/* Unexec for mips machines. + Note that I regard it as the responsibility of people at Mips + to tell me about any changes that need to be made in this code. + I won't take responsibility to think about it even if a change + I make elsewhere causes it to break. -- RMS. */ + +#include <sys/types.h> +#include <sys/file.h> +#include <sys/stat.h> +#include <stdio.h> +#include <varargs.h> +#include <filehdr.h> +#include <aouthdr.h> +#include <scnhdr.h> +#include <sym.h> + +#define private static + +extern int errno; +extern int sys_nerr; +extern char *sys_errlist[]; +#define EEOF -1 + +private void +fatal(s, va_alist) + va_dcl +{ + va_list ap; + if (errno == EEOF) { + fputs("unexec: unexpected end of file, ", stderr); + } + else if (errno < sys_nerr) { + fprintf(stderr, "unexec: %s, ", sys_errlist[errno]); + } + else { + fprintf(stderr, "unexec: error code %d, ", errno); + } + va_start(ap); + _doprnt(s, ap, stderr); + fputs(".\n", stderr); + exit(1); +} + +#define READ(_fd, _buffer, _size, _error_message, _error_arg) \ + errno = EEOF; \ + if (read(_fd, _buffer, _size) != _size) \ + fatal(_error_message, _error_arg); + +#define WRITE(_fd, _buffer, _size, _error_message, _error_arg) \ + if (write(_fd, _buffer, _size) != _size) \ + fatal(_error_message, _error_arg); + +#define SEEK(_fd, _position, _error_message, _error_arg) \ + errno = EEOF; \ + if (lseek(_fd, _position, L_SET) != _position) \ + fatal(_error_message, _error_arg); + +struct headers { + struct filehdr fhdr; + struct aouthdr aout; + struct scnhdr text_section; + struct scnhdr rdata_section; + struct scnhdr data_section; + struct scnhdr sdata_section; + struct scnhdr sbss_section; + struct scnhdr bss_section; +}; + +unexec (new_name, a_name, data_start, bss_start, entry_address) + char *new_name, *a_name; + unsigned data_start, bss_start, entry_address; +{ + int new, old; + int pagesize, brk; + int newsyms, symrel; + int nread; + struct headers hdr; +#define BUFSIZE 8192 + char buffer[BUFSIZE]; + + old = open (a_name, O_RDONLY, 0); + if (old < 0) fatal("openning %s", a_name); + + new = creat (new_name, 0666); + if (new < 0) fatal("creating %s", new_name); + + hdr = *((struct headers *)TEXT_START); + if (hdr.fhdr.f_magic != MIPSELMAGIC + && hdr.fhdr.f_magic != MIPSEBMAGIC) { + fprintf(stderr, "unexec: input file magic number is %x, not %x or %x.\n", + hdr.fhdr.f_magic, MIPSELMAGIC, MIPSEBMAGIC); + exit(1); + } + if (hdr.fhdr.f_opthdr != sizeof(hdr.aout)) { + fprintf(stderr, "unexec: input a.out header is %d bytes, not %d.\n", + hdr.fhdr.f_opthdr, sizeof(hdr.aout)); + exit(1); + } +#if 0 + if (hdr.aout.magic != ZMAGIC + && hdr.aout.magic != NMAGIC + && hdr.aout.magic != OMAGIC) { + fprintf(stderr, "unexec: input file a.out magic number is %o, not %o, %o, or %o.\n", + hdr.aout.magic, ZMAGIC, NMAGIC, OMAGIC); + exit(1); + } +#else + if (hdr.aout.magic != ZMAGIC) { + fprintf(stderr, "unexec: input file a.out magic number is %o, not %o.\n", + hdr.aout.magic, ZMAGIC); + exit(1); + } +#endif + if (hdr.fhdr.f_nscns != 6) { + fprintf(stderr, "unexec: %d sections instead of 6.\n", hdr.fhdr.f_nscns); + } +#define CHECK_SCNHDR(field, name, flags) \ + if (strcmp(hdr.field.s_name, name) != 0) { \ + fprintf(stderr, "unexec: %s section where %s expected.\n", \ + hdr.field.s_name, name); \ + exit(1); \ + } \ + else if (hdr.field.s_flags != flags) { \ + fprintf(stderr, "unexec: %x flags where %x expected in %s section.\n", \ + hdr.field.s_flags, flags, name); \ + } + CHECK_SCNHDR(text_section, _TEXT, STYP_TEXT); + CHECK_SCNHDR(rdata_section, _RDATA, STYP_RDATA); + CHECK_SCNHDR(data_section, _DATA, STYP_DATA); + CHECK_SCNHDR(sdata_section, _SDATA, STYP_SDATA); + CHECK_SCNHDR(sbss_section, _SBSS, STYP_SBSS); + CHECK_SCNHDR(bss_section, _BSS, STYP_BSS); + + pagesize = getpagesize(); + brk = (sbrk(0) + pagesize - 1) & (-pagesize); + hdr.aout.dsize = brk - DATA_START; + hdr.aout.bsize = 0; + if (entry_address == 0) { + extern __start(); + hdr.aout.entry = (unsigned)__start; + } + else { + hdr.aout.entry = entry_address; + } + hdr.aout.bss_start = hdr.aout.data_start + hdr.aout.dsize; + hdr.rdata_section.s_size = data_start - DATA_START; + hdr.data_section.s_vaddr = data_start; + hdr.data_section.s_paddr = data_start; + hdr.data_section.s_size = brk - DATA_START; + hdr.data_section.s_scnptr = hdr.rdata_section.s_scnptr + + hdr.rdata_section.s_size; + hdr.sdata_section.s_vaddr = hdr.data_section.s_vaddr + + hdr.data_section.s_size; + hdr.sdata_section.s_paddr = hdr.sdata_section.s_paddr; + hdr.sdata_section.s_size = 0; + hdr.sdata_section.s_scnptr = hdr.data_section.s_scnptr + + hdr.data_section.s_size; + hdr.sbss_section.s_vaddr = hdr.sdata_section.s_vaddr + + hdr.sdata_section.s_size; + hdr.sbss_section.s_paddr = hdr.sbss_section.s_vaddr; + hdr.sbss_section.s_size = 0; + hdr.sbss_section.s_scnptr = hdr.sdata_section.s_scnptr + + hdr.sdata_section.s_size; + hdr.bss_section.s_vaddr = hdr.sbss_section.s_vaddr + + hdr.sbss_section.s_size; + hdr.bss_section.s_paddr = hdr.bss_section.s_vaddr; + hdr.bss_section.s_size = 0; + hdr.bss_section.s_scnptr = hdr.sbss_section.s_scnptr + + hdr.sbss_section.s_size; + + WRITE(new, TEXT_START, hdr.aout.tsize, + "writing text section to %s", new_name); + WRITE(new, DATA_START, hdr.aout.dsize, + "writing text section to %s", new_name); + + SEEK(old, hdr.fhdr.f_symptr, "seeking to start of symbols in %s", a_name); + errno = EEOF; + nread = read(old, buffer, BUFSIZE); + if (nread < sizeof(HDRR)) fatal("reading symbols from %s", a_name); +#define symhdr ((pHDRR)buffer) + newsyms = hdr.aout.tsize + hdr.aout.dsize; + symrel = newsyms - hdr.fhdr.f_symptr; + hdr.fhdr.f_symptr = newsyms; + symhdr->cbLineOffset += symrel; + symhdr->cbDnOffset += symrel; + symhdr->cbPdOffset += symrel; + symhdr->cbSymOffset += symrel; + symhdr->cbOptOffset += symrel; + symhdr->cbAuxOffset += symrel; + symhdr->cbSsOffset += symrel; + symhdr->cbSsExtOffset += symrel; + symhdr->cbFdOffset += symrel; + symhdr->cbRfdOffset += symrel; + symhdr->cbExtOffset += symrel; +#undef symhdr + do { + if (write(new, buffer, nread) != nread) + fatal("writing symbols to %s", new_name); + nread = read(old, buffer, BUFSIZE); + if (nread < 0) fatal("reading symbols from %s", a_name); +#undef BUFSIZE + } while (nread != 0); + + SEEK(new, 0, "seeking to start of header in %s", new_name); + WRITE(new, &hdr, sizeof(hdr), + "writing header of %s", new_name); + + close(old); + close(new); + mark_x(new_name); +} + +/* + * mark_x + * + * After succesfully building the new a.out, mark it executable + */ +static +mark_x (name) + char *name; +{ + struct stat sbuf; + int um = umask (777); + umask (um); + if (stat(name, &sbuf) < 0) + fatal("getting protection on %s", name); + sbuf.st_mode |= 0111 & ~um; + if (chmod(name, sbuf.st_mode) < 0) + fatal("setting protection on %s", name); +} + +#endif /* mips */ + +#endif /* not CANNOT_UNEXEC */ + +#endif /* not CANNOT_DUMP */ diff --git a/obsolete/support/undump/Encore/unexec.c-dist b/obsolete/support/undump/Encore/unexec.c-dist new file mode 100644 index 0000000000..9855e90485 --- /dev/null +++ b/obsolete/support/undump/Encore/unexec.c-dist @@ -0,0 +1,1134 @@ +/* Copyright (C) 1985, 1986, 1987 Free Software Foundation, Inc. + + NO WARRANTY + + BECAUSE THIS PROGRAM IS LICENSED FREE OF CHARGE, WE PROVIDE ABSOLUTELY +NO WARRANTY, TO THE EXTENT PERMITTED BY APPLICABLE STATE LAW. EXCEPT +WHEN OTHERWISE STATED IN WRITING, FREE SOFTWARE FOUNDATION, INC, +RICHARD M. STALLMAN AND/OR OTHER PARTIES PROVIDE THIS PROGRAM "AS IS" +WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, +BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY +AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE +DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR +CORRECTION. + + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW WILL RICHARD M. +STALLMAN, THE FREE SOFTWARE FOUNDATION, INC., AND/OR ANY OTHER PARTY +WHO MAY MODIFY AND REDISTRIBUTE THIS PROGRAM AS PERMITTED BELOW, BE +LIABLE TO YOU FOR DAMAGES, INCLUDING ANY LOST PROFITS, LOST MONIES, OR +OTHER SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE +USE OR INABILITY TO USE (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR +DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY THIRD PARTIES OR +A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS) THIS +PROGRAM, EVEN IF YOU HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH +DAMAGES, OR FOR ANY CLAIM BY ANY OTHER PARTY. + + GENERAL PUBLIC LICENSE TO COPY + + 1. You may copy and distribute verbatim copies of this source file +as you receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy a valid copyright notice "Copyright +(C) 1987 Free Software Foundation, Inc."; and include following the +copyright notice a verbatim copy of the above disclaimer of warranty +and of this License. You may charge a distribution fee for the +physical act of transferring a copy. + + 2. You may modify your copy or copies of this source file or +any portion of it, and copy and distribute such modifications under +the terms of Paragraph 1 above, provided that you also do the following: + + a) cause the modified files to carry prominent notices stating + that you changed the files and the date of any change; and + + b) cause the whole of any work that you distribute or publish, + that in whole or in part contains or is a derivative of this + program or any part thereof, to be licensed at no charge to all + third parties on terms identical to those contained in this + License Agreement (except that you may choose to grant more + extensive warranty protection to third parties, at your option). + + c) You may charge a distribution fee for the physical act of + transferring a copy, and you may at your option offer warranty + protection in exchange for a fee. + + 3. You may copy and distribute this program or any portion of it in +compiled, executable or object code form under the terms of Paragraphs +1 and 2 above provided that you do the following: + + a) cause each such copy to be accompanied by the + corresponding machine-readable source code, which must + be distributed under the terms of Paragraphs 1 and 2 above; or, + + b) cause each such copy to be accompanied by a + written offer, with no time limit, to give any third party + free (except for a nominal shipping charge) a machine readable + copy of the corresponding source code, to be distributed + under the terms of Paragraphs 1 and 2 above; or, + + c) in the case of a recipient of this program in compiled, executable + or object code form (without the corresponding source code) you + shall cause copies you distribute to be accompanied by a copy + of the written offer of source code which you received along + with the copy you received. + + 4. You may not copy, sublicense, distribute or transfer this program +except as expressly provided under this License Agreement. Any attempt +otherwise to copy, sublicense, distribute or transfer this program is void and +your rights to use the program under this License agreement shall be +automatically terminated. However, parties who have received computer +software programs from you with this License Agreement will not have +their licenses terminated so long as such parties remain in full compliance. + + 5. If you wish to incorporate parts of this program into other free +programs whose distribution conditions are different, write to the Free +Software Foundation at 675 Mass Ave, Cambridge, MA 02139. We have not yet +worked out a simple rule that can be stated here, but we will often permit +this. We will be guided by the two goals of preserving the free status of +all derivatives of our free software and of promoting the sharing and reuse of +software. + + +In other words, you are welcome to use, share and improve this program. +You are forbidden to forbid anyone else to use, share and improve +what you give them. Help stamp out software-hoarding! */ + + +/* + * unexec.c - Convert a running program into an a.out file. + * + * Author: Spencer W. Thomas + * Computer Science Dept. + * University of Utah + * Date: Tue Mar 2 1982 + * Modified heavily since then. + * + * Synopsis: + * unexec (new_name, a_name, data_start, bss_start, entry_address) + * char *new_name, *a_name; + * unsigned data_start, bss_start, entry_address; + * + * Takes a snapshot of the program and makes an a.out format file in the + * file named by the string argument new_name. + * If a_name is non-NULL, the symbol table will be taken from the given file. + * On some machines, an existing a_name file is required. + * + * The boundaries within the a.out file may be adjusted with the data_start + * and bss_start arguments. Either or both may be given as 0 for defaults. + * + * Data_start gives the boundary between the text segment and the data + * segment of the program. The text segment can contain shared, read-only + * program code and literal data, while the data segment is always unshared + * and unprotected. Data_start gives the lowest unprotected address. + * The value you specify may be rounded down to a suitable boundary + * as required by the machine you are using. + * + * Specifying zero for data_start means the boundary between text and data + * should not be the same as when the program was loaded. + * If NO_REMAP is defined, the argument data_start is ignored and the + * segment boundaries are never changed. + * + * Bss_start indicates how much of the data segment is to be saved in the + * a.out file and restored when the program is executed. It gives the lowest + * unsaved address, and is rounded up to a page boundary. The default when 0 + * is given assumes that the entire data segment is to be stored, including + * the previous data and bss as well as any additional storage allocated with + * break (2). + * + * The new file is set up to start at entry_address. + * + * If you make improvements I'd like to get them too. + * harpo!utah-cs!thomas, thomas@Utah-20 + * + */ + +/* There are several compilation parameters affecting unexec: + +* COFF + +Define this if your system uses COFF for executables. +Otherwise we assume you use Berkeley format. + +* NO_REMAP + +Define this if you do not want to try to save Emacs's pure data areas +as part of the text segment. + +Saving them as text is good because it allows users to share more. + +However, on machines that locate the text area far from the data area, +the boundary cannot feasibly be moved. Such machines require +NO_REMAP. + +Also, remapping can cause trouble with the built-in startup routine +/lib/crt0.o, which defines `environ' as an initialized variable. +Dumping `environ' as pure does not work! So, to use remapping, +you must write a startup routine for your machine in Emacs's crt0.c. +If NO_REMAP is defined, Emacs uses the system's crt0.o. + +* SECTION_ALIGNMENT + +Some machines that use COFF executables require that each section +start on a certain boundary *in the COFF file*. Such machines should +define SECTION_ALIGNMENT to a mask of the low-order bits that must be +zero on such a boundary. This mask is used to control padding between +segments in the COFF file. + +If SECTION_ALIGNMENT is not defined, the segments are written +consecutively with no attempt at alignment. This is right for +unmodified system V. + +* SEGMENT_MASK + +Some machines require that the beginnings and ends of segments +*in core* be on certain boundaries. For most machines, a page +boundary is sufficient. That is the default. When a larger +boundary is needed, define SEGMENT_MASK to a mask of +the bits that must be zero on such a boundary. + +* A_TEXT_OFFSET(HDR) + +Some machines count the a.out header as part of the size of the text +segment (a_text); they may actually load the header into core as the +first data in the text segment. Some have additional padding between +the header and the real text of the program that is counted in a_text. + +For these machines, define A_TEXT_OFFSET(HDR) to examine the header +structure HDR and return the number of bytes to add to `a_text' +before writing it (above and beyond the number of bytes of actual +program text). HDR's standard fields are already correct, except that +this adjustment to the `a_text' field has not yet been made; +thus, the amount of offset can depend on the data in the file. + +* A_TEXT_SEEK(HDR) + +If defined, this macro specifies the number of bytes to seek into the +a.out file before starting to write the text segment.a + +* EXEC_MAGIC + +For machines using COFF, this macro, if defined, is a value stored +into the magic number field of the output file. + +* ADJUST_EXEC_HEADER + +This macro can be used to generate statements to adjust or +initialize nonstandard fields in the file header + +* ADDR_CORRECT(ADDR) + +Macro to correct an int which is the bit pattern of a pointer to a byte +into an int which is the number of a byte. + +This macro has a default definition which is usually right. +This default definition is a no-op on most machines (where a +pointer looks like an int) but not on all machines. + +*/ + +#ifndef emacs +#define PERROR(arg) perror (arg); return -1 +#else +#include "config.h" +#define PERROR(file) report_error (file, new) +#endif + +#ifndef CANNOT_DUMP /* all rest of file! */ + +#ifndef CANNOT_UNEXEC /* most of rest of file */ + +#ifndef mips /* mips machine requires completely separate code. */ + +#include <a.out.h> +/* Define getpagesize () if the system does not. + Note that this may depend on symbols defined in a.out.h + */ +#include "getpagesize.h" + +#ifndef makedev /* Try to detect types.h already loaded */ +#include <sys/types.h> +#endif +#include <stdio.h> +#include <sys/stat.h> +#include <errno.h> + +extern char *start_of_text (); /* Start of text */ +extern char *start_of_data (); /* Start of initialized data */ + +#ifdef COFF +#ifndef USG +#ifndef STRIDE +#ifndef UMAX +/* I have a suspicion that these are turned off on all systems + and can be deleted. Try it in version 19. */ +#include <filehdr.h> +#include <aouthdr.h> +#include <scnhdr.h> +#include <syms.h> +#endif /* not UMAX */ +#endif /* Not STRIDE */ +#endif /* not USG */ +static long block_copy_start; /* Old executable start point */ +static struct filehdr f_hdr; /* File header */ +static struct aouthdr f_ohdr; /* Optional file header (a.out) */ +long bias; /* Bias to add for growth */ +long lnnoptr; /* Pointer to line-number info within file */ +#define SYMS_START block_copy_start + +static long text_scnptr; +static long data_scnptr; + +#else /* not COFF */ + +extern char *sbrk (); + +#define SYMS_START ((long) N_SYMOFF (ohdr)) + +#ifdef HPUX +#ifdef HP9000S200_ID +#define MY_ID HP9000S200_ID +#else +#include <model.h> +#define MY_ID MYSYS +#endif /* no HP9000S200_ID */ +static MAGIC OLDMAGIC = {MY_ID, SHARE_MAGIC}; +static MAGIC NEWMAGIC = {MY_ID, DEMAND_MAGIC}; +#define N_TXTOFF(x) TEXT_OFFSET(x) +#define N_SYMOFF(x) LESYM_OFFSET(x) +static struct exec hdr, ohdr; + +#else /* not HPUX */ + +#if defined (USG) && !defined (IRIS) +static struct bhdr hdr, ohdr; +#define a_magic fmagic +#define a_text tsize +#define a_data dsize +#define a_bss bsize +#define a_syms ssize +#define a_trsize rtsize +#define a_drsize rdsize +#define a_entry entry +#define N_BADMAG(x) \ + (((x).fmagic)!=OMAGIC && ((x).fmagic)!=NMAGIC &&\ + ((x).fmagic)!=FMAGIC && ((x).fmagic)!=IMAGIC) +#define NEWMAGIC FMAGIC +#else /* IRIS or not USG */ +static struct exec hdr, ohdr; +#define NEWMAGIC ZMAGIC +#endif /* IRIS or not USG */ +#endif /* not HPUX */ + +static int unexec_text_start; +static int unexec_data_start; + +#endif /* not COFF */ + +static int pagemask; + +/* Correct an int which is the bit pattern of a pointer to a byte + into an int which is the number of a byte. + This is a no-op on ordinary machines, but not on all. */ + +#ifndef ADDR_CORRECT /* Let m-*.h files override this definition */ +#define ADDR_CORRECT(x) ((char *)(x) - (char*)0) +#endif + +#ifdef emacs + +static +report_error (file, fd) + char *file; + int fd; +{ + if (fd) + close (fd); + error ("Failure operating on %s", file); +} +#endif /* emacs */ + +#define ERROR0(msg) report_error_1 (new, msg, 0, 0); return -1 +#define ERROR1(msg,x) report_error_1 (new, msg, x, 0); return -1 +#define ERROR2(msg,x,y) report_error_1 (new, msg, x, y); return -1 + +static +report_error_1 (fd, msg, a1, a2) + int fd; + char *msg; + int a1, a2; +{ + close (fd); +#ifdef emacs + error (msg, a1, a2); +#else + fprintf (stderr, msg, a1, a2); + fprintf (stderr, "\n"); +#endif +} + +/* **************************************************************** + * unexec + * + * driving logic. + */ +unexec (new_name, a_name, data_start, bss_start, entry_address) + char *new_name, *a_name; + unsigned data_start, bss_start, entry_address; +{ + int new, a_out = -1; + + if (a_name && (a_out = open (a_name, 0)) < 0) + { + PERROR (a_name); + } + if ((new = creat (new_name, 0666)) < 0) + { + PERROR (new_name); + } + + if (make_hdr (new, a_out, data_start, bss_start, entry_address, a_name, new_name) < 0 + || copy_text_and_data (new) < 0 + || copy_sym (new, a_out, a_name, new_name) < 0 +#ifdef COFF + || adjust_lnnoptrs (new, a_out, new_name) < 0 +#endif + ) + { + close (new); + /* unlink (new_name); /* Failed, unlink new a.out */ + return -1; + } + + close (new); + if (a_out >= 0) + close (a_out); + mark_x (new_name); + return 0; +} + +/* **************************************************************** + * make_hdr + * + * Make the header in the new a.out from the header in core. + * Modify the text and data sizes. + */ +static int +make_hdr (new, a_out, data_start, bss_start, entry_address, a_name, new_name) + int new, a_out; + unsigned data_start, bss_start, entry_address; + char *a_name; + char *new_name; +{ + int tem; +#ifdef COFF + auto struct scnhdr f_thdr; /* Text section header */ + auto struct scnhdr f_dhdr; /* Data section header */ + auto struct scnhdr f_bhdr; /* Bss section header */ + auto struct scnhdr scntemp; /* Temporary section header */ + register int scns; +#endif /* COFF */ + unsigned int bss_end; + + pagemask = getpagesize () - 1; + + /* Adjust text/data boundary. */ +#ifdef NO_REMAP + data_start = (int) start_of_data (); +#else /* not NO_REMAP */ + if (!data_start) + data_start = (int) start_of_data (); +#endif /* not NO_REMAP */ + data_start = ADDR_CORRECT (data_start); + +#ifdef SEGMENT_MASK + data_start = data_start & ~SEGMENT_MASK; /* (Down) to segment boundary. */ +#else + data_start = data_start & ~pagemask; /* (Down) to page boundary. */ +#endif + + bss_end = ADDR_CORRECT (sbrk (0)) + pagemask; + bss_end &= ~ pagemask; + + /* Adjust data/bss boundary. */ + if (bss_start != 0) + { + bss_start = (ADDR_CORRECT (bss_start) + pagemask); + /* (Up) to page bdry. */ + bss_start &= ~ pagemask; + if (bss_start > bss_end) + { + ERROR1 ("unexec: Specified bss_start (%u) is past end of program", + bss_start); + } + } + else + bss_start = bss_end; + + if (data_start > bss_start) /* Can't have negative data size. */ + { + ERROR2 ("unexec: data_start (%u) can't be greater than bss_start (%u)", + data_start, bss_start); + } + +#ifdef COFF + /* Salvage as much info from the existing file as possible */ + if (a_out >= 0) + { + if (read (a_out, &f_hdr, sizeof (f_hdr)) != sizeof (f_hdr)) + { + PERROR (a_name); + } + block_copy_start += sizeof (f_hdr); + if (f_hdr.f_opthdr > 0) + { + if (read (a_out, &f_ohdr, sizeof (f_ohdr)) != sizeof (f_ohdr)) + { + PERROR (a_name); + } + block_copy_start += sizeof (f_ohdr); + } + /* Loop through section headers, copying them in */ + for (scns = f_hdr.f_nscns; scns > 0; scns--) { + if (read (a_out, &scntemp, sizeof (scntemp)) != sizeof (scntemp)) + { + PERROR (a_name); + } + if (scntemp.s_scnptr > 0L) + { + if (block_copy_start < scntemp.s_scnptr + scntemp.s_size) + block_copy_start = scntemp.s_scnptr + scntemp.s_size; + } + if (strcmp (scntemp.s_name, ".text") == 0) + { + f_thdr = scntemp; + } + else if (strcmp (scntemp.s_name, ".data") == 0) + { + f_dhdr = scntemp; + } + else if (strcmp (scntemp.s_name, ".bss") == 0) + { + f_bhdr = scntemp; + } + } + } + else + { + ERROR0 ("can't build a COFF file from scratch yet"); + } + + /* Now we alter the contents of all the f_*hdr variables + to correspond to what we want to dump. */ + + f_hdr.f_flags |= (F_RELFLG | F_EXEC); +#ifdef EXEC_MAGIC + f_ohdr.magic = EXEC_MAGIC; +#endif +#ifndef NO_REMAP + f_ohdr.text_start = (long) start_of_text (); + f_ohdr.tsize = data_start - f_ohdr.text_start; + f_ohdr.data_start = data_start; +#endif /* NO_REMAP */ + f_ohdr.dsize = bss_start - f_ohdr.data_start; + f_ohdr.bsize = bss_end - bss_start; + f_thdr.s_size = f_ohdr.tsize; + f_thdr.s_scnptr = sizeof (f_hdr) + sizeof (f_ohdr); + f_thdr.s_scnptr += (f_hdr.f_nscns) * (sizeof (f_thdr)); + lnnoptr = f_thdr.s_lnnoptr; +#ifdef SECTION_ALIGNMENT + /* Some systems require special alignment + of the sections in the file itself. */ + f_thdr.s_scnptr + = (f_thdr.s_scnptr + SECTION_ALIGNMENT) & ~SECTION_ALIGNMENT; +#endif /* SECTION_ALIGNMENT */ + text_scnptr = f_thdr.s_scnptr; + f_dhdr.s_paddr = f_ohdr.data_start; + f_dhdr.s_vaddr = f_ohdr.data_start; + f_dhdr.s_size = f_ohdr.dsize; + f_dhdr.s_scnptr = f_thdr.s_scnptr + f_thdr.s_size; +#ifdef SECTION_ALIGNMENT + /* Some systems require special alignment + of the sections in the file itself. */ + f_dhdr.s_scnptr + = (f_dhdr.s_scnptr + SECTION_ALIGNMENT) & ~SECTION_ALIGNMENT; +#endif /* SECTION_ALIGNMENT */ + data_scnptr = f_dhdr.s_scnptr; + f_bhdr.s_paddr = f_ohdr.data_start + f_ohdr.dsize; + f_bhdr.s_vaddr = f_ohdr.data_start + f_ohdr.dsize; + f_bhdr.s_size = f_ohdr.bsize; + f_bhdr.s_scnptr = 0L; + bias = f_dhdr.s_scnptr + f_dhdr.s_size - block_copy_start; + + if (f_hdr.f_symptr > 0L) + { + f_hdr.f_symptr += bias; + } + + if (f_thdr.s_lnnoptr > 0L) + { + f_thdr.s_lnnoptr += bias; + } + +#ifdef ADJUST_EXEC_HEADER + ADJUST_EXEC_HEADER +#endif /* ADJUST_EXEC_HEADER */ + + if (write (new, &f_hdr, sizeof (f_hdr)) != sizeof (f_hdr)) + { + PERROR (new_name); + } + + if (write (new, &f_ohdr, sizeof (f_ohdr)) != sizeof (f_ohdr)) + { + PERROR (new_name); + } + + if (write (new, &f_thdr, sizeof (f_thdr)) != sizeof (f_thdr)) + { + PERROR (new_name); + } + + if (write (new, &f_dhdr, sizeof (f_dhdr)) != sizeof (f_dhdr)) + { + PERROR (new_name); + } + + if (write (new, &f_bhdr, sizeof (f_bhdr)) != sizeof (f_bhdr)) + { + PERROR (new_name); + } + return (0); + +#else /* if not COFF */ + + /* Get symbol table info from header of a.out file if given one. */ + if (a_out >= 0) + { + if (read (a_out, &ohdr, sizeof hdr) != sizeof hdr) + { + PERROR (a_name); + } + + if N_BADMAG (ohdr) + { + ERROR1 ("invalid magic number in %s", a_name); + } + hdr = ohdr; + } + else + { + bzero (hdr, sizeof hdr); + } + + unexec_text_start = (long) start_of_text (); + unexec_data_start = data_start; + + /* Machine-dependent fixup for header, or maybe for unexec_text_start */ +#ifdef ADJUST_EXEC_HEADER + ADJUST_EXEC_HEADER; +#endif /* ADJUST_EXEC_HEADER */ + + hdr.a_trsize = 0; + hdr.a_drsize = 0; + if (entry_address != 0) + hdr.a_entry = entry_address; + + hdr.a_bss = bss_end - bss_start; + hdr.a_data = bss_start - data_start; +#ifdef NO_REMAP + hdr.a_text = ohdr.a_text; +#else /* not NO_REMAP */ + hdr.a_text = data_start - unexec_text_start; +#endif /* not NO_REMAP */ + +#ifdef A_TEXT_OFFSET + hdr.a_text += A_TEXT_OFFSET (ohdr); +#endif + + if (write (new, &hdr, sizeof hdr) != sizeof hdr) + { + PERROR (new_name); + } + +#ifdef A_TEXT_OFFSET + hdr.a_text -= A_TEXT_OFFSET (ohdr); +#endif + + return 0; + +#endif /* not COFF */ +} + +/* **************************************************************** + * copy_text_and_data + * + * Copy the text and data segments from memory to the new a.out + */ +static int +copy_text_and_data (new) + int new; +{ + register char *end; + register char *ptr; + +#ifdef COFF + lseek (new, (long) text_scnptr, 0); + ptr = (char *) f_ohdr.text_start; + end = ptr + f_ohdr.tsize; + write_segment (new, ptr, end); + + lseek (new, (long) data_scnptr, 0); + ptr = (char *) f_ohdr.data_start; + end = ptr + f_ohdr.dsize; + write_segment (new, ptr, end); + +#else /* if not COFF */ + +/* Some machines count the header as part of the text segment. + That is to say, the header appears in core + just before the address that start_of_text () returns. + For them, N_TXTOFF is the place where the header goes. + We must adjust the seek to the place after the header. + Note that at this point hdr.a_text does *not* count + the extra A_TEXT_OFFSET bytes, only the actual bytes of code. */ + +#ifdef A_TEXT_SEEK + lseek (new, (long) A_TEXT_SEEK (hdr), 0); +#else +#ifdef A_TEXT_OFFSET + /* Note that on the Sequent machine A_TEXT_OFFSET != sizeof (hdr) + and sizeof (hdr) is the correct amount to add here. */ + /* In version 19, eliminate this case and use A_TEXT_SEEK whenever + N_TXTOFF is not right. */ + lseek (new, (long) N_TXTOFF (hdr) + sizeof (hdr), 0); +#else + lseek (new, (long) N_TXTOFF (hdr), 0); +#endif /* no A_TEXT_OFFSET */ +#endif /* no A_TEXT_SEEK */ + + ptr = (char *) unexec_text_start; + end = ptr + hdr.a_text; + write_segment (new, ptr, end); + + ptr = (char *) unexec_data_start; + end = ptr + hdr.a_data; +/* This lseek is certainly incorrect when A_TEXT_OFFSET + and I believe it is a no-op otherwise. + Let's see if its absence ever fails. */ +/* lseek (new, (long) N_TXTOFF (hdr) + hdr.a_text, 0); */ + write_segment (new, ptr, end); + +#endif /* not COFF */ + + return 0; +} + +write_segment (new, ptr, end) + int new; + register char *ptr, *end; +{ + register int i, nwrite, ret; + char buf[80]; + extern int errno; + char zeros[128]; + + bzero (zeros, sizeof zeros); + + for (i = 0; ptr < end;) + { + /* distance to next multiple of 128. */ + nwrite = (((int) ptr + 128) & -128) - (int) ptr; + /* But not beyond specified end. */ + if (nwrite > end - ptr) nwrite = end - ptr; + ret = write (new, ptr, nwrite); + /* If write gets a page fault, it means we reached + a gap between the old text segment and the old data segment. + This gap has probably been remapped into part of the text segment. + So write zeros for it. */ + if (ret == -1 && errno == EFAULT) + write (new, zeros, nwrite); + else if (nwrite != ret) + { + sprintf (buf, + "unexec write failure: addr 0x%x, fileno %d, size 0x%x, wrote 0x%x, errno %d", + ptr, new, nwrite, ret, errno); + PERROR (buf); + } + i += nwrite; + ptr += nwrite; + } +} + +/* **************************************************************** + * copy_sym + * + * Copy the relocation information and symbol table from the a.out to the new + */ +static int +copy_sym (new, a_out, a_name, new_name) + int new, a_out; + char *a_name, *new_name; +{ + char page[1024]; + int n; + + if (a_out < 0) + return 0; + +#ifdef COFF + if (SYMS_START == 0L) + return 0; +#endif /* COFF */ + +#ifdef COFF + if (lnnoptr) /* if there is line number info */ + lseek (a_out, lnnoptr, 0); /* start copying from there */ + else +#endif /* COFF */ + lseek (a_out, SYMS_START, 0); /* Position a.out to symtab. */ + + while ((n = read (a_out, page, sizeof page)) > 0) + { + if (write (new, page, n) != n) + { + PERROR (new_name); + } + } + if (n < 0) + { + PERROR (a_name); + } + return 0; +} + +/* **************************************************************** + * mark_x + * + * After succesfully building the new a.out, mark it executable + */ +static +mark_x (name) + char *name; +{ + struct stat sbuf; + int um; + int new = 0; /* for PERROR */ + + um = umask (777); + umask (um); + if (stat (name, &sbuf) == -1) + { + PERROR (name); + } + sbuf.st_mode |= 0111 & ~um; + if (chmod (name, sbuf.st_mode) == -1) + PERROR (name); +} + +/* + * If the COFF file contains a symbol table and a line number section, + * then any auxiliary entries that have values for x_lnnoptr must + * be adjusted by the amount that the line number section has moved + * in the file (bias computed in make_hdr). The #@$%&* designers of + * the auxiliary entry structures used the absolute file offsets for + * the line number entry rather than an offset from the start of the + * line number section! + * + * When I figure out how to scan through the symbol table and pick out + * the auxiliary entries that need adjustment, this routine will + * be fixed. As it is now, all such entries are wrong and sdb + * will complain. Fred Fish, UniSoft Systems Inc. + */ + +#ifdef COFF + +/* This function is probably very slow. Instead of reopening the new + file for input and output it should copy from the old to the new + using the two descriptors already open (WRITEDESC and READDESC). + Instead of reading one small structure at a time it should use + a reasonable size buffer. But I don't have time to work on such + things, so I am installing it as submitted to me. -- RMS. */ + +adjust_lnnoptrs (writedesc, readdesc, new_name) + int writedesc; + int readdesc; + char *new_name; +{ + register int nsyms; + register int new; +#ifdef amdahl_uts + SYMENT symentry; + AUXENT auxentry; +#else + struct syment symentry; + struct auxent auxentry; +#endif + + if (!lnnoptr || !f_hdr.f_symptr) + return 0; + + if ((new = open (new_name, 2)) < 0) + { + PERROR (new_name); + return -1; + } + + lseek (new, f_hdr.f_symptr, 0); + for (nsyms = 0; nsyms < f_hdr.f_nsyms; nsyms++) + { + read (new, &symentry, SYMESZ); + if (symentry.n_numaux) + { + read (new, &auxentry, AUXESZ); + nsyms++; + if (ISFCN (symentry.n_type)) { + auxentry.x_sym.x_fcnary.x_fcn.x_lnnoptr += bias; + lseek (new, -AUXESZ, 1); + write (new, &auxentry, AUXESZ); + } + } + } + close (new); +} + +#endif /* COFF */ + + +#else /* mips */ + +/* Unexec for mips machines. + Note that I regard it as the responsibility of people at Mips + to tell me about any changes that need to be made in this code. + I won't take responsibility to think about it even if a change + I make elsewhere causes it to break. -- RMS. */ + +#include <sys/types.h> +#include <sys/file.h> +#include <sys/stat.h> +#include <stdio.h> +#include <varargs.h> +#include <filehdr.h> +#include <aouthdr.h> +#include <scnhdr.h> +#include <sym.h> + +#define private static + +extern int errno; +extern int sys_nerr; +extern char *sys_errlist[]; +#define EEOF -1 + +private void +fatal(s, va_alist) + va_dcl +{ + va_list ap; + if (errno == EEOF) { + fputs("unexec: unexpected end of file, ", stderr); + } + else if (errno < sys_nerr) { + fprintf(stderr, "unexec: %s, ", sys_errlist[errno]); + } + else { + fprintf(stderr, "unexec: error code %d, ", errno); + } + va_start(ap); + _doprnt(s, ap, stderr); + fputs(".\n", stderr); + exit(1); +} + +#define READ(_fd, _buffer, _size, _error_message, _error_arg) \ + errno = EEOF; \ + if (read(_fd, _buffer, _size) != _size) \ + fatal(_error_message, _error_arg); + +#define WRITE(_fd, _buffer, _size, _error_message, _error_arg) \ + if (write(_fd, _buffer, _size) != _size) \ + fatal(_error_message, _error_arg); + +#define SEEK(_fd, _position, _error_message, _error_arg) \ + errno = EEOF; \ + if (lseek(_fd, _position, L_SET) != _position) \ + fatal(_error_message, _error_arg); + +struct headers { + struct filehdr fhdr; + struct aouthdr aout; + struct scnhdr text_section; + struct scnhdr rdata_section; + struct scnhdr data_section; + struct scnhdr sdata_section; + struct scnhdr sbss_section; + struct scnhdr bss_section; +}; + +unexec (new_name, a_name, data_start, bss_start, entry_address) + char *new_name, *a_name; + unsigned data_start, bss_start, entry_address; +{ + int new, old; + int pagesize, brk; + int newsyms, symrel; + int nread; + struct headers hdr; +#define BUFSIZE 8192 + char buffer[BUFSIZE]; + + old = open (a_name, O_RDONLY, 0); + if (old < 0) fatal("openning %s", a_name); + + new = creat (new_name, 0666); + if (new < 0) fatal("creating %s", new_name); + + hdr = *((struct headers *)TEXT_START); + if (hdr.fhdr.f_magic != MIPSELMAGIC + && hdr.fhdr.f_magic != MIPSEBMAGIC) { + fprintf(stderr, "unexec: input file magic number is %x, not %x or %x.\n", + hdr.fhdr.f_magic, MIPSELMAGIC, MIPSEBMAGIC); + exit(1); + } + if (hdr.fhdr.f_opthdr != sizeof(hdr.aout)) { + fprintf(stderr, "unexec: input a.out header is %d bytes, not %d.\n", + hdr.fhdr.f_opthdr, sizeof(hdr.aout)); + exit(1); + } +#if 0 + if (hdr.aout.magic != ZMAGIC + && hdr.aout.magic != NMAGIC + && hdr.aout.magic != OMAGIC) { + fprintf(stderr, "unexec: input file a.out magic number is %o, not %o, %o, or %o.\n", + hdr.aout.magic, ZMAGIC, NMAGIC, OMAGIC); + exit(1); + } +#else + if (hdr.aout.magic != ZMAGIC) { + fprintf(stderr, "unexec: input file a.out magic number is %o, not %o.\n", + hdr.aout.magic, ZMAGIC); + exit(1); + } +#endif + if (hdr.fhdr.f_nscns != 6) { + fprintf(stderr, "unexec: %d sections instead of 6.\n", hdr.fhdr.f_nscns); + } +#define CHECK_SCNHDR(field, name, flags) \ + if (strcmp(hdr.field.s_name, name) != 0) { \ + fprintf(stderr, "unexec: %s section where %s expected.\n", \ + hdr.field.s_name, name); \ + exit(1); \ + } \ + else if (hdr.field.s_flags != flags) { \ + fprintf(stderr, "unexec: %x flags where %x expected in %s section.\n", \ + hdr.field.s_flags, flags, name); \ + } + CHECK_SCNHDR(text_section, _TEXT, STYP_TEXT); + CHECK_SCNHDR(rdata_section, _RDATA, STYP_RDATA); + CHECK_SCNHDR(data_section, _DATA, STYP_DATA); + CHECK_SCNHDR(sdata_section, _SDATA, STYP_SDATA); + CHECK_SCNHDR(sbss_section, _SBSS, STYP_SBSS); + CHECK_SCNHDR(bss_section, _BSS, STYP_BSS); + + pagesize = getpagesize(); + brk = (sbrk(0) + pagesize - 1) & (-pagesize); + hdr.aout.dsize = brk - DATA_START; + hdr.aout.bsize = 0; + if (entry_address == 0) { + extern __start(); + hdr.aout.entry = (unsigned)__start; + } + else { + hdr.aout.entry = entry_address; + } + hdr.aout.bss_start = hdr.aout.data_start + hdr.aout.dsize; + hdr.rdata_section.s_size = data_start - DATA_START; + hdr.data_section.s_vaddr = data_start; + hdr.data_section.s_paddr = data_start; + hdr.data_section.s_size = brk - DATA_START; + hdr.data_section.s_scnptr = hdr.rdata_section.s_scnptr + + hdr.rdata_section.s_size; + hdr.sdata_section.s_vaddr = hdr.data_section.s_vaddr + + hdr.data_section.s_size; + hdr.sdata_section.s_paddr = hdr.sdata_section.s_paddr; + hdr.sdata_section.s_size = 0; + hdr.sdata_section.s_scnptr = hdr.data_section.s_scnptr + + hdr.data_section.s_size; + hdr.sbss_section.s_vaddr = hdr.sdata_section.s_vaddr + + hdr.sdata_section.s_size; + hdr.sbss_section.s_paddr = hdr.sbss_section.s_vaddr; + hdr.sbss_section.s_size = 0; + hdr.sbss_section.s_scnptr = hdr.sdata_section.s_scnptr + + hdr.sdata_section.s_size; + hdr.bss_section.s_vaddr = hdr.sbss_section.s_vaddr + + hdr.sbss_section.s_size; + hdr.bss_section.s_paddr = hdr.bss_section.s_vaddr; + hdr.bss_section.s_size = 0; + hdr.bss_section.s_scnptr = hdr.sbss_section.s_scnptr + + hdr.sbss_section.s_size; + + WRITE(new, TEXT_START, hdr.aout.tsize, + "writing text section to %s", new_name); + WRITE(new, DATA_START, hdr.aout.dsize, + "writing text section to %s", new_name); + + SEEK(old, hdr.fhdr.f_symptr, "seeking to start of symbols in %s", a_name); + errno = EEOF; + nread = read(old, buffer, BUFSIZE); + if (nread < sizeof(HDRR)) fatal("reading symbols from %s", a_name); +#define symhdr ((pHDRR)buffer) + newsyms = hdr.aout.tsize + hdr.aout.dsize; + symrel = newsyms - hdr.fhdr.f_symptr; + hdr.fhdr.f_symptr = newsyms; + symhdr->cbLineOffset += symrel; + symhdr->cbDnOffset += symrel; + symhdr->cbPdOffset += symrel; + symhdr->cbSymOffset += symrel; + symhdr->cbOptOffset += symrel; + symhdr->cbAuxOffset += symrel; + symhdr->cbSsOffset += symrel; + symhdr->cbSsExtOffset += symrel; + symhdr->cbFdOffset += symrel; + symhdr->cbRfdOffset += symrel; + symhdr->cbExtOffset += symrel; +#undef symhdr + do { + if (write(new, buffer, nread) != nread) + fatal("writing symbols to %s", new_name); + nread = read(old, buffer, BUFSIZE); + if (nread < 0) fatal("reading symbols from %s", a_name); +#undef BUFSIZE + } while (nread != 0); + + SEEK(new, 0, "seeking to start of header in %s", new_name); + WRITE(new, &hdr, sizeof(hdr), + "writing header of %s", new_name); + + close(old); + close(new); + mark_x(new_name); +} + +/* + * mark_x + * + * After succesfully building the new a.out, mark it executable + */ +static +mark_x (name) + char *name; +{ + struct stat sbuf; + int um = umask (777); + umask (um); + if (stat(name, &sbuf) < 0) + fatal("getting protection on %s", name); + sbuf.st_mode |= 0111 & ~um; + if (chmod(name, sbuf.st_mode) < 0) + fatal("setting protection on %s", name); +} + +#endif /* mips */ + +#endif /* not CANNOT_UNEXEC */ + +#endif /* not CANNOT_DUMP */ diff --git a/obsolete/support/undump/Encore/unexec.diff b/obsolete/support/undump/Encore/unexec.diff new file mode 100644 index 0000000000..886d0bd42a --- /dev/null +++ b/obsolete/support/undump/Encore/unexec.diff @@ -0,0 +1,91 @@ +*** unexec.c-dist Tue Sep 29 15:20:15 1987 +--- unexec.c Tue Sep 29 17:50:03 1987 +*************** +*** 428,433 + register int scns; + #endif /* COFF */ + unsigned int bss_end; + + pagemask = getpagesize () - 1; + + +--- 428,436 ----- + register int scns; + #endif /* COFF */ + unsigned int bss_end; ++ #ifdef UMAX ++ extern etext; ++ #endif + + pagemask = getpagesize () - 1; + +*************** +*** 435,440 + #ifdef NO_REMAP + data_start = (int) start_of_data (); + #else /* not NO_REMAP */ + if (!data_start) + data_start = (int) start_of_data (); + #endif /* not NO_REMAP */ + +--- 438,444 ----- + #ifdef NO_REMAP + data_start = (int) start_of_data (); + #else /* not NO_REMAP */ ++ #ifndef UMAX + if (!data_start) + #endif + data_start = (int) start_of_data (); +*************** +*** 436,441 + data_start = (int) start_of_data (); + #else /* not NO_REMAP */ + if (!data_start) + data_start = (int) start_of_data (); + #endif /* not NO_REMAP */ + data_start = ADDR_CORRECT (data_start); + +--- 440,446 ----- + #else /* not NO_REMAP */ + #ifndef UMAX + if (!data_start) ++ #endif + data_start = (int) start_of_data (); + #endif /* not NO_REMAP */ + data_start = ADDR_CORRECT (data_start); +*************** +*** 526,531 + #endif + #ifndef NO_REMAP + f_ohdr.text_start = (long) start_of_text (); + f_ohdr.tsize = data_start - f_ohdr.text_start; + f_ohdr.data_start = data_start; + #endif /* NO_REMAP */ + +--- 531,539 ----- + #endif + #ifndef NO_REMAP + f_ohdr.text_start = (long) start_of_text (); ++ #ifdef UMAX ++ f_ohdr.tsize = (long) &etext; ++ #else + f_ohdr.tsize = data_start - f_ohdr.text_start; + #endif + f_ohdr.data_start = data_start; +*************** +*** 527,532 + #ifndef NO_REMAP + f_ohdr.text_start = (long) start_of_text (); + f_ohdr.tsize = data_start - f_ohdr.text_start; + f_ohdr.data_start = data_start; + #endif /* NO_REMAP */ + f_ohdr.dsize = bss_start - f_ohdr.data_start; + +--- 535,541 ----- + f_ohdr.tsize = (long) &etext; + #else + f_ohdr.tsize = data_start - f_ohdr.text_start; ++ #endif + f_ohdr.data_start = data_start; + #endif /* NO_REMAP */ + f_ohdr.dsize = bss_start - f_ohdr.data_start; diff --git a/obsolete/support/undump/Makefile.BALANCE b/obsolete/support/undump/Makefile.BALANCE new file mode 100644 index 0000000000..fa377fed1f --- /dev/null +++ b/obsolete/support/undump/Makefile.BALANCE @@ -0,0 +1,11 @@ +BINDIR=/usr/local/bin +CFLAGS = -O + +undump: & undump.o scanargs.o + cc -o undump undump.o scanargs.o + +clean: + rm -f *.o + +install: undump + cp undump $(BINDIR) diff --git a/obsolete/support/undump/Makefile.PYR b/obsolete/support/undump/Makefile.PYR new file mode 100644 index 0000000000..a7db084836 --- /dev/null +++ b/obsolete/support/undump/Makefile.PYR @@ -0,0 +1,9 @@ +BINDIR=/usr/local/bin + +undump: undump.c + cc -O -o undump undump.c +clean: + rm -f *.o undump + +install: undump + cp undump $(BINDIR) diff --git a/obsolete/support/undump/Makefile.SUN4 b/obsolete/support/undump/Makefile.SUN4 new file mode 100644 index 0000000000..2aacc18bbf --- /dev/null +++ b/obsolete/support/undump/Makefile.SUN4 @@ -0,0 +1,14 @@ +BINDIR=/usr/local +CFLAGS= -g -Dsun3 + +undump: undump.o + cc $(CFLAGS) -o undump undump.o + +undump.o: undump.c + cc $(CFLAGS) -c undump.c + +clean: + rm -f *.o + +install: undump + cp undump $(BINDIR) diff --git a/obsolete/support/undump/Makefile.SUN_V2 b/obsolete/support/undump/Makefile.SUN_V2 new file mode 100644 index 0000000000..b92f3af043 --- /dev/null +++ b/obsolete/support/undump/Makefile.SUN_V2 @@ -0,0 +1,14 @@ +BINDIR=/usr/local +CFLAGS= -g -Dsun3 + +undump: undump.o scanargs.o + cc $(CFLAGS) -o undump undump.o scanargs.o + +undump.o: undump.c + cc $(CFLAGS) -c undump.c + +clean: + rm -f *.o + +install: undump + cp undump $(BINDIR) diff --git a/obsolete/support/undump/Makefile.SUN_V3 b/obsolete/support/undump/Makefile.SUN_V3 new file mode 100644 index 0000000000..b92f3af043 --- /dev/null +++ b/obsolete/support/undump/Makefile.SUN_V3 @@ -0,0 +1,14 @@ +BINDIR=/usr/local +CFLAGS= -g -Dsun3 + +undump: undump.o scanargs.o + cc $(CFLAGS) -o undump undump.o scanargs.o + +undump.o: undump.c + cc $(CFLAGS) -c undump.c + +clean: + rm -f *.o + +install: undump + cp undump $(BINDIR) diff --git a/obsolete/support/undump/Makefile.SYS_V b/obsolete/support/undump/Makefile.SYS_V new file mode 100644 index 0000000000..62831e78f3 --- /dev/null +++ b/obsolete/support/undump/Makefile.SYS_V @@ -0,0 +1,14 @@ +BINDIR=/usr/local +CFLAGS= -O + +undump: undump.o + cc $(CFLAGS) -o undump undump.o + +undump.o: undump.c + cc $(CFLAGS) -c undump.c + +clean: + rm -f *.o + +install: undump + cp undump $(BINDIR) diff --git a/obsolete/support/undump/Makefile.VAX4_2 b/obsolete/support/undump/Makefile.VAX4_2 new file mode 100644 index 0000000000..77de95bc65 --- /dev/null +++ b/obsolete/support/undump/Makefile.VAX4_2 @@ -0,0 +1,13 @@ +BINDIR=/usr/local + +undump: undump.o scanargs.o + cc -O -o undump undump.o scanargs.o + +undump.o: undump.c + cc -O -c undump.c + +clean: + rm -f *.o + +install: undump + cp undump $(BINDIR) diff --git a/obsolete/support/undump/Makefile.VAX4_3 b/obsolete/support/undump/Makefile.VAX4_3 new file mode 100644 index 0000000000..77de95bc65 --- /dev/null +++ b/obsolete/support/undump/Makefile.VAX4_3 @@ -0,0 +1,13 @@ +BINDIR=/usr/local + +undump: undump.o scanargs.o + cc -O -o undump undump.o scanargs.o + +undump.o: undump.c + cc -O -c undump.c + +clean: + rm -f *.o + +install: undump + cp undump $(BINDIR) diff --git a/obsolete/support/undump/Setup.BALANCE b/obsolete/support/undump/Setup.BALANCE new file mode 100644 index 0000000000..9dcb1f3cbb --- /dev/null +++ b/obsolete/support/undump/Setup.BALANCE @@ -0,0 +1,4 @@ +# /bin/sh +# setup the ./undump area for Sequent Balance/DYNIX +cp Makefile.BALANCE Makefile +cp undump.BALANCE.c undump.c diff --git a/obsolete/support/undump/Setup.PYR b/obsolete/support/undump/Setup.PYR new file mode 100644 index 0000000000..907be482b0 --- /dev/null +++ b/obsolete/support/undump/Setup.PYR @@ -0,0 +1,7 @@ +#!/bin/sh +# setup the ./undump area for Pyramid +cp Makefile.PYR Makefile +cp undump.PYR.c undump.c + + + diff --git a/obsolete/support/undump/Setup.SUN4 b/obsolete/support/undump/Setup.SUN4 new file mode 100644 index 0000000000..238b9de2d5 --- /dev/null +++ b/obsolete/support/undump/Setup.SUN4 @@ -0,0 +1,5 @@ +#!/bin/sh +# setup the ./undump area for Sun4 +cp Makefile.SUN4 Makefile +cp undump.SUN4.c undump.c + diff --git a/obsolete/support/undump/Setup.SUN_V2 b/obsolete/support/undump/Setup.SUN_V2 new file mode 100644 index 0000000000..c79fcea64d --- /dev/null +++ b/obsolete/support/undump/Setup.SUN_V2 @@ -0,0 +1,5 @@ +#!/bin/sh +# setup the ./undump area for Sun2 running O.S. 3.2 or above +echo If you are not running O.S. 3.2, use Setup.VAX4_2 instead +cp Makefile.SUN_V2 Makefile +cp undump.SUN_V2.c undump.c diff --git a/obsolete/support/undump/Setup.SUN_V3 b/obsolete/support/undump/Setup.SUN_V3 new file mode 100644 index 0000000000..1bf48da26d --- /dev/null +++ b/obsolete/support/undump/Setup.SUN_V3 @@ -0,0 +1,5 @@ +#!/bin/sh +# setup the ./undump area for Sun3 running O.S. 3.0 or above +cp Makefile.SUN_V3 Makefile +cp undump.SUN_V3.c undump.c + diff --git a/obsolete/support/undump/Setup.SYS_V b/obsolete/support/undump/Setup.SYS_V new file mode 100644 index 0000000000..1832a36228 --- /dev/null +++ b/obsolete/support/undump/Setup.SYS_V @@ -0,0 +1,5 @@ +#!/bin/sh +# setup the ./undump area for System V +cp Makefile.SYS_V Makefile +cp undump.SYS_V.c undump.c + diff --git a/obsolete/support/undump/Setup.VAX4_2 b/obsolete/support/undump/Setup.VAX4_2 new file mode 100644 index 0000000000..3aae9fe29e --- /dev/null +++ b/obsolete/support/undump/Setup.VAX4_2 @@ -0,0 +1,5 @@ +#!/bin/sh +# setup the ./undump area for Vax running BSD 4.2 +cp Makefile.VAX4_2 Makefile +cp undump.VAX4_2.c undump.c + diff --git a/obsolete/support/undump/Setup.VAX4_3 b/obsolete/support/undump/Setup.VAX4_3 new file mode 100644 index 0000000000..bea5d5dd0b --- /dev/null +++ b/obsolete/support/undump/Setup.VAX4_3 @@ -0,0 +1,4 @@ +#!/bin/sh +# setup the ./undump area for Vax running BSD 4.3 +cp Makefile.VAX4_3 Makefile +cp undump.VAX4_3.c undump.c diff --git a/obsolete/support/undump/scanargs.1 b/obsolete/support/undump/scanargs.1 new file mode 100644 index 0000000000..827788f4e3 --- /dev/null +++ b/obsolete/support/undump/scanargs.1 @@ -0,0 +1,446 @@ +.TH SCANARGS 3 "AMPEX CORP." +.SH NAME +scanargs, qscanargs - formatted conversion from command argument list +.SH SYNOPSIS +.B "#include <stdio.h>" +.PP +.B "scanargs(argc, argv, format" +[, pointer]... +.B ) +.br +.B "int argc;" +.br +.B "char *argv[];" +.br +.B "char *format;" +.SH DESCRIPTION +.I Scanargs +reads +.I argc +arguments from an argument list pointed to by +.I argv. +It converts the argument list according to the format string, +and stores the results of the conversions in its parameters. +.I Qscanargs +is a smaller and less powerful version which does not understand floating +point. +.PP +Scanargs expects as its parameters an argument count +.I argc, +a pointer to an argument list +.I argv +(see +.IR exec (2)), +a control string +.I format, +described below, and a set of +.I pointer +arguments indicating where the converted output should be stored. +.PP +The control string contains specifications, which are used to direct +interpretation of argument sequences. It contains +the necessary information to describe an acceptable +syntax for the argument list, and the expected meaning of each argument. +.PP +If the scanning fails it will print a cryptic +message telling why it failed, and generate a +.I usage +message from the control string. +.PP +The control string is composed of two parts: +.PP +.B Name:\ \ +The first characters in the string are assumed to be the calling +name of the program being executed. This is used for generation of +usage messages, but is otherwise ignored. +If this field is a % sign, it is replaced with the contents of +.IR argv [0] +in the message. +.PP +.B Conversions:\ \ +Following the name, an optional list of conversion specifications is given, +with separating spaces. The structure of a conversion specification: +.RS +.PP +.B "label_key_conversion" +.RE +.PP +consists of a +.I label +which is a string of non-space characters describing the acceptable +argument, a +.I key +which may be either of +.TP 4 +.B % +The argument is optional. Its absence is ignored. +.TP 4 +.B ! +A required argument. If absent, an error return ensues. +.PP +and a +.I conversion +character which indicates the interpretation of the argument; the corresponding +pointer parameter must be of a restricted type. +.PP +The following conversion characters are supported: +.TP 4 +.B d D +a decimal integer is expected; the corresponding parameter should be an +.I int +or a +.I long +(if +.B D +is specified) pointer. +.TP 4 +.B o O +an octal integer is expected; the corresponding parameter should be an +.I int +or a +.I long +pointer. +.TP 4 +.B x X +a hexadecimal integer is expected; the corresponding parameter should be an +.I int +or a +.I long +pointer. +.TP 4 +.B n N +an integer numeric conversion using +.I C +language syntax. Numbers beginning +.B 0x +are hexadecimal, numbers beginning +.B 0 +are octal, and other numbers are decimal. Negative hex numbers must have +the minus sign +.I following +the +.BR 0x , +i.e. negative 0xa would be given as 0x\-a. The corresponding pointer +should point to an +.I int +or a +.I long. +.TP 4 +.B f F +a floating point number is expected; the corresponding parameter should +be a pointer to a +.I float +or a +.I double. +Not available in +.I qscanargs. +.TP 4 +.B "x X d D o O f F" +all numeric types supported by +.I scanf(3S) +are legal in +.I scanargs; +.I qscanargs +supports all but +.B f +and +.B F +formats, and avoids including the large size of the +.I scanf +routine. +.TP 4 +.B s +a character string is expected; the corresponding parameter should be the +address of a pointer to +.I char. +.TP 4 +.B \- +a single character flag is expected; the corresponding parameter should +be an +.I int +pointer. The occurrence of a +.B \- +followed by the character specified in the label +will cause the setting of the least significant bit of the integer pointed to +by the corresponding parameter. The label may consist of up to sixteen +(32 on a VAX) option +characters, in which case one of the bits of the integer is independantly +set to reflect which one of the flags was present. (The right most character +corresponds to the LSB of the integer) Only one option may be chosen from +each conversion specification. The bits which are not set will remain in +their previous state. For example, a specification of +.B abc%\- +would match one of +.B \-a \-b +or +.B \-c +in the argument list. +.B \-c +would cause the corresponding variable to be set to 1, +.B \-b +to 2, and +.B \-a +to 4. (Actually, these bits would be ored in, but assuming an intial value +of 0, this is true). +.PP +.RS 4 +The +.B \- +may be followed immediately by more label_key_conversion specifications. +These should not be separated by blanks and should not contain any +.B \- +specifications. They will be processed only if the flag argument is scanned. +This allows optional specification of parameters corresponding to a flag +(e.g. +.I \-f file +). Corresponding arguments on the command line must appear between the flag +which introduces them and the next flag in the command line. +.RE +.TP 4 +.B $ +This may appear only as the last specifier in the format string, and is used +to "eat up" the rest of the command arguments. The corresponding function +argument is an +.I int +pointer. An index into +.I argv +to the dividing point between the arguments which have been used, and those +which have not is returned. This index points to the first unused command +argument. If there is no such dividing point, an error +will be generated. +.PP +A string or numeric conversion character may be preceded by a +.B * +or a +.B , +to indicate that a list of such arguments is expected. If +.B , +is used, then the AT&T proposed argument standard is followed, and a single +string is expected, with the individual list elements separated by commas or +spaces. Two commas in a row will produce a null entry (0 if numeric, +zero-length string if string conversion), but multiple spaces, and spaces +following a comma, are taken as a single separator. If +.B * +is specified, then multiple arguments are parsed to produce the list. A +format specifier with a +.B * +or a +.B , +takes two arguments. The first is an +.B int +pointer, the number of items in the list is returned here. The second is a +pointer to pointer to the correct data type for the format specifier. A +pointer to the list of arguments is returned here. +.PP +The scanner will process the control string from left to right, +and where there are multiple conversions of the same type, they will +be assigned one to one with their order of occurrence in the argument list. +Where the order of the arguments is not ambiguous in the control string, +they may occur in any order in the argument list. (ie. A decimal number +will not be confused with a flag, but may +be confused with an octal number or another decimal number. So if an +octal and a decimal number are to be arguments, their order will determine +their conversion, while a decimal number and a flag as arguments may occur +in any order and still be converted correctly.) +.PP +An argument list that does not match the requirements of the control +string will cause the printing of a short message telling why, and +a message telling what the correct usage is. +This usage is gleaned from the control string, and the labels are used +directly. The labels should be both terse and descriptive! Spaces, tabs, +and newlines in the format string will be reproduced in the usage message, +and can be used for effective prettyprinting. A single tab (following a +newline) will indent the line directly under the command name in the usage +message. +.PP +The +.I scanargs +function returns 1 when the argument list matched the requirements +of the control string, and returns 0 if there was a failure. +Parameters for any conversions not matched are left untouched. +.br +For example, the call +.RS +.PP +int i; double x; char *name; +.br +scanargs(argc, argv, "program decimal%d floating%F file%s" +.in 15 +, &i, &x, &name ); +.RE +.PP +in a C program executed by the shell command +.RS +.PP +.I % +program 10 3.5397 inputfile +.RE +.PP +will assign to +.I i +the value 10, +.I x +the value 3.5397, and +.I name +will point to the string "inputfile". +.PP +If the program was executed by the shell command +.RS +.PP +.I % +program 3.4 .7 inputfile +.RE +.PP +the following would be printed on the standard error: +.RS +.PP +extra arguments not processed +.br +usage : program [decimal] [floating] [file] +.RE +.PP +because 3.4 matches the type of 'floating' and inputfile matches +the type of 'file', leaving .7 unmatched (it is considered a string by +scanargs, to be considered a number, it must begin with a digit). +.PP +Finally, executing the command +.RS +.br +.I % +program 10 +.RE +.br +would assign 10 to +.IR i , +leaving +.I x +and +.I name +unaffected. +.PP +This call could be used for the +.IR diff (1) +command +.RS +.PP +int blanks; int flags; char *file1; char *file2; +.br +scanargs(argc, argv, "diff b%\- efh%\- file1!s file2!s" +.in 15 +, &blanks, &flags, &file1, &file2 ); +.RE +.PP +and would only allow one of either +.B "\-e \-f" +or +.B \-h +to be chosen optionally, with +.B \-b +as an independent option. +.B File1 +and +.B file2 +are both required. +The usage message for this version of +.I diff +would be +.RS +.PP +usage : diff [\-b] \-{efh} file1 file2 +.RE + +This call could be used for a simplified version of the +.IR sed (1) +command +.RS +.PP +int efile; int noprint; char *script; char *file1; char *file2; +.br +scanargs(argc, argv, "sed n%\- script%s f%\-editfile!s file%s" +.in 15 +, &noprint, &script, &efile, &file1, &file2 ); +.RE +.PP +If the +.B \-f +option is specified, then a file name must be given as the next string +argument. +The usage message for this version of +.I sed +would be +.RS +.PP +usage : sed [\-n] [script] [\-f editfile] file +.RE + +.PP +Further notes on putting together a format string: +.PP +It is still possible for conditional arguments to be confused with +arguments which stand alone. For this reason, it is recommended that +all flags (and associated conditional arguments) be specified first in +the scanargs format string. This ordering is not necessary for the +command line arguments, however. The only case which could still cause +confusion if these rules are followed is illustrated below: +.br +.RS +format string: "prog d%\-num%d othernum%d" +.br +command line: prog \-d 9 +.RE +.br +It is unclear whether the number 9 should be associated with the +.I num +parameter or the +.I othernum +parameter. +.I Scanargs +assigns it to the +.I num +parameter. To force it to be associated with +.I othernum +the +command could be invoked as either +.br +.RS + prog 9 \-d +.br +or prog \-d \-\- 9 +.RE +.br +The +.B \-\- +in the second example is interpreted as a flag, thereby +terminating the scan for arguments introduced by the +.BR \-d . +According to the proposed standard, an argument of +.B \-\- +is to be interpreted as terminating the optional arguments on a flag. +.PP +Note that if the format string in the above example were +.br +.RS + "prog othernum%d d%\-num%d" +.RE +.br +it would be impossible to assign a value to +.I num +without also +assigning a value to +.I othernum. + +.SH SEE ALSO +exec(2), scanf(3S) +.SH DIAGNOSTICS +Returns 0 on error, 1 on success. +.SH AUTHOR +Gary Newman \(em Ampex Corporation +.br +Spencer W. Thomas \(em University of Utah +.SH BUGS +By its nature a call to scanargs defines a syntax +which may be ambiguous, and although the results may be surprising, +they are quite predictable. +The heuristic used to tell string arguments from numeric arguments is just +that. In fact, that you can't give a number as a string argument +is sort of bogus. diff --git a/obsolete/support/undump/scanargs.c b/obsolete/support/undump/scanargs.c new file mode 100644 index 0000000000..ec78837f93 --- /dev/null +++ b/obsolete/support/undump/scanargs.c @@ -0,0 +1,879 @@ +/* + * $Header: scanargs.c,v 1.7 86/11/16 03:25:48 thomas Exp $ + * Version 7 compatible + * Argument scanner, scans argv style argument list. + * + * Some stuff is a kludge because sscanf screws up + * + * Gary Newman - 10/4/1979 - Ampex Corp. + * + * Modified by Spencer W. Thomas, Univ. of Utah, 5/81 to + * add args introduced by a flag, add qscanargs call, + * allow empty flags. + * + * Compiling with QUICK defined generates 'qscanargs' == + * scanargs w/o floating point support; avoids huge size + * of scanf. + * + * If you make improvements we'd like to get them too. + * Jay Lepreau lepreau@utah-20, decvax!harpo!utah-cs!lepreau + * Spencer Thomas thomas@utah-20, decvax!harpo!utah-cs!thomas + * + * (I know the code is ugly, but it just grew, you see ...) + * + * Modified by: Spencer W. Thomas + * Date: Feb 25 1983 + * 1. Fixed scanning of optional args. Now args introduced by a flag + * must follow the flag which introduces them and precede any other + * flag argument. It is still possible for a flag introduced + * argument to be mistaken for a "bare" argument which occurs + * earlier in the format string. This implies that flags may not + * be conditional upon other flags, and a message will be generated + * if this is attempted. + * + * 2. Usage message can be formatted by inserting newlines, tabs and + * spaces into the format string. This is especially useful for + * long argument lists. + * + * 3. Added n/N types for "numeric" args. These args are scanned + * using the C language conventions - a number starting 0x is + * hexadecimal, a number starting with 0 is octal, otherwise it is + * decimal. + * + * Modified at BRL 16-May-88 by Mike Muuss to avoid Alliant STDC desire + * to have all "void" functions so declared. + */ + +#include <stdio.h> +#include <ctype.h> +#include <varargs.h> + +typedef char bool; +/* + * An explicit assumption is made in this code that all pointers look + * alike, except possible char * pointers. + */ +typedef int *ptr; + +#define YES 1 +#define NO 0 +#define ERROR(msg) {fprintf(stderr, "msg\n"); goto error; } + +/* + * Storage allocation macros + */ +#define NEW( type, cnt ) (type *) malloc( (cnt) * sizeof( type ) ) +#define RENEW( type, ptr, cnt ) (type *) realloc( ptr, (cnt) * sizeof( type ) ) + +static char * prformat(); +static bool isnum(); +static int _do_scanargs(); +void scan_usage(); + +/* + * Argument list is (argc, argv, format, ... ) + */ +#ifndef QUICK +scanargs ( va_alist ) +#else +qscanargs ( va_alist ) +#endif +va_dcl +{ + va_list argl; + int retval; + + va_start( argl ); + retval = _do_scanargs( argl ); + va_end( argl ); + return retval; +} + +/* + * This routine is necessary because of a pyramid compiler botch that + * uses parameter registers in a varargs routine. The extra + * subroutine call isolates the args on the register stack so they + * don't get trashed. + */ + +static +_do_scanargs( argl ) +va_list argl; +{ + int argc; /* Actual arguments */ + char **argv; + char *format; + + register check; /* check counter to be sure all argvs + are processed */ + register char *cp; + register cnt; + int optarg = 0; /* where optional args start */ + int nopt; + char tmpflg, /* temp flag */ + typchr; /* type char from format string */ + char c; + bool * arg_used; /* array of flags */ + char * malloc(); + ptr aptr; /* pointer to return loc */ + + bool required; + int excnt; /* which flag is set */ + bool exflag; /* when set, one of a set of exclusive + flags is set */ + + bool list_of; /* set if parsing off a list of args */ + bool comma_list; /* set if AT&T style multiple args */ + int * cnt_arg; /* where to stuff list count */ + int list_cnt; /* how many in list */ + /* These are used to build return lists */ + char ** strlist; + int * intlist; + long * longlist; + float * fltlist; + double *dbllist; + + char *ncp; /* remember cp during flag scanning */ +#ifndef QUICK + char *cntrl; /* control string for scanf's */ + char junk[2]; /* junk buffer for scanf's */ + + cntrl = "% %1s"; /* control string initialization for + scanf's */ +#endif + + argc = va_arg( argl, int ); + argv = va_arg( argl, char ** ); + format = va_arg( argl, char * ); + + arg_used = NEW( bool, argc ); + if (arg_used == NULL) + { + fprintf(stderr, "malloc failed in scanargs, exiting\n"); + exit(-1); + } + else + { + for (cnt=0; cnt<argc; cnt++) + arg_used[cnt] = NO; + } + + check = 0; + cp = format; + /* + * Skip program name + */ + while ( *cp != ' ' && *cp != '\t' && *cp != '\n' && *cp != '\0' ) + cp++; + + while (*cp) + { + required = NO; /* reset per-arg flags */ + list_of = NO; + comma_list = NO; + list_cnt = 0; + switch (*(cp++)) + { + default: /* all other chars */ + break; + case ' ': /* separators */ + case '\t': + case '\n': + optarg = 0; /* end of optional arg string */ + break; + + case '!': /* required argument */ + required = YES; + case '%': /* not required argument */ +reswitch: /* after finding '*' or ',' */ + switch (typchr = *(cp++)) + { + case ',': /* argument is AT&T list of things */ + comma_list = YES; + case '*': /* argument is list of things */ + list_of = YES; + list_cnt = 0; /* none yet */ + cnt_arg = va_arg( argl, int *); /* item count * here */ + goto reswitch; /* try again */ + + case '$': /* "rest" of argument list */ + while ( argc > 1 && !arg_used[argc-1] ) + argc--; /* find last used argument */ + *va_arg( argl, int * ) = argc; + break; + + case '-': /* argument is flag */ + if (optarg > 0) + ERROR(Format error: flag conditional on flag not allowed); + + /* go back to label */ + ncp = cp-1; /* remember */ + cp -= 3; + for (excnt = exflag = 0 + ; *cp != ' ' && !(*cp=='-' &&(cp[-1]=='!'||cp[-1]=='%')); + (--cp, excnt++)) + { + for (cnt = optarg+1; cnt < argc; cnt++) + { + /* flags all start with - */ + if (*argv[cnt] == '-' && !arg_used[cnt] && + !isdigit(argv[cnt][1])) + if (*(argv[cnt] + 1) == *cp) + { + if (*(argv[cnt] + 2) != 0) + ERROR (extra flags ignored); + if (exflag) + ERROR (more than one exclusive flag chosen); + exflag++; + required = NO; + check += cnt; + arg_used[cnt] = 1; + nopt = cnt; + *va_arg( argl, int *) |= (1 << excnt); + break; + } + } + } + if (required) + ERROR (flag argument missing); + cp = ncp; + /* + * If none of these flags were found, skip any + * optional arguments (in the varargs list, too). + */ + if (!exflag) + { + va_arg( argl, int * ); /* skip the arg, too */ + while (*++cp && ! isspace(*cp)) + if (*cp == '!' || *cp == '%') + { + if ( *++cp == '*' || *cp == ',' ) + { + cp++; + va_arg( argl, int * ); + } + /* + * Assume that char * might be a + * different size, but that all + * other pointers are same size. + */ + if ( *cp == 's' ) + va_arg( argl, char * ); + else + va_arg( argl, ptr ); + } + } + else + { + optarg = nopt; + cp++; /* skip over - */ + } + + break; + + case 's': /* char string */ + case 'd': /* decimal # */ + case 'o': /* octal # */ + case 'x': /* hexadecimal # */ + case 'n': /* "number" in C syntax */ +#ifndef QUICK + case 'f': /* floating # */ +#endif + case 'D': /* long decimal # */ + case 'O': /* long octal # */ + case 'X': /* long hexadecimal # */ + case 'N': /* long number in C syntax */ +#ifndef QUICK + case 'F': /* double precision floating # */ +#ifdef sgi + /* Fix for broken SGI IRIS floats */ + if ( typchr == 'F' ) typchr = 'f'; +#endif /* sgi */ +#endif /* QUICK */ + for (cnt = optarg+1; cnt < argc; cnt++) + { + ncp = argv[cnt]; + + if ( isnum( ncp, typchr, comma_list ) ) + { + ; /* it's ok, then */ + } + else if ( *ncp == '-' && ncp[1] != '\0' ) + if ( optarg > 0 ) /* end optional args? */ + { + /* Eat the arg, too, if necessary */ + if ( list_cnt == 0 ) + if ( typchr == 's' ) + va_arg( argl, char * ); + else + va_arg( argl, ptr ); + break; + } + else + continue; + else if ( typchr != 's' ) + continue; /* not number, keep looking */ + + /* + * Otherwise usable argument may already + * be used. (Must check this after + * checking for flag, though.) + */ + if (arg_used[cnt]) continue; + + /* + * If it's a comma-and-or-space-separated + * list then count how many, and separate + * the list into an array of strings. + */ + if ( comma_list ) + { + register char * s; + int pass; + + /* + * On pass 0, just count them. On + * pass 1, null terminate each string + */ + for ( pass = 0; pass <= 1; pass++ ) + { + for ( s = ncp; *s != '\0'; ) + { + if ( pass ) + strlist[list_cnt] = s; + while ( (c = *s) != '\0' && c != ' ' && + c != '\t' && c != ',' ) + s++; + if ( pass ) + *s = '\0'; + + list_cnt++; /* count separators */ + /* + * Two commas in a row give a null + * string, but two spaces + * don't. Also skip spaces + * after a comma. + */ + if ( c != '\0' ) + while ( *++s == ' ' || *s == '\t' ) + ; + } + if ( pass == 0 ) + { + strlist = NEW( char *, list_cnt ); + list_cnt = 0; + } + } + } + else if ( list_of ) + list_cnt++; /* getting them one at a time */ + /* + * If it's either type of list, then alloc + * storage space for the returned values + * (except that comma-separated string + * lists already are done). + */ + if ( list_of ) + { + if ( list_cnt == 1 || comma_list ) + switch( typchr ) + { + case 's': + if ( !comma_list ) + strlist = NEW( char *, 1 ); + aptr = (ptr) &strlist[0]; + break; + case 'n': + case 'd': + case 'o': + case 'x': + intlist = NEW( int, list_cnt ); + aptr = (ptr) &intlist[0]; + break; + case 'N': + case 'D': + case 'O': + case 'X': + longlist = NEW( long, list_cnt ); + aptr = (ptr) &longlist[0]; + break; + case 'f': + fltlist = NEW( float, list_cnt ); + aptr = (ptr) &fltlist[0]; + break; + case 'F': + dbllist = NEW( double, list_cnt ); + aptr = (ptr) &dbllist[0]; + break; + } + else + switch( typchr ) + { + case 's': + strlist = RENEW( char *, strlist, + list_cnt ); + aptr = (ptr) &strlist[list_cnt-1]; + break; + case 'n': + case 'd': + case 'o': + case 'x': + intlist = RENEW( int, intlist, + list_cnt ); + aptr = (ptr) &intlist[list_cnt-1]; + break; + case 'N': + case 'D': + case 'O': + case 'X': + longlist = RENEW( long, longlist, + list_cnt ); + aptr = (ptr) &longlist[list_cnt-1]; + break; + case 'f': + fltlist = RENEW( float, fltlist, + list_cnt ); + aptr = (ptr) &fltlist[list_cnt-1]; + break; + case 'F': + dbllist = RENEW( double, dbllist, + list_cnt ); + aptr = (ptr) &dbllist[list_cnt-1]; + break; + } + } + else + aptr = va_arg( argl, ptr ); + + if ( typchr == 's' ) + { + if ( ! comma_list ) + *(char **)aptr = ncp; + } + else + { + nopt = 0; + do { + /* + * Need to update aptr if parsing + * a comma list + */ + if ( comma_list && nopt > 0 ) + { + ncp = strlist[nopt]; + switch( typchr ) + { + case 'n': + case 'd': + case 'o': + case 'x': + aptr = (ptr) &intlist[nopt]; + break; + case 'N': + case 'D': + case 'O': + case 'X': + aptr = (ptr) &longlist[nopt]; + break; + case 'f': + aptr = (ptr) &fltlist[nopt]; + break; + case 'F': + aptr = (ptr) &dbllist[nopt]; + break; + } + } + /* + * Do conversion for n and N types + */ + tmpflg = typchr; + if (typchr == 'n' || typchr == 'N' ) + if (*ncp != '0') + tmpflg = 'd'; + else if (*(ncp+1) == 'x' || + *(ncp+1) == 'X') + { + tmpflg = 'x'; + ncp += 2; + } + else + tmpflg = 'o'; + if (typchr == 'N') + toupper( tmpflg ); + + +#ifndef QUICK + cntrl[1] = tmpflg;/* put in conversion */ + if (sscanf (ncp, cntrl, aptr, junk) != 1) + ERROR (Bad numeric argument); +#else + if (numcvt(ncp, tmpflg, aptr) != 1) + ERROR (Bad numeric argument); +#endif + } while ( comma_list && ++nopt < list_cnt ); + } + check += cnt; + arg_used[cnt] = 1; + required = NO; + /* + * If not looking for multiple args, + * then done, otherwise, keep looking. + */ + if ( !( list_of && !comma_list ) ) + break; + else + continue; + } + if (required) + switch (typchr) + { + case 'x': + case 'X': + ERROR (missing hexadecimal argument); + case 's': + ERROR (missing string argument); + case 'o': + case 'O': + ERROR (missing octal argument); + case 'd': + case 'D': + ERROR (missing decimal argument); + case 'f': + case 'F': + ERROR (missing floating argument); + case 'n': + case 'N': + ERROR (missing numeric argument); + } + if ( list_cnt > 0 ) + { + *cnt_arg = list_cnt; + switch ( typchr ) + { + case 's': + *va_arg( argl, char *** ) = strlist; + break; + case 'n': + case 'd': + case 'o': + case 'x': + *va_arg( argl, int ** ) = intlist; + break; + case 'N': + case 'D': + case 'O': + case 'X': + *va_arg( argl, long ** ) = longlist; + break; + case 'f': + *va_arg( argl, float ** ) = fltlist; + break; + case 'F': + *va_arg( argl, double **) = dbllist; + break; + } + if ( typchr != 's' ) + free( (char *) strlist ); + } + else if ( cnt >= argc ) + { + /* Fell off end looking, so must eat the arg */ + if ( typchr == 's' ) + va_arg( argl, char * ); + else + va_arg( argl, ptr ); + } + break; + default: /* error */ + fprintf (stderr, "error in call to scanargs\n"); + return (0); + } + } + } + + /* Count up empty flags */ + for (cnt=1; cnt<argc; cnt++) + if (argv[cnt][0] == '-' && argv[cnt][1] == '-' && argv[cnt][2] == 0 + && !arg_used[cnt] ) + check += cnt; + + /* sum from 1 to N = n*(n+1)/2 used to count up checks */ + if (check != (((argc - 1) * argc) / 2)) + ERROR (extra arguments not processed); + + free(arg_used); + return (1); + +error: + scan_usage( argv, format ); + free(arg_used); + return 0; +} + +void +scan_usage( argv, format ) +char ** argv; +char * format; +{ + register char * cp; + + fprintf (stderr, "usage : "); + if (*(cp = format) != ' ') + { + if ( *cp == '%' ) + { + /* + * This is bogus, but until everyone can agree on a name + * for (rindex/strrchr) .... + */ + for ( cp = argv[0]; *cp != '\0'; cp++ ) + ; /* find the end of the string */ + for ( ; cp > argv[0] && *cp != '/'; cp-- ) + ; /* find the last / */ + if ( *cp == '/' ) + cp++; + fprintf( stderr, "%s", cp ); + + cp = format + 1; /* reset to where it should be */ + } + while (putc (*cp++, stderr) != ' '); + } + else + fprintf (stderr, "?? "); + while (*cp == ' ') + cp++; + prformat (cp, NO); +} + +static char * +prformat (format, recurse) +char *format; +{ + register char *cp; + bool required, comma_list; + int list_of; + + cp = format; + if (recurse) + putc (' ', stderr); + + required = NO; + list_of = 0; + comma_list = NO; + while (*cp) + { + switch (*cp) + { + default: + cp++; + break; + case ' ': + case '\n': + case '\t': + /* allow annotations */ + for ( ; format < cp; format++ ) + putc( *format, stderr ); + putc(*cp, stderr); + format = ++cp; + break; + case '!': + required = YES; + case '%': +reswitch: + switch (*++cp) + { + case ',': + comma_list++; + case '*': + list_of++; + goto reswitch; + + case '$': /* "rest" of argument list */ + if (!required) + putc ('[', stderr); + for (; format < cp - 1 - list_of; format++) + putc (*format, stderr); + fputs( " ...", stderr ); + if ( !required ) + putc( ']', stderr ); + break; + + case '-': /* flags */ + if (!required) + putc ('[', stderr); + putc ('-', stderr); + + if (cp - format > 2 + list_of) + putc ('{', stderr); + cp = format; + while (*cp != '%' && *cp != '!') + putc (*cp++, stderr); + if (cp - format > 1 + list_of) + putc ('}', stderr); + cp += 2; /* skip !- or %- */ + if (*cp && !isspace(*cp)) + cp = prformat (cp, YES); + /* this is a recursive call */ + + cp--; /* don't ignore next character */ + + if (!required) + putc (']', stderr); + break; + case 's': /* char string */ + case 'd': /* decimal # */ + case 'o': /* octal # */ + case 'x': /* hexadecimal # */ + case 'f': /* floating # */ + case 'D': /* long decimal # */ + case 'O': /* long octal # */ + case 'X': /* long hexadecimal # */ + case 'F': /* double precision floating # */ + case 'n': /* numeric arg (C format) */ + case 'N': /* long numeric arg */ + if (!required) + putc ('[', stderr); + for (; format < cp - 1 - list_of; format++) + putc (*format, stderr); + if ( list_of != 0 ) + { + if ( comma_list ) + putc( ',', stderr ); + else + putc( ' ', stderr ); + fputs( "...", stderr ); + } + if (!required) + putc (']', stderr); + break; + default: + break; + } + required = NO; + list_of = NO; + comma_list = NO; + if (*cp) /* check for end of string */ + format = ++cp; + if (*cp && !isspace(*cp)) + putc (' ', stderr); + } + if (recurse && isspace(*cp)) + break; + } + if (!recurse) + { + for ( ; format < cp; format++ ) + putc( *format, stderr ); + putc ('\n', stderr); + } + return (cp); +} + +/* + * isnum - determine whether a string MIGHT represent a number. + * typchr indicates the type of argument we are looking for, and + * determines the legal character set. If comma_list is YES, then + * space and comma are also legal characters. + */ +static bool +isnum( str, typchr, comma_list ) +register char * str; +char typchr; +bool comma_list; +{ + register char * allowed, * digits, * cp; + bool hasdigit = NO; + + switch( typchr ) + { + case 'n': + case 'N': + allowed = " \t,+-x0123456789abcdefABCDEF"; + break; + case 'd': + case 'D': + allowed = " \t,+-0123456789"; + break; + case 'o': + case 'O': + allowed = " \t,01234567"; + break; + case 'x': + case 'X': + allowed = " \t,0123456789abcdefABCDEF"; + break; + case 'f': + case 'F': + allowed = " \t,+-eE.0123456789"; + break; + case 's': /* only throw out decimal numbers */ + default: + allowed = " \t,+-.0123456789"; + break; + } + digits = allowed; + while ( *digits != '0' ) + digits++; + if ( ! comma_list ) + allowed += 3; /* then don't allow space, tab, comma */ + + while ( *str != '\0' ) + { + for ( cp = allowed; *cp != '\0' && *cp != *str; cp++ ) + ; + if ( *cp == '\0' ) + return NO; /* if not in allowed chars, not number */ + if ( cp - digits >= 0 ) + hasdigit = YES; + str++; + } + return hasdigit; +} + +#ifdef QUICK +numcvt(str, conv, val) +register char *str; +char conv; +int *val; +{ + int base, neg = 0; + register unsigned int d; + long retval = 0; + register char *digits; + extern char *index(); + if (conv == 'o' || conv == 'O') + base = 8; + else if (conv == 'd' || conv == 'D') + base = 10; + else if (conv == 'x' || conv == 'X') + base = 16; + else + return 0; + + if (*str == '-') + { + neg = 1; + str++; + } + while (*str) + { + if (*str >= '0' && *str < '0'+base) + d = *str - '0'; + else if (base == 16 && *str >= 'a' && *str <= 'f') + d = 10 + *str - 'a'; + else if (base == 16 && *str >= 'A' && *str <= 'F') + d = 10 + *str - 'A'; + else + return 0; + retval = retval*base + d; + str++; + } + if (neg) + retval = -retval; + if (conv == 'D' || conv == 'O' || conv == 'X') + *(long *) val = retval; + else + *val = (int) retval; + return 1; +} +#endif QUICK diff --git a/obsolete/support/undump/undump.1 b/obsolete/support/undump/undump.1 new file mode 100644 index 0000000000..797cdb0377 --- /dev/null +++ b/obsolete/support/undump/undump.1 @@ -0,0 +1,28 @@ +.TH UNDUMP 1 "University of Utah" +.SH NAME +undump \- convert a core dump to an executable a.out file +.SH SYNOPSIS +undump new-a.out-file [old-a.out-file] [core-file] +.SH DESCRIPTION +Undump takes a core dump file and the executable "a.out" file which +caused it and produces a new executable file with all static +variables initialised to the values they held at the time of the +core dump. It is primarily useful for programs which take a long time +to initialise themselves, e.g. Emacs. The idea is to go through all of +the initialisations and then create a core dump (e.g. with the abort() +call). One then uses undump to make a new executable file with all of it +done. This usually implies the use of a global flag variable which says +whether or not initialisation has been done. +.PP +Undump's arguments, old-a.out-file and core-file, default to "a.out" and +"core", respectively. +.PP +A few things to keep in mind about undump: +.IP +It doesn't preserve open files. +.IP +The program will be re-entered at the beginning of main(), not at the point +where the core dump occurred. +.SH BUGS +Probably should have an option to not require +old-a.out-file if the core came from a 407 file. diff --git a/obsolete/support/undump/undump.BALANCE.c b/obsolete/support/undump/undump.BALANCE.c new file mode 100644 index 0000000000..e8bdedec11 --- /dev/null +++ b/obsolete/support/undump/undump.BALANCE.c @@ -0,0 +1,298 @@ +/* + * This program is hacked for Sequent Balance. + * The original is from 4.2undump.c of UNIX TeX distribution. + * This is tested on Serquent Balance 21000, DYNIX 2.1.1 + * with UNIX TeX 2.1. Modification may be necessary for newer DYNIX. + * Takashi Chikayama, ICOT Research Center. + */ + +/* + * This program was advertised on unix-wizards. I have had such a large + * response I'm sending it out to the world. + * + * Here is the source. It works fine under 4.1bsd, I see no fundamental + * reason why it shouldn't work on an 11. (Except possibly small format + * changes in exec header or user structure.) No documentation yet. + * Usage is + * undump new-a.out-file [old-a.out-file] [core-file] + * where old-a.out-file and core-file default to "a.out" and "core", + * respectively. Probably should have an option to not require + * old-a.out-file if the core came from a 407 file. + * + * It doesn't preserve open files, and the program is re-entered at main + * when you run it. It's used locally to dump a lisp and restart it. + * + * It requires a local subroutine called scanargs, somewhat similar to + * getopt (I think). You should be able to easily get around this, though. + * =Spencer + */ + + +/* + * undump.c - Convert a core file to an a.out. + * + * Author: Spencer W. Thomas + * Computer Science Dept. + * University of Utah + * Date: Wed Feb 17 1982 + * Copyright (c) 1982 Spencer W. Thomas + * + * Modification for Balance/DYNIX 2.1.1: + * Takashi Chikayama + * ICOT Research Center + * Date: Wed Nov 25 1987 + * Copyright (c) 1987 Takashi Chikayama + * See copy_text for details. + * + * Usage: + * undump new-a.out [a.out] [core] + */ + +#include <stdio.h> +#include <sys/param.h> +#include <sys/dir.h> +#include <sys/user.h> +#include <sys/stat.h> +#include <a.out.h> + +#define PSIZE 10240 + +struct user u; +struct exec hdr, ohdr; + +main(argc, argv) +char **argv; +{ + char *new_name, *a_out_name = "a.out", *core_name = "core"; + FILE *new, *a_out, *core; + + if (scanargs(argc, argv, "undump new-a.out!s a.out%s core%s", + &new_name, &a_out_name, &core_name) + != 1) + exit(1); + + if ((a_out = fopen(a_out_name, "r")) == NULL) + { + perror(a_out_name); + exit(1); + } + if ((core = fopen(core_name, "r")) == NULL) + { + perror(core_name); + exit(1); + } + if ((new = fopen(new_name, "w")) == NULL) + { + perror(new_name); + exit(1); + } + + read_u(core); + make_hdr(new, a_out); + copy_text(new, a_out); + copy_data(new, core); + copy_sym(new, a_out); + fclose(new); + fclose(core); + fclose(a_out); + mark_x(new_name); +} + +/* + * read the u structure from the core file. + */ +read_u(core) +FILE *core; +{ + if ( fread(&u, sizeof u, 1, core) != 1 ) + { + perror("Couldn't read user structure from core file"); + exit(1); + } +} + +/* + * Make the header in the new a.out from the header in the old one + * modified by the new data size. + */ +make_hdr(new, a_out) +FILE *new, *a_out; +{ + if (fread(&hdr, sizeof hdr, 1, a_out) != 1) + { + perror("Couldn't read header from a.out file"); + exit(1); + } + ohdr = hdr; + if N_BADMAG(hdr) + { + fprintf(stderr, "a.out file doesn't have legal magic number\n"); + exit(1); + } + +/*** Checks are omitted for now. (T.C.) + if (hdr.a_magic != u.u_exdata.ux_mag || + hdr.a_text != u.u_exdata.ux_tsize || + hdr.a_data != u.u_exdata.ux_dsize || + hdr.a_entry != u.u_exdata.ux_entloc) + { + fprintf(stderr, "Core file didn't come from this a.out\n"); + exit(1); + } +***/ + + printf("Data segment size was %u", hdr.a_data); + hdr.a_data = ctob(u.u_dsize); + hdr.a_bss = 0; /* all data is inited now! */ + printf(" now is %u\n", hdr.a_data); + if (fwrite(&hdr, sizeof hdr, 1, new) != 1) + { + perror("Couldn't write header to new a.out file"); + exit(1); + } +} + +/* + * Copy the text from the a.out to the new a.out + */ +copy_text(new, a_out) +FILE *new, *a_out; +{ + char page[PSIZE]; +/* + * Modification by T.C.: + * Text size is actually smaller in files in case of DYNIX. + * As a_text includes exec structure, we avoid overwriting it here. + */ + int txtcnt = hdr.a_text - N_ADDRADJ(hdr) - sizeof(struct exec); + fseek(new, sizeof(struct exec), 0); + fseek(a_out, sizeof(struct exec), 0); + if (hdr.a_magic == OMAGIC) + { + printf("a.out file is not shared text, getting text from core file\n"); + fseek(a_out, hdr.a_text, 1); /* skip over text */ + return; + } + while (txtcnt >= PSIZE) + { + if (fread(page, PSIZE, 1, a_out) != 1) + { + perror("Read failure on a.out text"); + exit(1); + } + if (fwrite(page, PSIZE, 1, new) != 1) + { + perror("Write failure in text segment"); + exit(1); + } + txtcnt -= PSIZE; + } + if (txtcnt) + { + if (fread(page, txtcnt, 1, a_out) != 1) + { + perror("Read failure on a.out text"); + exit(1); + } + if (fwrite(page, txtcnt, 1, new) != 1) + { + perror("Write failure in text segment"); + exit(1); + } + } +} + +/* + * copy the data from the core file to the new a.out + */ +copy_data(new, core) +FILE *new, *core; +{ + char page[PSIZE]; + int datacnt = ctob(u.u_dsize); + + if (hdr.a_magic == OMAGIC) + datacnt += u.u_tsize; + fseek(core, ctob(UPAGES), 0); + while (datacnt >= PSIZE) + { + if (fread(page, PSIZE, 1, core) != 1) + { + perror("Read failure on core data"); + exit(1); + } + if (fwrite(page, PSIZE, 1, new) != 1) + { + perror("Write failure in data segment"); + exit(1); + } + datacnt -= PSIZE; + } + if (datacnt) + { + if (fread(page, datacnt, 1, core) != 1) + { + perror("Read failure on core data"); + exit(1); + } + if (fwrite(page, datacnt, 1, new) != 1) + { + perror("Write failure in data segment"); + exit(1); + } + } +} + +/* + * Copy the relocation information and symbol table from the a.out to the new + */ +copy_sym(new, a_out) +FILE *new, *a_out; +{ + char page[PSIZE]; + int n; + +/* + * Modification by T.C.: + * Use macro N_SYMOFF to compute symbol table offset. + */ + fseek(a_out, N_SYMOFF(ohdr), 0); /* find symbol table */ + while ((n = fread(page, 1, PSIZE, a_out)) > 0) + { + if (fwrite(page, 1, n, new) != n) + { + perror("Error writing symbol table to new a.out"); + fprintf(stderr, "new a.out should be ok otherwise\n"); + return; + } + } + if (n < 0) + { + perror("Error reading symbol table from a.out"); + fprintf(stderr, "new a.out should be ok otherwise\n"); + } +} + +/* + * After succesfully building the new a.out, mark it executable + */ +mark_x(name) +char *name; +{ + struct stat sbuf; + int um; + + um = umask(777); + umask(um); + if (stat(name, &sbuf) == -1) + { + perror ("Can't stat new a.out"); + fprintf(stderr, "Setting protection to %o\n", 0777 & ~um); + sbuf.st_mode = 0777; + } + sbuf.st_mode |= 0111 & ~um; + if (chmod(name, sbuf.st_mode) == -1) + perror("Couldn't change mode of new a.out to executable"); + +} + diff --git a/obsolete/support/undump/undump.PYR.c b/obsolete/support/undump/undump.PYR.c new file mode 100644 index 0000000000..0dd413c77e --- /dev/null +++ b/obsolete/support/undump/undump.PYR.c @@ -0,0 +1,287 @@ +/* + * This program was advertised on unix-wizards. I have had such a large + * response I'm sending it out to the world. + * + * Here is the source. It works fine under 4.1bsd, I see no fundamental + * reason why it shouldn't work on an 11. (Except possibly small format + * changes in exec header or user structure.) No documentation yet. + * Usage is + * undump new-a.out-file [old-a.out-file] [core-file] + * where old-a.out-file and core-file default to "a.out" and "core", + * respectively. Probably should have an option to not require + * old-a.out-file if the core came from a 407 file. + * + * It doesn't preserve open files, and the program is re-entered at main + * when you run it. It's used locally to dump a lisp and restart it. + * + * It requires a local subroutine called scanargs, somewhat similar to + * getopt (I think). You should be able to easily get around this, though. + * =Spencer + * + * Scanargs didn't work on the Pyramid, and its function was + * too simple in this case to bother with repair, so it was chucked. + * -Mike + */ + + +/* + * undump.c - Convert a core file to an a.out. + * + * Author: Spencer W. Thomas + * Computer Science Dept. + * University of Utah + * Date: Wed Feb 17 1982 + * Copyright (c) 1982 Spencer W. Thomas + * + * Usage: + * undump new-a.out [a.out] [core] + */ + +#include <stdio.h> +#include <sys/param.h> +#include <sys/dir.h> +#include <sys/user.h> +#include <sys/stat.h> +#include <a.out.h> + +#define PSIZE 10240 +#define ctob(x) (x<<PGSHIFT) /* Pyramid */ + +struct user u; +struct exec hdr, ohdr; + +main(argc, argv) +char **argv; +{ + char *new_name, *a_out_name = "a.out", *core_name = "core"; + FILE *new, *a_out, *core; + + /*if (scanargs(argc, argv, "undump new-a.out!s a.out%s core%s", + /*&new_name, &a_out_name, &core_name) + /*!= 1) + /*exit(1);*/ + if ((argc > 4)|| (argc < 2)) { + fprintf(stderr, "Usage: %s new-a.out [old-a.out] [core]\n",argv[0]); + exit(1); + } + new_name = argv[1]; + if (argc > 2) a_out_name = argv[2]; + if (argc > 3) core_name = argv[3]; + if ((a_out = fopen(a_out_name, "r")) == NULL) + { + perror(a_out_name); + exit(1); + } + if ((core = fopen(core_name, "r")) == NULL) + { + perror(core_name); + exit(1); + } + if ((new = fopen(new_name, "w")) == NULL) + { + perror(new_name); + exit(1); + } + + read_u(core); + make_hdr(new, a_out); + copy_text(new, a_out); + copy_data(new, core); + copy_sym(new, a_out); + fclose(new); + fclose(core); + fclose(a_out); + mark_x(new_name); +} + +/* + * read the u structure from the core file. + */ +read_u(core) +FILE *core; +{ + if ( fread(&u, sizeof u, 1, core) != 1 ) + { + perror("Couldn't read user structure from core file"); + exit(1); + } +} + +/* + * Make the header in the new a.out from the header in the old one + * modified by the new data size. + */ +make_hdr(new, a_out) +FILE *new, *a_out; +{ + if (fread(&hdr, sizeof hdr, 1, a_out) != 1) + { + perror("Couldn't read header from a.out file"); + exit(1); + } + ohdr = hdr; + if N_BADMAG(hdr) + { + fprintf(stderr, "a.out file doesn't have legal magic number\n"); + exit(1); + } + if (hdr.a_magic != u.u_exdata.ux_mag || + hdr.a_text != u.u_exdata.ux_tsize || + hdr.a_data != u.u_exdata.ux_dsize || + hdr.a_entry != u.u_exdata.ux_entloc) + { + fprintf(stderr, "Core file didn't come from this a.out\n"); +fprintf(stderr, "magic: %o %o", hdr.a_magic, u.u_exdata.ux_mag); +fprintf(stderr, "text: %o %o", hdr.a_text, u.u_exdata.ux_tsize); +fprintf(stderr, "data: %o %o", hdr.a_data, u.u_exdata.ux_dsize); +fprintf(stderr, "entry: %o %o", hdr.a_entry, u.u_exdata.ux_entloc); + exit(1); + } + + printf("Data segment size was %u", hdr.a_data); + hdr.a_data = ctob(u.u_dsize); + hdr.a_bss = 0; /* all data is inited now! */ + printf(" now is %u\n", hdr.a_data); + if (fwrite(&hdr, sizeof hdr, 1, new) != 1) + { + perror("Couldn't write header to new a.out file"); + exit(1); + } +} + +/* + * Copy the text from the a.out to the new a.out + */ +copy_text(new, a_out) +FILE *new, *a_out; +{ + char page[PSIZE]; + int txtcnt = hdr.a_text; + + fseek(new, N_TXTOFF(hdr), 0); + fseek(a_out, N_TXTOFF(hdr), 0); + if (hdr.a_magic == OMAGIC) + { + printf("a.out file is not shared text, getting text from core file\n"); + fseek(a_out, hdr.a_text, 1); /* skip over text */ + return; + } + while (txtcnt >= PSIZE) + { + if (fread(page, PSIZE, 1, a_out) != 1) + { + perror("Read failure on a.out text"); + exit(1); + } + if (fwrite(page, PSIZE, 1, new) != 1) + { + perror("Write failure in text segment"); + exit(1); + } + txtcnt -= PSIZE; + } + if (txtcnt) + { + if (fread(page, txtcnt, 1, a_out) != 1) + { + perror("Read failure on a.out text"); + exit(1); + } + if (fwrite(page, txtcnt, 1, new) != 1) + { + perror("Write failure in text segment"); + exit(1); + } + } +} + +/* + * copy the data from the core file to the new a.out + */ +copy_data(new, core) +FILE *new, *core; +{ + char page[PSIZE]; + int datacnt = ctob(u.u_dsize); + + if (hdr.a_magic == OMAGIC) + datacnt += u.u_tsize; + fseek(core, ctob(UPAGES), 0); + while (datacnt >= PSIZE) + { + if (fread(page, PSIZE, 1, core) != 1) + { + perror("Read failure on core data"); + exit(1); + } + if (fwrite(page, PSIZE, 1, new) != 1) + { + perror("Write failure in data segment"); + exit(1); + } + datacnt -= PSIZE; + } + if (datacnt) + { + if (fread(page, datacnt, 1, core) != 1) + { + perror("Read failure on core data"); + exit(1); + } + if (fwrite(page, datacnt, 1, new) != 1) + { + perror("Write failure in data segment"); + exit(1); + } + } +} + +/* + * Copy the relocation information and symbol table from the a.out to the new + */ +copy_sym(new, a_out) +FILE *new, *a_out; +{ + char page[PSIZE]; + int n; + + fseek(a_out, ohdr.a_data, 1); /* skip over data segment */ + while ((n = fread(page, 1, PSIZE, a_out)) > 0) + { + if (fwrite(page, 1, n, new) != n) + { + perror("Error writing symbol table to new a.out"); + fprintf(stderr, "new a.out should be ok otherwise\n"); + return; + } + } + if (n < 0) + { + perror("Error reading symbol table from a.out"); + fprintf(stderr, "new a.out should be ok otherwise\n"); + } +} + +/* + * After succesfully building the new a.out, mark it executable + */ +mark_x(name) +char *name; +{ + struct stat sbuf; + int um; + + um = umask(777); + umask(um); + if (stat(name, &sbuf) == -1) + { + perror ("Can't stat new a.out"); + fprintf(stderr, "Setting protection to %o\n", 0777 & ~um); + sbuf.st_mode = 0777; + } + sbuf.st_mode |= 0111 & ~um; + if (chmod(name, sbuf.st_mode) == -1) + perror("Couldn't change mode of new a.out to executable"); + +} + diff --git a/obsolete/support/undump/undump.SUN4.c b/obsolete/support/undump/undump.SUN4.c new file mode 100644 index 0000000000..fa518f733b --- /dev/null +++ b/obsolete/support/undump/undump.SUN4.c @@ -0,0 +1,367 @@ +/* + * This program was advertised on unix-wizards. I have had such a large + * response I'm sending it out to the world. + * + * Here is the source. It works fine under 4.1bsd, I see no fundamental + * reason why it shouldn't work on an 11. (Except possibly small format + * changes in exec header or user structure.) No documentation yet. + * Usage is + * undump new-a.out-file [old-a.out-file] [core-file] + * where old-a.out-file and core-file default to "a.out" and "core", + * respectively. Probably should have an option to not require + * old-a.out-file if the core came from a 407 file. + * + * It doesn't preserve open files, and the program is re-entered at main + * when you run it. It's used locally to dump a lisp and restart it. + * + * Other versions of this program required a local subroutine called + * scanargs, which has been eliminated in the SUN4 version. + */ + + +/* + * Barry Shein (BZS@BU-CS.CSNET) - Add SUN/3 changes, tried and + * worked on TeX but not certain about OMAGIC files. Build it + * on a SUN/3 with -Dsun3 on the command line. (1/26/86) + * + * + * This version has applied the patch for a SUN4 contributed by + * Christopher A. Welty (weltyc@nisc.nyser.net). + * It has not been tested, and I do not know what the effect of + * the "#ifdef sun3" lines will be. + * + * Christopher Welty describes the patch as follows, + * + * Here is the quick hack to the SUN 3 undump that I made. The problem is + * that scanargs doesn't use varargs (the Other Unix Text Formatter is + * full of problems like this :-) so I just used brute force... + * + */ + +/* + * undump.c - Convert a core file to an a.out. + * + * Author: Spencer W. Thomas + * Computer Science Dept. + * University of Utah + * Date: Wed Feb 17 1982 + * Copyright (c) 1982 Spencer W. Thomas + * + * Usage: + * undump new-a.out [a.out] [core] + */ + +#include <stdio.h> +#include <sys/param.h> +#include <sys/dir.h> + +#ifdef sun3 +#include <sys/core.h> +#include <machine/param.h> +#else +#include <sys/user.h> +#endif + +#include <sys/stat.h> +#include <a.out.h> + +#ifdef sun3 +#define PSIZE NBPG +#else +#define PSIZE 10240 +#endif sun3 + +#define TEXITUDE + +#ifdef sun3 +struct core c ; +#else +struct user u; +#endif + +struct exec hdr, ohdr; + +main(argc, argv) +char **argv; +{ + char *new_name, *a_out_name = "a.out", *core_name = "core"; + FILE *new, *a_out, *core; + + if ( argc < 2 || argc > 4 ) { + fprintf(stderr, "usage: %s new-a.out [a.out] [core]\n",argv[0]); + exit(1); + } + + new_name = argv[1]; + if ( argc > 2 ) + a_out_name = argv[2]; + if ( argc > 3 ) + core_name = argv[3]; + + if ((a_out = fopen(a_out_name, "r")) == NULL) + { + perror(a_out_name); + exit(1); + } + if ((core = fopen(core_name, "r")) == NULL) + { + perror(core_name); + exit(1); + } + if ((new = fopen(new_name, "w")) == NULL) + { + perror(new_name); + exit(1); + } + +#ifdef sun3 + read_c(core); +#else + read_u(core); +#endif + make_hdr(new, a_out); + copy_text(new, a_out); + copy_data(new, core); + copy_sym(new, a_out); + fclose(new); + fclose(core); + fclose(a_out); + mark_x(new_name); +} + +#ifdef sun3 +read_c(core) FILE *core; +{ + if(fread(&c, sizeof c, 1, core) != 1) { + perror("Couldn't read core header"); + exit(1); + } + if(c.c_magic != CORE_MAGIC) { + fprintf(stderr,"Not a core file\n"); + exit(1); + } +} + +#else +/* + * read the u structure from the core file. + */ +read_u(core) +FILE *core; +{ + if ( fread(&u, sizeof u, 1, core) != 1 ) + { + perror("Couldn't read user structure from core file"); + exit(1); + } +} +#endif sun3 + +/* + * Make the header in the new a.out from the header in the old one + * modified by the new data size. + */ +make_hdr(new, a_out) +FILE *new, *a_out; +{ + if (fread(&hdr, sizeof hdr, 1, a_out) != 1) + { + perror("Couldn't read header from a.out file"); + exit(1); + } + ohdr = hdr; + if N_BADMAG(hdr) + { + fprintf(stderr, "a.out file doesn't have legal magic number\n"); + exit(1); + } +#ifdef sun3 + if (hdr.a_magic != c.c_aouthdr.a_magic || + hdr.a_text != c.c_aouthdr.a_text || + hdr.a_data != c.c_aouthdr.a_data || + hdr.a_entry != c.c_aouthdr.a_entry) +#else + if (hdr.a_magic != u.u_exdata.ux_mag || + hdr.a_text != u.u_exdata.ux_tsize || + hdr.a_data != u.u_exdata.ux_dsize || + hdr.a_entry != u.u_exdata.ux_entloc) +#endif sun3 + { + fprintf(stderr, "Core file didn't come from this a.out\n"); +#ifndef TEXITUDE + exit(1); +#endif + } + + printf("Data segment size was %u", hdr.a_data); +#ifdef sun3 + hdr.a_data = c.c_dsize; +#else + hdr.a_data = ctob(u.u_dsize); +#endif sun3 + hdr.a_bss = 0; /* all data is inited now! */ + printf(" now is %u\n", hdr.a_data); + if (fwrite(&hdr, sizeof hdr, 1, new) != 1) + { + perror("Couldn't write header to new a.out file"); + exit(1); + } +} + +/* + * Copy the text from the a.out to the new a.out + */ +copy_text(new, a_out) +FILE *new, *a_out; +{ + char page[PSIZE]; + int txtcnt = hdr.a_text; + +#ifdef sun3 + fseek(new,(long) N_TXTOFF(hdr)+sizeof(hdr),0); + fseek(a_out,(long) N_TXTOFF(hdr)+sizeof(hdr),0); + txtcnt -= sizeof(hdr); +#else + fseek(new, N_TXTOFF(hdr), 0); + fseek(a_out, N_TXTOFF(hdr), 0); +#endif sun3 + if (hdr.a_magic == OMAGIC) + { + printf("a.out file is not shared text, getting text from core file\n"); + fseek(a_out, hdr.a_text, 1); /* skip over text */ + return; + } + while (txtcnt >= PSIZE) + { + if (fread(page, PSIZE, 1, a_out) != 1) + { + perror("Read failure on a.out text"); + exit(1); + } + if (fwrite(page, PSIZE, 1, new) != 1) + { + perror("Write failure in text segment"); + exit(1); + } + txtcnt -= PSIZE; + } + if (txtcnt) + { + if (fread(page, txtcnt, 1, a_out) != 1) + { + perror("Read failure on a.out text"); + exit(1); + } + if (fwrite(page, txtcnt, 1, new) != 1) + { + perror("Write failure in text segment"); + exit(1); + } + } +} + +/* + * copy the data from the core file to the new a.out + */ +copy_data(new, core) +FILE *new, *core; +{ + char page[PSIZE]; +#ifdef sun3 + int datacnt = c.c_dsize; +#else + int datacnt = ctob(u.u_dsize); +#endif sun3 + + if (hdr.a_magic == OMAGIC) +#ifdef sun3 + datacnt += c.c_tsize; /* BZS - not sure about this */ +#else + datacnt += u.u_tsize; +#endif + +#ifndef sun3 /* for the sun3 the data should be right where we left off */ + fseek(core, ctob(UPAGES), 0); +#endif + while (datacnt >= PSIZE) + { + if (fread(page, PSIZE, 1, core) != 1) + { + perror("Read failure on core data"); + exit(1); + } + if (fwrite(page, PSIZE, 1, new) != 1) + { + perror("Write failure in data segment"); + exit(1); + } + datacnt -= PSIZE; + } + if (datacnt) + { + if (fread(page, datacnt, 1, core) != 1) + { + perror("Read failure on core data"); + exit(1); + } + if (fwrite(page, datacnt, 1, new) != 1) + { + perror("Write failure in data segment"); + exit(1); + } + } +} + +/* + * Copy the relocation information and symbol table from the a.out to the new + */ +copy_sym(new, a_out) +FILE *new, *a_out; +{ + char page[PSIZE]; + int n; + +#ifdef sun3 + fseek(a_out, N_SYMOFF(ohdr), 0); +#else + fseek(a_out, ohdr.a_data, 1); /* skip over data segment */ +#endif sun3 + while ((n = fread(page, 1, PSIZE, a_out)) > 0) + { + if (fwrite(page, 1, n, new) != n) + { + perror("Error writing symbol table to new a.out"); + fprintf(stderr, "new a.out should be ok otherwise\n"); + return; + } + } + if (n < 0) + { + perror("Error reading symbol table from a.out"); + fprintf(stderr, "new a.out should be ok otherwise\n"); + } +} + +/* + * After succesfully building the new a.out, mark it executable + */ +mark_x(name) +char *name; +{ + struct stat sbuf; + int um; + + um = umask(777); + umask(um); + if (stat(name, &sbuf) == -1) + { + perror ("Can't stat new a.out"); + fprintf(stderr, "Setting protection to %o\n", 0777 & ~um); + sbuf.st_mode = 0777; + } + sbuf.st_mode |= 0111 & ~um; + if (chmod(name, sbuf.st_mode) == -1) + perror("Couldn't change mode of new a.out to executable"); + +} + diff --git a/obsolete/support/undump/undump.SUN_V2.c b/obsolete/support/undump/undump.SUN_V2.c new file mode 100644 index 0000000000..ebff8a31f7 --- /dev/null +++ b/obsolete/support/undump/undump.SUN_V2.c @@ -0,0 +1,352 @@ +/* + * This program was advertised on unix-wizards. I have had such a large + * response I'm sending it out to the world. + * + * Here is the source. It works fine under 4.1bsd, I see no fundamental + * reason why it shouldn't work on an 11. (Except possibly small format + * changes in exec header or user structure.) No documentation yet. + * Usage is + * undump new-a.out-file [old-a.out-file] [core-file] + * where old-a.out-file and core-file default to "a.out" and "core", + * respectively. Probably should have an option to not require + * old-a.out-file if the core came from a 407 file. + * + * It doesn't preserve open files, and the program is re-entered at main + * when you run it. It's used locally to dump a lisp and restart it. + * + * It requires a local subroutine called scanargs, somewhat similar to + * getopt (I think). You should be able to easily get around this, though. + * =Spencer + */ + + +/* + * Barry Shein (BZS@BU-CS.CSNET) - Add SUN/3 changes, tried and + * worked on TeX but not certain about OMAGIC files. Build it + * on a SUN/3 with -Dsun3 on the command line. (1/26/86) + * + * + * Believed to work on a Sun2 with O.S. 3.2 as well. If it + * doesn't, try the 4.2undump.c (P. A. MacKay. (2/23/86) + */ +/* + * undump.c - Convert a core file to an a.out. + * + * Author: Spencer W. Thomas + * Computer Science Dept. + * University of Utah + * Date: Wed Feb 17 1982 + * Copyright (c) 1982 Spencer W. Thomas + * + * Usage: + * undump new-a.out [a.out] [core] + */ + +#include <stdio.h> +#include <sys/param.h> +#include <sys/dir.h> + +#ifdef sun3 +#include <sys/core.h> +#include <machine/param.h> +#else +#include <sys/user.h> +#endif + +#include <sys/stat.h> +#include <a.out.h> + +#ifdef sun3 +#define PSIZE NBPG +#else +#define PSIZE 10240 +#endif sun3 + +#define TEXITUDE + +#ifdef sun3 +struct core c ; +#else +struct user u; +#endif + +struct exec hdr, ohdr; + +main(argc, argv) +char **argv; +{ + char *new_name, *a_out_name = "a.out", *core_name = "core"; + FILE *new, *a_out, *core; + + if (scanargs(argc, argv, "undump new-a.out!s a.out%s core%s", + &new_name, &a_out_name, &core_name) + != 1) + exit(1); + + if ((a_out = fopen(a_out_name, "r")) == NULL) + { + perror(a_out_name); + exit(1); + } + if ((core = fopen(core_name, "r")) == NULL) + { + perror(core_name); + exit(1); + } + if ((new = fopen(new_name, "w")) == NULL) + { + perror(new_name); + exit(1); + } + +#ifdef sun3 + read_c(core); +#else + read_u(core); +#endif + make_hdr(new, a_out); + copy_text(new, a_out); + copy_data(new, core); + copy_sym(new, a_out); + fclose(new); + fclose(core); + fclose(a_out); + mark_x(new_name); +} + +#ifdef sun3 +read_c(core) FILE *core; +{ + if(fread(&c, sizeof c, 1, core) != 1) { + perror("Couldn't read core header"); + exit(1); + } + if(c.c_magic != CORE_MAGIC) { + fprintf(stderr,"Not a core file\n"); + exit(1); + } +} + +#else +/* + * read the u structure from the core file. + */ +read_u(core) +FILE *core; +{ + if ( fread(&u, sizeof u, 1, core) != 1 ) + { + perror("Couldn't read user structure from core file"); + exit(1); + } +} +#endif sun3 + +/* + * Make the header in the new a.out from the header in the old one + * modified by the new data size. + */ +make_hdr(new, a_out) +FILE *new, *a_out; +{ + if (fread(&hdr, sizeof hdr, 1, a_out) != 1) + { + perror("Couldn't read header from a.out file"); + exit(1); + } + ohdr = hdr; + if N_BADMAG(hdr) + { + fprintf(stderr, "a.out file doesn't have legal magic number\n"); + exit(1); + } +#ifdef sun3 + if (hdr.a_magic != c.c_aouthdr.a_magic || + hdr.a_text != c.c_aouthdr.a_text || + hdr.a_data != c.c_aouthdr.a_data || + hdr.a_entry != c.c_aouthdr.a_entry) +#else + if (hdr.a_magic != u.u_exdata.ux_mag || + hdr.a_text != u.u_exdata.ux_tsize || + hdr.a_data != u.u_exdata.ux_dsize || + hdr.a_entry != u.u_exdata.ux_entloc) +#endif sun3 + { + fprintf(stderr, "Core file didn't come from this a.out\n"); +#ifndef TEXITUDE + exit(1); +#endif + } + + printf("Data segment size was %u", hdr.a_data); +#ifdef sun3 + hdr.a_data = c.c_dsize; +#else + hdr.a_data = ctob(u.u_dsize); +#endif sun3 + hdr.a_bss = 0; /* all data is inited now! */ + printf(" now is %u\n", hdr.a_data); + if (fwrite(&hdr, sizeof hdr, 1, new) != 1) + { + perror("Couldn't write header to new a.out file"); + exit(1); + } +} + +/* + * Copy the text from the a.out to the new a.out + */ +copy_text(new, a_out) +FILE *new, *a_out; +{ + char page[PSIZE]; + int txtcnt = hdr.a_text; + +#ifdef sun3 + fseek(new,(long) N_TXTOFF(hdr)+sizeof(hdr),0); + fseek(a_out,(long) N_TXTOFF(hdr)+sizeof(hdr),0); + txtcnt -= sizeof(hdr); +#else + fseek(new, N_TXTOFF(hdr), 0); + fseek(a_out, N_TXTOFF(hdr), 0); +#endif sun3 + if (hdr.a_magic == OMAGIC) + { + printf("a.out file is not shared text, getting text from core file\n"); + fseek(a_out, hdr.a_text, 1); /* skip over text */ + return; + } + while (txtcnt >= PSIZE) + { + if (fread(page, PSIZE, 1, a_out) != 1) + { + perror("Read failure on a.out text"); + exit(1); + } + if (fwrite(page, PSIZE, 1, new) != 1) + { + perror("Write failure in text segment"); + exit(1); + } + txtcnt -= PSIZE; + } + if (txtcnt) + { + if (fread(page, txtcnt, 1, a_out) != 1) + { + perror("Read failure on a.out text"); + exit(1); + } + if (fwrite(page, txtcnt, 1, new) != 1) + { + perror("Write failure in text segment"); + exit(1); + } + } +} + +/* + * copy the data from the core file to the new a.out + */ +copy_data(new, core) +FILE *new, *core; +{ + char page[PSIZE]; +#ifdef sun3 + int datacnt = c.c_dsize; +#else + int datacnt = ctob(u.u_dsize); +#endif sun3 + + if (hdr.a_magic == OMAGIC) +#ifdef sun3 + datacnt += c.c_tsize; /* BZS - not sure about this */ +#else + datacnt += u.u_tsize; +#endif + +#ifndef sun3 /* for the sun3 the data should be right where we left off */ + fseek(core, ctob(UPAGES), 0); +#endif + while (datacnt >= PSIZE) + { + if (fread(page, PSIZE, 1, core) != 1) + { + perror("Read failure on core data"); + exit(1); + } + if (fwrite(page, PSIZE, 1, new) != 1) + { + perror("Write failure in data segment"); + exit(1); + } + datacnt -= PSIZE; + } + if (datacnt) + { + if (fread(page, datacnt, 1, core) != 1) + { + perror("Read failure on core data"); + exit(1); + } + if (fwrite(page, datacnt, 1, new) != 1) + { + perror("Write failure in data segment"); + exit(1); + } + } +} + +/* + * Copy the relocation information and symbol table from the a.out to the new + */ +copy_sym(new, a_out) +FILE *new, *a_out; +{ + char page[PSIZE]; + int n; + +#ifdef sun3 + fseek(a_out, N_SYMOFF(ohdr), 0); +#else + fseek(a_out, ohdr.a_data, 1); /* skip over data segment */ +#endif sun3 + while ((n = fread(page, 1, PSIZE, a_out)) > 0) + { + if (fwrite(page, 1, n, new) != n) + { + perror("Error writing symbol table to new a.out"); + fprintf(stderr, "new a.out should be ok otherwise\n"); + return; + } + } + if (n < 0) + { + perror("Error reading symbol table from a.out"); + fprintf(stderr, "new a.out should be ok otherwise\n"); + } +} + +/* + * After succesfully building the new a.out, mark it executable + */ +mark_x(name) +char *name; +{ + struct stat sbuf; + int um; + + um = umask(777); + umask(um); + if (stat(name, &sbuf) == -1) + { + perror ("Can't stat new a.out"); + fprintf(stderr, "Setting protection to %o\n", 0777 & ~um); + sbuf.st_mode = 0777; + } + sbuf.st_mode |= 0111 & ~um; + if (chmod(name, sbuf.st_mode) == -1) + perror("Couldn't change mode of new a.out to executable"); + +} + diff --git a/obsolete/support/undump/undump.SUN_V3 b/obsolete/support/undump/undump.SUN_V3 new file mode 100644 index 0000000000..ebff8a31f7 --- /dev/null +++ b/obsolete/support/undump/undump.SUN_V3 @@ -0,0 +1,352 @@ +/* + * This program was advertised on unix-wizards. I have had such a large + * response I'm sending it out to the world. + * + * Here is the source. It works fine under 4.1bsd, I see no fundamental + * reason why it shouldn't work on an 11. (Except possibly small format + * changes in exec header or user structure.) No documentation yet. + * Usage is + * undump new-a.out-file [old-a.out-file] [core-file] + * where old-a.out-file and core-file default to "a.out" and "core", + * respectively. Probably should have an option to not require + * old-a.out-file if the core came from a 407 file. + * + * It doesn't preserve open files, and the program is re-entered at main + * when you run it. It's used locally to dump a lisp and restart it. + * + * It requires a local subroutine called scanargs, somewhat similar to + * getopt (I think). You should be able to easily get around this, though. + * =Spencer + */ + + +/* + * Barry Shein (BZS@BU-CS.CSNET) - Add SUN/3 changes, tried and + * worked on TeX but not certain about OMAGIC files. Build it + * on a SUN/3 with -Dsun3 on the command line. (1/26/86) + * + * + * Believed to work on a Sun2 with O.S. 3.2 as well. If it + * doesn't, try the 4.2undump.c (P. A. MacKay. (2/23/86) + */ +/* + * undump.c - Convert a core file to an a.out. + * + * Author: Spencer W. Thomas + * Computer Science Dept. + * University of Utah + * Date: Wed Feb 17 1982 + * Copyright (c) 1982 Spencer W. Thomas + * + * Usage: + * undump new-a.out [a.out] [core] + */ + +#include <stdio.h> +#include <sys/param.h> +#include <sys/dir.h> + +#ifdef sun3 +#include <sys/core.h> +#include <machine/param.h> +#else +#include <sys/user.h> +#endif + +#include <sys/stat.h> +#include <a.out.h> + +#ifdef sun3 +#define PSIZE NBPG +#else +#define PSIZE 10240 +#endif sun3 + +#define TEXITUDE + +#ifdef sun3 +struct core c ; +#else +struct user u; +#endif + +struct exec hdr, ohdr; + +main(argc, argv) +char **argv; +{ + char *new_name, *a_out_name = "a.out", *core_name = "core"; + FILE *new, *a_out, *core; + + if (scanargs(argc, argv, "undump new-a.out!s a.out%s core%s", + &new_name, &a_out_name, &core_name) + != 1) + exit(1); + + if ((a_out = fopen(a_out_name, "r")) == NULL) + { + perror(a_out_name); + exit(1); + } + if ((core = fopen(core_name, "r")) == NULL) + { + perror(core_name); + exit(1); + } + if ((new = fopen(new_name, "w")) == NULL) + { + perror(new_name); + exit(1); + } + +#ifdef sun3 + read_c(core); +#else + read_u(core); +#endif + make_hdr(new, a_out); + copy_text(new, a_out); + copy_data(new, core); + copy_sym(new, a_out); + fclose(new); + fclose(core); + fclose(a_out); + mark_x(new_name); +} + +#ifdef sun3 +read_c(core) FILE *core; +{ + if(fread(&c, sizeof c, 1, core) != 1) { + perror("Couldn't read core header"); + exit(1); + } + if(c.c_magic != CORE_MAGIC) { + fprintf(stderr,"Not a core file\n"); + exit(1); + } +} + +#else +/* + * read the u structure from the core file. + */ +read_u(core) +FILE *core; +{ + if ( fread(&u, sizeof u, 1, core) != 1 ) + { + perror("Couldn't read user structure from core file"); + exit(1); + } +} +#endif sun3 + +/* + * Make the header in the new a.out from the header in the old one + * modified by the new data size. + */ +make_hdr(new, a_out) +FILE *new, *a_out; +{ + if (fread(&hdr, sizeof hdr, 1, a_out) != 1) + { + perror("Couldn't read header from a.out file"); + exit(1); + } + ohdr = hdr; + if N_BADMAG(hdr) + { + fprintf(stderr, "a.out file doesn't have legal magic number\n"); + exit(1); + } +#ifdef sun3 + if (hdr.a_magic != c.c_aouthdr.a_magic || + hdr.a_text != c.c_aouthdr.a_text || + hdr.a_data != c.c_aouthdr.a_data || + hdr.a_entry != c.c_aouthdr.a_entry) +#else + if (hdr.a_magic != u.u_exdata.ux_mag || + hdr.a_text != u.u_exdata.ux_tsize || + hdr.a_data != u.u_exdata.ux_dsize || + hdr.a_entry != u.u_exdata.ux_entloc) +#endif sun3 + { + fprintf(stderr, "Core file didn't come from this a.out\n"); +#ifndef TEXITUDE + exit(1); +#endif + } + + printf("Data segment size was %u", hdr.a_data); +#ifdef sun3 + hdr.a_data = c.c_dsize; +#else + hdr.a_data = ctob(u.u_dsize); +#endif sun3 + hdr.a_bss = 0; /* all data is inited now! */ + printf(" now is %u\n", hdr.a_data); + if (fwrite(&hdr, sizeof hdr, 1, new) != 1) + { + perror("Couldn't write header to new a.out file"); + exit(1); + } +} + +/* + * Copy the text from the a.out to the new a.out + */ +copy_text(new, a_out) +FILE *new, *a_out; +{ + char page[PSIZE]; + int txtcnt = hdr.a_text; + +#ifdef sun3 + fseek(new,(long) N_TXTOFF(hdr)+sizeof(hdr),0); + fseek(a_out,(long) N_TXTOFF(hdr)+sizeof(hdr),0); + txtcnt -= sizeof(hdr); +#else + fseek(new, N_TXTOFF(hdr), 0); + fseek(a_out, N_TXTOFF(hdr), 0); +#endif sun3 + if (hdr.a_magic == OMAGIC) + { + printf("a.out file is not shared text, getting text from core file\n"); + fseek(a_out, hdr.a_text, 1); /* skip over text */ + return; + } + while (txtcnt >= PSIZE) + { + if (fread(page, PSIZE, 1, a_out) != 1) + { + perror("Read failure on a.out text"); + exit(1); + } + if (fwrite(page, PSIZE, 1, new) != 1) + { + perror("Write failure in text segment"); + exit(1); + } + txtcnt -= PSIZE; + } + if (txtcnt) + { + if (fread(page, txtcnt, 1, a_out) != 1) + { + perror("Read failure on a.out text"); + exit(1); + } + if (fwrite(page, txtcnt, 1, new) != 1) + { + perror("Write failure in text segment"); + exit(1); + } + } +} + +/* + * copy the data from the core file to the new a.out + */ +copy_data(new, core) +FILE *new, *core; +{ + char page[PSIZE]; +#ifdef sun3 + int datacnt = c.c_dsize; +#else + int datacnt = ctob(u.u_dsize); +#endif sun3 + + if (hdr.a_magic == OMAGIC) +#ifdef sun3 + datacnt += c.c_tsize; /* BZS - not sure about this */ +#else + datacnt += u.u_tsize; +#endif + +#ifndef sun3 /* for the sun3 the data should be right where we left off */ + fseek(core, ctob(UPAGES), 0); +#endif + while (datacnt >= PSIZE) + { + if (fread(page, PSIZE, 1, core) != 1) + { + perror("Read failure on core data"); + exit(1); + } + if (fwrite(page, PSIZE, 1, new) != 1) + { + perror("Write failure in data segment"); + exit(1); + } + datacnt -= PSIZE; + } + if (datacnt) + { + if (fread(page, datacnt, 1, core) != 1) + { + perror("Read failure on core data"); + exit(1); + } + if (fwrite(page, datacnt, 1, new) != 1) + { + perror("Write failure in data segment"); + exit(1); + } + } +} + +/* + * Copy the relocation information and symbol table from the a.out to the new + */ +copy_sym(new, a_out) +FILE *new, *a_out; +{ + char page[PSIZE]; + int n; + +#ifdef sun3 + fseek(a_out, N_SYMOFF(ohdr), 0); +#else + fseek(a_out, ohdr.a_data, 1); /* skip over data segment */ +#endif sun3 + while ((n = fread(page, 1, PSIZE, a_out)) > 0) + { + if (fwrite(page, 1, n, new) != n) + { + perror("Error writing symbol table to new a.out"); + fprintf(stderr, "new a.out should be ok otherwise\n"); + return; + } + } + if (n < 0) + { + perror("Error reading symbol table from a.out"); + fprintf(stderr, "new a.out should be ok otherwise\n"); + } +} + +/* + * After succesfully building the new a.out, mark it executable + */ +mark_x(name) +char *name; +{ + struct stat sbuf; + int um; + + um = umask(777); + umask(um); + if (stat(name, &sbuf) == -1) + { + perror ("Can't stat new a.out"); + fprintf(stderr, "Setting protection to %o\n", 0777 & ~um); + sbuf.st_mode = 0777; + } + sbuf.st_mode |= 0111 & ~um; + if (chmod(name, sbuf.st_mode) == -1) + perror("Couldn't change mode of new a.out to executable"); + +} + diff --git a/obsolete/support/undump/undump.SUN_V3.c b/obsolete/support/undump/undump.SUN_V3.c new file mode 100644 index 0000000000..ebff8a31f7 --- /dev/null +++ b/obsolete/support/undump/undump.SUN_V3.c @@ -0,0 +1,352 @@ +/* + * This program was advertised on unix-wizards. I have had such a large + * response I'm sending it out to the world. + * + * Here is the source. It works fine under 4.1bsd, I see no fundamental + * reason why it shouldn't work on an 11. (Except possibly small format + * changes in exec header or user structure.) No documentation yet. + * Usage is + * undump new-a.out-file [old-a.out-file] [core-file] + * where old-a.out-file and core-file default to "a.out" and "core", + * respectively. Probably should have an option to not require + * old-a.out-file if the core came from a 407 file. + * + * It doesn't preserve open files, and the program is re-entered at main + * when you run it. It's used locally to dump a lisp and restart it. + * + * It requires a local subroutine called scanargs, somewhat similar to + * getopt (I think). You should be able to easily get around this, though. + * =Spencer + */ + + +/* + * Barry Shein (BZS@BU-CS.CSNET) - Add SUN/3 changes, tried and + * worked on TeX but not certain about OMAGIC files. Build it + * on a SUN/3 with -Dsun3 on the command line. (1/26/86) + * + * + * Believed to work on a Sun2 with O.S. 3.2 as well. If it + * doesn't, try the 4.2undump.c (P. A. MacKay. (2/23/86) + */ +/* + * undump.c - Convert a core file to an a.out. + * + * Author: Spencer W. Thomas + * Computer Science Dept. + * University of Utah + * Date: Wed Feb 17 1982 + * Copyright (c) 1982 Spencer W. Thomas + * + * Usage: + * undump new-a.out [a.out] [core] + */ + +#include <stdio.h> +#include <sys/param.h> +#include <sys/dir.h> + +#ifdef sun3 +#include <sys/core.h> +#include <machine/param.h> +#else +#include <sys/user.h> +#endif + +#include <sys/stat.h> +#include <a.out.h> + +#ifdef sun3 +#define PSIZE NBPG +#else +#define PSIZE 10240 +#endif sun3 + +#define TEXITUDE + +#ifdef sun3 +struct core c ; +#else +struct user u; +#endif + +struct exec hdr, ohdr; + +main(argc, argv) +char **argv; +{ + char *new_name, *a_out_name = "a.out", *core_name = "core"; + FILE *new, *a_out, *core; + + if (scanargs(argc, argv, "undump new-a.out!s a.out%s core%s", + &new_name, &a_out_name, &core_name) + != 1) + exit(1); + + if ((a_out = fopen(a_out_name, "r")) == NULL) + { + perror(a_out_name); + exit(1); + } + if ((core = fopen(core_name, "r")) == NULL) + { + perror(core_name); + exit(1); + } + if ((new = fopen(new_name, "w")) == NULL) + { + perror(new_name); + exit(1); + } + +#ifdef sun3 + read_c(core); +#else + read_u(core); +#endif + make_hdr(new, a_out); + copy_text(new, a_out); + copy_data(new, core); + copy_sym(new, a_out); + fclose(new); + fclose(core); + fclose(a_out); + mark_x(new_name); +} + +#ifdef sun3 +read_c(core) FILE *core; +{ + if(fread(&c, sizeof c, 1, core) != 1) { + perror("Couldn't read core header"); + exit(1); + } + if(c.c_magic != CORE_MAGIC) { + fprintf(stderr,"Not a core file\n"); + exit(1); + } +} + +#else +/* + * read the u structure from the core file. + */ +read_u(core) +FILE *core; +{ + if ( fread(&u, sizeof u, 1, core) != 1 ) + { + perror("Couldn't read user structure from core file"); + exit(1); + } +} +#endif sun3 + +/* + * Make the header in the new a.out from the header in the old one + * modified by the new data size. + */ +make_hdr(new, a_out) +FILE *new, *a_out; +{ + if (fread(&hdr, sizeof hdr, 1, a_out) != 1) + { + perror("Couldn't read header from a.out file"); + exit(1); + } + ohdr = hdr; + if N_BADMAG(hdr) + { + fprintf(stderr, "a.out file doesn't have legal magic number\n"); + exit(1); + } +#ifdef sun3 + if (hdr.a_magic != c.c_aouthdr.a_magic || + hdr.a_text != c.c_aouthdr.a_text || + hdr.a_data != c.c_aouthdr.a_data || + hdr.a_entry != c.c_aouthdr.a_entry) +#else + if (hdr.a_magic != u.u_exdata.ux_mag || + hdr.a_text != u.u_exdata.ux_tsize || + hdr.a_data != u.u_exdata.ux_dsize || + hdr.a_entry != u.u_exdata.ux_entloc) +#endif sun3 + { + fprintf(stderr, "Core file didn't come from this a.out\n"); +#ifndef TEXITUDE + exit(1); +#endif + } + + printf("Data segment size was %u", hdr.a_data); +#ifdef sun3 + hdr.a_data = c.c_dsize; +#else + hdr.a_data = ctob(u.u_dsize); +#endif sun3 + hdr.a_bss = 0; /* all data is inited now! */ + printf(" now is %u\n", hdr.a_data); + if (fwrite(&hdr, sizeof hdr, 1, new) != 1) + { + perror("Couldn't write header to new a.out file"); + exit(1); + } +} + +/* + * Copy the text from the a.out to the new a.out + */ +copy_text(new, a_out) +FILE *new, *a_out; +{ + char page[PSIZE]; + int txtcnt = hdr.a_text; + +#ifdef sun3 + fseek(new,(long) N_TXTOFF(hdr)+sizeof(hdr),0); + fseek(a_out,(long) N_TXTOFF(hdr)+sizeof(hdr),0); + txtcnt -= sizeof(hdr); +#else + fseek(new, N_TXTOFF(hdr), 0); + fseek(a_out, N_TXTOFF(hdr), 0); +#endif sun3 + if (hdr.a_magic == OMAGIC) + { + printf("a.out file is not shared text, getting text from core file\n"); + fseek(a_out, hdr.a_text, 1); /* skip over text */ + return; + } + while (txtcnt >= PSIZE) + { + if (fread(page, PSIZE, 1, a_out) != 1) + { + perror("Read failure on a.out text"); + exit(1); + } + if (fwrite(page, PSIZE, 1, new) != 1) + { + perror("Write failure in text segment"); + exit(1); + } + txtcnt -= PSIZE; + } + if (txtcnt) + { + if (fread(page, txtcnt, 1, a_out) != 1) + { + perror("Read failure on a.out text"); + exit(1); + } + if (fwrite(page, txtcnt, 1, new) != 1) + { + perror("Write failure in text segment"); + exit(1); + } + } +} + +/* + * copy the data from the core file to the new a.out + */ +copy_data(new, core) +FILE *new, *core; +{ + char page[PSIZE]; +#ifdef sun3 + int datacnt = c.c_dsize; +#else + int datacnt = ctob(u.u_dsize); +#endif sun3 + + if (hdr.a_magic == OMAGIC) +#ifdef sun3 + datacnt += c.c_tsize; /* BZS - not sure about this */ +#else + datacnt += u.u_tsize; +#endif + +#ifndef sun3 /* for the sun3 the data should be right where we left off */ + fseek(core, ctob(UPAGES), 0); +#endif + while (datacnt >= PSIZE) + { + if (fread(page, PSIZE, 1, core) != 1) + { + perror("Read failure on core data"); + exit(1); + } + if (fwrite(page, PSIZE, 1, new) != 1) + { + perror("Write failure in data segment"); + exit(1); + } + datacnt -= PSIZE; + } + if (datacnt) + { + if (fread(page, datacnt, 1, core) != 1) + { + perror("Read failure on core data"); + exit(1); + } + if (fwrite(page, datacnt, 1, new) != 1) + { + perror("Write failure in data segment"); + exit(1); + } + } +} + +/* + * Copy the relocation information and symbol table from the a.out to the new + */ +copy_sym(new, a_out) +FILE *new, *a_out; +{ + char page[PSIZE]; + int n; + +#ifdef sun3 + fseek(a_out, N_SYMOFF(ohdr), 0); +#else + fseek(a_out, ohdr.a_data, 1); /* skip over data segment */ +#endif sun3 + while ((n = fread(page, 1, PSIZE, a_out)) > 0) + { + if (fwrite(page, 1, n, new) != n) + { + perror("Error writing symbol table to new a.out"); + fprintf(stderr, "new a.out should be ok otherwise\n"); + return; + } + } + if (n < 0) + { + perror("Error reading symbol table from a.out"); + fprintf(stderr, "new a.out should be ok otherwise\n"); + } +} + +/* + * After succesfully building the new a.out, mark it executable + */ +mark_x(name) +char *name; +{ + struct stat sbuf; + int um; + + um = umask(777); + umask(um); + if (stat(name, &sbuf) == -1) + { + perror ("Can't stat new a.out"); + fprintf(stderr, "Setting protection to %o\n", 0777 & ~um); + sbuf.st_mode = 0777; + } + sbuf.st_mode |= 0111 & ~um; + if (chmod(name, sbuf.st_mode) == -1) + perror("Couldn't change mode of new a.out to executable"); + +} + diff --git a/obsolete/support/undump/undump.SYS_V.c b/obsolete/support/undump/undump.SYS_V.c new file mode 100644 index 0000000000..8d61cb61ee --- /dev/null +++ b/obsolete/support/undump/undump.SYS_V.c @@ -0,0 +1,250 @@ +/* + * undump - resurrect a core file into a running program. + * + * for UNIX System V on a 3Bx + * that uses the Common Object File Format + * + * Author: + * Lou Salkind + * New York University + * Tue Mar 3 13:18:25 EST 1987 + * + * Adapted from: + * Spencer Thomas's undump and the file unexec.c in GNU emacs + */ + +#include <sys/param.h> +#include <sys/types.h> +#include <sys/psw.h> +#include <sys/pcb.h> +#include <sys/signal.h> +#include <sys/fs/s5dir.h> +#include <sys/user.h> + +#include <stdio.h> +#include <sys/stat.h> + +#include <aouthdr.h> +#include <filehdr.h> +#include <scnhdr.h> +#include <syms.h> + +#define PAGE_SIZE NBPC + +struct filehdr fh; +AOUTHDR aout; +struct scnhdr tsc; +struct scnhdr dsc; +struct scnhdr bsc; + +long bias; +long lnnoptr; +long text_scnptr; +long data_scnptr; +long symlocptr; + +main(argc, argv) + char **argv; +{ + FILE *afp, *cfp, *nfp; + struct user u; + long off; + long size; + struct scnhdr sc; + int i, n; + char *a_out_name = "a.out"; + char *core_name = "core"; + char *new_name; + + if (argc < 2 || argc > 4) { + fprintf(stderr, "usage: %s new [a.out [core]]\n", argv[0]); + exit(1); + } + new_name = argv[1]; + if (argc > 2) + a_out_name = argv[2]; + if (argc > 3) + core_name = argv[3]; + afp = fopen(a_out_name, "r"); + if (afp == 0) + Perror(a_out_name); + cfp = fopen(core_name, "r"); + if (cfp == 0) + Perror(core_name); + nfp = fopen(new_name, "w"); + if (nfp == 0) + Perror(new_name); + + if (fread(&fh, sizeof fh, 1, afp) != 1) + Perror("fh read"); + if (fread(&aout, sizeof aout, 1, afp) != 1) + Perror("aout read"); + + for (i = 0; i < fh.f_nscns; i++) { + if (fread(&sc, sizeof(sc), 1, afp) != 1) + Perror("read"); + if (strcmp(sc.s_name, ".text") == 0) { + tsc = sc; + } else if (strcmp(sc.s_name, ".data") == 0) { + dsc = sc; + } else if (strcmp(sc.s_name, ".bss") == 0) { + bsc = sc; + } + } + + if (fread(&u, sizeof u, 1, cfp) != 1) + Perror("core read"); + if (u.u_exdata.ux_tsize != aout.tsize || + u.u_exdata.ux_dsize != aout.dsize || + u.u_exdata.ux_bsize != aout.bsize) { + fprintf("mismatch between %s and %s sizes\n", a_out_name, core_name); + exit(1); + } + + off = USIZE*PAGE_SIZE; + size = u.u_dsize *PAGE_SIZE; + + fh.f_flags |= F_RELFLG | F_EXEC; + aout.dsize = size; + aout.bsize = 0; + tsc.s_size = aout.tsize; + tsc.s_scnptr = sizeof(fh) + sizeof(aout); + tsc.s_scnptr += fh.f_nscns * sizeof (struct scnhdr); + text_scnptr = tsc.s_scnptr; + lnnoptr = tsc.s_lnnoptr; + symlocptr = fh.f_symptr; + + dsc.s_paddr = dsc.s_vaddr = aout.data_start; + dsc.s_size = aout.dsize; + dsc.s_scnptr = tsc.s_scnptr + tsc.s_size; + data_scnptr = dsc.s_scnptr; + + bsc.s_paddr = bsc.s_vaddr = aout.data_start + aout.dsize; + bsc.s_size = aout.bsize; + bsc.s_scnptr = 0L; + bias = dsc.s_scnptr + dsc.s_size - lnnoptr; + + if (fh.f_symptr > 0L) + fh.f_symptr += bias; + if (tsc.s_lnnoptr > 0L) + tsc.s_lnnoptr += bias; + + if (fwrite(&fh, sizeof(fh), 1, nfp) != 1) + Perror("fh write"); + if (fwrite(&aout, sizeof(aout), 1, nfp) != 1) + Perror("aout write"); + if (fwrite(&tsc, sizeof(tsc), 1, nfp) != 1) + Perror("ts write"); + if (fwrite(&dsc, sizeof(dsc), 1, nfp) != 1) + Perror("ds write"); + if (fwrite(&bsc, sizeof(bsc), 1, nfp) != 1) + Perror("bs write"); + fseek(nfp, (long)text_scnptr, 0); + copy(afp, nfp, aout.tsize); + fseek(cfp, off, 0); + fseek(nfp, (long)data_scnptr, 0); + copy(cfp, nfp, size); + copy_syms(afp, nfp); + fclose(nfp); + fclose(afp); + fclose(cfp); + mark_x(new_name); + exit(0); +} + +copy_syms(afp, nfp) + register FILE *afp, *nfp; +{ + char page[BUFSIZ]; + register int n; + register int nsyms; + struct syment symentry; + AUXENT auxentry; + + /* if there are line numbers, copy them */ + if (lnnoptr) { + if (fseek(afp, lnnoptr, 0) == -1L) + Perror("ln fseek"); + copy(afp, nfp, symlocptr - lnnoptr); + } + + /* now write the symbol table */ + if (fseek(nfp, fh.f_symptr, 0) == -1L) + Perror("fh fseek"); + for (nsyms = 0; nsyms < fh.f_nsyms; nsyms++) { + if (fread(&symentry, SYMESZ, 1, afp) != 1) + Perror("sym fread"); + if (fwrite(&symentry, SYMESZ, 1, nfp) != 1) + Perror("sym fwrite"); + /* + * adjust relative offsets of line numbers for + * function definitions + */ + if (symentry.n_numaux) { + if (fread(&auxentry, AUXESZ, 1, afp) != 1) + Perror("aux fread"); + nsyms++; + if (ISFCN (symentry.n_type)) + auxentry.x_sym.x_fcnary.x_fcn.x_lnnoptr += bias; + if (fwrite(&auxentry, AUXESZ, 1, nfp) != 1) + Perror("aux fwrite"); + } + } + + /* finally write the string table, if any */ + while ((n = fread(page, 1, sizeof page, afp)) > 0) { + if (fwrite(page, 1, n, nfp) != n) + Perror("sym write"); + } + if (n < 0) + Perror("sym read"); +} + +/* + * After succesfully building the new a.out, mark it executable + */ +mark_x(name) +char *name; +{ + struct stat sbuf; + int um; + + um = umask(777); + umask(um); + if (stat(name, &sbuf) == -1) + { + perror ("Can't stat new a.out"); + fprintf(stderr, "Setting protection to %o\n", 0777 & ~um); + sbuf.st_mode = 0777; + } + sbuf.st_mode |= 0111 & ~um; + if (chmod(name, sbuf.st_mode) == -1) + perror("Couldn't change mode of new a.out to executable"); + +} + +copy(a, b, size) + register FILE *a, *b; + long size; +{ + char buf[BUFSIZ]; + register int i, n; + + while (size > 0) { + i = size; + if (i > sizeof buf) + i = sizeof buf; + if ((n = fread(buf, 1, i, a)) <= 0) + Perror("copy read"); + if (fwrite(buf, 1, n, b) != n) + Perror("copy write"); + size -= n; + } +} + +Perror(s) + char *s; +{ + perror(s); + exit(1); +} diff --git a/obsolete/support/undump/undump.VAX4_2.c b/obsolete/support/undump/undump.VAX4_2.c new file mode 100644 index 0000000000..f5588abf6e --- /dev/null +++ b/obsolete/support/undump/undump.VAX4_2.c @@ -0,0 +1,272 @@ +/* + * This program was advertised on unix-wizards. I have had such a large + * response I'm sending it out to the world. + * + * Here is the source. It works fine under 4.1bsd, I see no fundamental + * reason why it shouldn't work on an 11. (Except possibly small format + * changes in exec header or user structure.) No documentation yet. + * Usage is + * undump new-a.out-file [old-a.out-file] [core-file] + * where old-a.out-file and core-file default to "a.out" and "core", + * respectively. Probably should have an option to not require + * old-a.out-file if the core came from a 407 file. + * + * It doesn't preserve open files, and the program is re-entered at main + * when you run it. It's used locally to dump a lisp and restart it. + * + * It requires a local subroutine called scanargs, somewhat similar to + * getopt (I think). You should be able to easily get around this, though. + * =Spencer + */ + + +/* + * undump.c - Convert a core file to an a.out. + * + * Author: Spencer W. Thomas + * Computer Science Dept. + * University of Utah + * Date: Wed Feb 17 1982 + * Copyright (c) 1982 Spencer W. Thomas + * + * Usage: + * undump new-a.out [a.out] [core] + */ + +#include <stdio.h> +#include <sys/param.h> +#include <sys/dir.h> +#include <sys/user.h> +#include <sys/stat.h> +#include <a.out.h> + +#define PSIZE 10240 + +struct user u; +struct exec hdr, ohdr; + +main(argc, argv) +char **argv; +{ + char *new_name, *a_out_name = "a.out", *core_name = "core"; + FILE *new, *a_out, *core; + + if (scanargs(argc, argv, "undump new-a.out!s a.out%s core%s", + &new_name, &a_out_name, &core_name) + != 1) + exit(1); + + if ((a_out = fopen(a_out_name, "r")) == NULL) + { + perror(a_out_name); + exit(1); + } + if ((core = fopen(core_name, "r")) == NULL) + { + perror(core_name); + exit(1); + } + if ((new = fopen(new_name, "w")) == NULL) + { + perror(new_name); + exit(1); + } + + read_u(core); + make_hdr(new, a_out); + copy_text(new, a_out); + copy_data(new, core); + copy_sym(new, a_out); + fclose(new); + fclose(core); + fclose(a_out); + mark_x(new_name); +} + +/* + * read the u structure from the core file. + */ +read_u(core) +FILE *core; +{ + if ( fread(&u, sizeof u, 1, core) != 1 ) + { + perror("Couldn't read user structure from core file"); + exit(1); + } +} + +/* + * Make the header in the new a.out from the header in the old one + * modified by the new data size. + */ +make_hdr(new, a_out) +FILE *new, *a_out; +{ + if (fread(&hdr, sizeof hdr, 1, a_out) != 1) + { + perror("Couldn't read header from a.out file"); + exit(1); + } + ohdr = hdr; + if N_BADMAG(hdr) + { + fprintf(stderr, "a.out file doesn't have legal magic number\n"); + exit(1); + } + if (hdr.a_magic != u.u_exdata.ux_mag || + hdr.a_text != u.u_exdata.ux_tsize || + hdr.a_data != u.u_exdata.ux_dsize || + hdr.a_entry != u.u_exdata.ux_entloc) + { + fprintf(stderr, "Core file didn't come from this a.out\n"); + exit(1); + } + + printf("Data segment size was %u", hdr.a_data); + hdr.a_data = ctob(u.u_dsize); + hdr.a_bss = 0; /* all data is inited now! */ + printf(" now is %u\n", hdr.a_data); + if (fwrite(&hdr, sizeof hdr, 1, new) != 1) + { + perror("Couldn't write header to new a.out file"); + exit(1); + } +} + +/* + * Copy the text from the a.out to the new a.out + */ +copy_text(new, a_out) +FILE *new, *a_out; +{ + char page[PSIZE]; + int txtcnt = hdr.a_text; + + fseek(new, N_TXTOFF(hdr), 0); + fseek(a_out, N_TXTOFF(hdr), 0); + if (hdr.a_magic == OMAGIC) + { + printf("a.out file is not shared text, getting text from core file\n"); + fseek(a_out, hdr.a_text, 1); /* skip over text */ + return; + } + while (txtcnt >= PSIZE) + { + if (fread(page, PSIZE, 1, a_out) != 1) + { + perror("Read failure on a.out text"); + exit(1); + } + if (fwrite(page, PSIZE, 1, new) != 1) + { + perror("Write failure in text segment"); + exit(1); + } + txtcnt -= PSIZE; + } + if (txtcnt) + { + if (fread(page, txtcnt, 1, a_out) != 1) + { + perror("Read failure on a.out text"); + exit(1); + } + if (fwrite(page, txtcnt, 1, new) != 1) + { + perror("Write failure in text segment"); + exit(1); + } + } +} + +/* + * copy the data from the core file to the new a.out + */ +copy_data(new, core) +FILE *new, *core; +{ + char page[PSIZE]; + int datacnt = ctob(u.u_dsize); + + if (hdr.a_magic == OMAGIC) + datacnt += u.u_tsize; + fseek(core, ctob(UPAGES), 0); + while (datacnt >= PSIZE) + { + if (fread(page, PSIZE, 1, core) != 1) + { + perror("Read failure on core data"); + exit(1); + } + if (fwrite(page, PSIZE, 1, new) != 1) + { + perror("Write failure in data segment"); + exit(1); + } + datacnt -= PSIZE; + } + if (datacnt) + { + if (fread(page, datacnt, 1, core) != 1) + { + perror("Read failure on core data"); + exit(1); + } + if (fwrite(page, datacnt, 1, new) != 1) + { + perror("Write failure in data segment"); + exit(1); + } + } +} + +/* + * Copy the relocation information and symbol table from the a.out to the new + */ +copy_sym(new, a_out) +FILE *new, *a_out; +{ + char page[PSIZE]; + int n; + + fseek(a_out, ohdr.a_data, 1); /* skip over data segment */ + while ((n = fread(page, 1, PSIZE, a_out)) > 0) + { + if (fwrite(page, 1, n, new) != n) + { + perror("Error writing symbol table to new a.out"); + fprintf(stderr, "new a.out should be ok otherwise\n"); + return; + } + } + if (n < 0) + { + perror("Error reading symbol table from a.out"); + fprintf(stderr, "new a.out should be ok otherwise\n"); + } +} + +/* + * After succesfully building the new a.out, mark it executable + */ +mark_x(name) +char *name; +{ + struct stat sbuf; + int um; + + um = umask(777); + umask(um); + if (stat(name, &sbuf) == -1) + { + perror ("Can't stat new a.out"); + fprintf(stderr, "Setting protection to %o\n", 0777 & ~um); + sbuf.st_mode = 0777; + } + sbuf.st_mode |= 0111 & ~um; + if (chmod(name, sbuf.st_mode) == -1) + perror("Couldn't change mode of new a.out to executable"); + +} + diff --git a/obsolete/support/undump/undump.VAX4_3.c b/obsolete/support/undump/undump.VAX4_3.c new file mode 100644 index 0000000000..19fe9315bb --- /dev/null +++ b/obsolete/support/undump/undump.VAX4_3.c @@ -0,0 +1,264 @@ +/* + * This program was advertised on unix-wizards. I have had such a large + * response I'm sending it out to the world. + * + * Here is the source. It works fine under 4.1bsd, I see no fundamental + * reason why it shouldn't work on an 11. (Except possibly small format + * changes in exec header or user structure.) No documentation yet. + * Usage is + * undump new-a.out-file [old-a.out-file] [core-file] + * where old-a.out-file and core-file default to "a.out" and "core", + * respectively. Probably should have an option to not require + * old-a.out-file if the core came from a 407 file. + * + * It doesn't preserve open files, and the program is re-entered at main + * when you run it. It's used locally to dump a lisp and restart it. + * + * It requires a local subroutine called scanargs, somewhat similar to + * getopt (I think). You should be able to easily get around this, though. + * =Spencer + */ + + +/* + * undump.c - Convert a core file to an a.out. + * + * Author: Spencer W. Thomas + * Computer Science Dept. + * University of Utah + * Date: Wed Feb 17 1982 + * Copyright (c) 1982 Spencer W. Thomas + * + * Usage: + * undump new-a.out [a.out] [core] + */ + +#include <stdio.h> +#include <sys/param.h> +#include <sys/dir.h> +#include <sys/user.h> +#include <sys/stat.h> +#include <a.out.h> + +#define PSIZE 10240 + +struct user u; +struct exec hdr, ohdr; + +main(argc, argv) +char **argv; +{ + char *new_name, *a_out_name = "a.out", *core_name = "core"; + FILE *new, *a_out, *core; + + if (scanargs(argc, argv, "undump new-a.out!s a.out%s core%s", + &new_name, &a_out_name, &core_name) + != 1) + exit(1); + + if ((a_out = fopen(a_out_name, "r")) == NULL) + { + perror(a_out_name); + exit(1); + } + if ((core = fopen(core_name, "r")) == NULL) + { + perror(core_name); + exit(1); + } + if ((new = fopen(new_name, "w")) == NULL) + { + perror(new_name); + exit(1); + } + + read_u(core); + make_hdr(new, a_out); + copy_text(new, a_out); + copy_data(new, core); + copy_sym(new, a_out); + fclose(new); + fclose(core); + fclose(a_out); + mark_x(new_name); +} + +/* + * read the u structure from the core file. + */ +read_u(core) +FILE *core; +{ + if ( fread(&u, sizeof u, 1, core) != 1 ) + { + perror("Couldn't read user structure from core file"); + exit(1); + } +} + +/* + * Make the header in the new a.out from the header in the old one + * modified by the new data size. + */ +make_hdr(new, a_out) +FILE *new, *a_out; +{ + if (fread(&hdr, sizeof hdr, 1, a_out) != 1) + { + perror("Couldn't read header from a.out file"); + exit(1); + } + ohdr = hdr; + if N_BADMAG(hdr) + { + fprintf(stderr, "a.out file doesn't have legal magic number\n"); + exit(1); + } + + printf("Data segment size was %u", hdr.a_data); + hdr.a_data = ctob(u.u_dsize); + hdr.a_bss = 0; /* all data is inited now! */ + printf(" now is %u\n", hdr.a_data); + if (fwrite(&hdr, sizeof hdr, 1, new) != 1) + { + perror("Couldn't write header to new a.out file"); + exit(1); + } +} + +/* + * Copy the text from the a.out to the new a.out + */ +copy_text(new, a_out) +FILE *new, *a_out; +{ + char page[PSIZE]; + int txtcnt = hdr.a_text; + + fseek(new, N_TXTOFF(hdr), 0); + fseek(a_out, N_TXTOFF(hdr), 0); + if (hdr.a_magic == OMAGIC) + { + printf("a.out file is not shared text, getting text from core file\n"); + fseek(a_out, hdr.a_text, 1); /* skip over text */ + return; + } + while (txtcnt >= PSIZE) + { + if (fread(page, PSIZE, 1, a_out) != 1) + { + perror("Read failure on a.out text"); + exit(1); + } + if (fwrite(page, PSIZE, 1, new) != 1) + { + perror("Write failure in text segment"); + exit(1); + } + txtcnt -= PSIZE; + } + if (txtcnt) + { + if (fread(page, txtcnt, 1, a_out) != 1) + { + perror("Read failure on a.out text"); + exit(1); + } + if (fwrite(page, txtcnt, 1, new) != 1) + { + perror("Write failure in text segment"); + exit(1); + } + } +} + +/* + * copy the data from the core file to the new a.out + */ +copy_data(new, core) +FILE *new, *core; +{ + char page[PSIZE]; + int datacnt = ctob(u.u_dsize); + + if (hdr.a_magic == OMAGIC) + datacnt += u.u_tsize; + fseek(core, ctob(UPAGES), 0); + while (datacnt >= PSIZE) + { + if (fread(page, PSIZE, 1, core) != 1) + { + perror("Read failure on core data"); + exit(1); + } + if (fwrite(page, PSIZE, 1, new) != 1) + { + perror("Write failure in data segment"); + exit(1); + } + datacnt -= PSIZE; + } + if (datacnt) + { + if (fread(page, datacnt, 1, core) != 1) + { + perror("Read failure on core data"); + exit(1); + } + if (fwrite(page, datacnt, 1, new) != 1) + { + perror("Write failure in data segment"); + exit(1); + } + } +} + +/* + * Copy the relocation information and symbol table from the a.out to the new + */ +copy_sym(new, a_out) +FILE *new, *a_out; +{ + char page[PSIZE]; + int n; + + fseek(a_out, ohdr.a_data, 1); /* skip over data segment */ + while ((n = fread(page, 1, PSIZE, a_out)) > 0) + { + if (fwrite(page, 1, n, new) != n) + { + perror("Error writing symbol table to new a.out"); + fprintf(stderr, "new a.out should be ok otherwise\n"); + return; + } + } + if (n < 0) + { + perror("Error reading symbol table from a.out"); + fprintf(stderr, "new a.out should be ok otherwise\n"); + } +} + +/* + * After succesfully building the new a.out, mark it executable + */ +mark_x(name) +char *name; +{ + struct stat sbuf; + int um; + + um = umask(777); + umask(um); + if (stat(name, &sbuf) == -1) + { + perror ("Can't stat new a.out"); + fprintf(stderr, "Setting protection to %o\n", 0777 & ~um); + sbuf.st_mode = 0777; + } + sbuf.st_mode |= 0111 & ~um; + if (chmod(name, sbuf.st_mode) == -1) + perror("Couldn't change mode of new a.out to executable"); + +} + |