This is stubedit.c in view mode; [Download] [Up]
/* This is file STUBEDIT.C */ /* ** Copyright (C) 1993 DJ Delorie, 24 Kirsten Ave, Rochester NH 03867-2954 ** ** This file is distributed under the terms listed in the document ** "copying.dj", available from DJ Delorie at the address above. ** A copy of "copying.dj" should accompany this file; if not, a copy ** should be available from where this file was obtained. This file ** may not be distributed without a verbatim copy of "copying.dj". ** ** This file is distributed WITHOUT ANY WARRANTY; without even the implied ** warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. */ #include <stdio.h> #include <stdlib.h> #include <string.h> #include <io.h> #include <fcntl.h> #include "gotypes.h" #include "stubinfo.h" word32 offset_of_info = 0; word32 size_of_info = 0; StubInfo stub_info = { STUB_INFO_MAGIC }; char *key = stub_info.magic; void find_info(char *filename) { FILE *f; int ch, found = 0; int key_p; long key_max, key_cnt=0; unsigned char header[6]; unsigned char test_magic[16]; f = fopen(filename, "rb"); if (f == 0) { char buf[100]; sprintf(buf, "Fatal error in stubedit reading %s", filename); perror(buf); exit(1); } fread(header, 6, 1, f); key_max = header[4] + header[5]*256 + 1; key_max *= 512; /* First, look for tag */ fseek(f, -4L, 2); fread(test_magic, 4, 1, f); offset_of_info = (test_magic[0]) | (test_magic[1] << 8) | (test_magic[2] << 16) | (test_magic[3] << 24); if (offset_of_info > 0 && offset_of_info < key_max) { fseek(f, offset_of_info, 0); fread(test_magic, 16, 1, f); if (strcmp((char *)test_magic, key) == 0) found = 1; } if (!found) { fseek(f, 0L, 0); key_p = 0; while ((ch = fgetc(f)) != EOF) { if (ch == key[key_p]) { key_p++; if (key[key_p] == 0) { fgetc(f); /* the NULL */ offset_of_info = ftell(f) - 16; /* skip the NULL in the file */ found = 1; break; } } else key_p = 0; key_cnt++; if (key_cnt > key_max) break; } } if (!found) { fprintf(stderr, "Error: I cannot find the stub info structure. Must be either\n"); fprintf(stderr, "this is not a stub'd program, or it is older and does not have one.\n"); exit(1); } fseek(f, offset_of_info + 16L, 0); fread(&size_of_info, 1, 4, f); stub_info.struct_length = size_of_info; if (size_of_info > sizeof(StubInfo)) size_of_info = sizeof(StubInfo); fseek(f, offset_of_info, 0); fread(&stub_info, 1, (int)size_of_info, f); fclose(f); return; } void store_info(char *filename) { FILE *f; f = fopen(filename, "r+b"); if (f == 0) { char buf[100]; sprintf(buf, "Fatal error in stubedit writing %s", filename); perror(buf); exit(1); } fseek(f, offset_of_info, 0); fwrite(&stub_info, 1, (int)size_of_info, f); fclose(f); } char *pose_question(char *question, char *default_answer) { static char response[200]; printf("%s ? [%s] ", question, default_answer); fflush(stdout); gets(response); if (response[0] == '\0') return 0; return response; } typedef void (*PerFunc)(void *address_of_field, char *buffer); void str_v2s(void *addr, char *buf) { if (*(char *)addr == 0) strcpy(buf, "\"\""); else { strncpy(buf, (char *)addr, 14); buf[14] = 0; } } void str_s2v(void *addr, char *buf) { if (strcmp(buf, "\"\"") == 0) *(char *)addr = 0; else { strncpy((char *)addr, buf, 14); ((char *)addr)[14] = 0; } } void bool_v2s(void *addr, char *buf) { if (*(word8 *)addr) strcpy(buf, "yes"); else strcpy(buf, "no"); } void bool_s2v(void *addr, char *buf) { switch (buf[0]) { case 'y': case 'Y': case '1': case 't': case 'T': *(char *)addr = 1; break; case 'n': case 'N': case '0': case 'f': case 'F': *(char *)addr = 0; break; } } void ver_v2s(void *addr, char *buf) { char *field = (char *)(addr); char *rtype = "unknown"; char *fmt = "%d.%d.%s%d"; switch (field[1]) { case 'a': rtype = "alpha"; break; case 'b': rtype = "beta"; break; case 'f': fmt = "%d.%d"; break; case 'm': rtype = "maint"; break; case 's': rtype = "special"; break; } sprintf(buf, fmt, field[3], field[2], rtype, field[0]); } void ver_s2v(void *addr, char *buf) { char *field = (char *)(addr); int major = 0; int minor = 0; char rtype; int release = 0; char rstr[100]; rstr[0] = 'f'; sscanf(buf, "%d.%d.%[^0-9]%d", &major, &minor, &rstr, &release); rtype = rstr[0]; field[3] = major; field[2] = minor; field[1] = rtype; field[0] = release; } void num_v2s(void *addr, char *buf) { word32 v = *(word32 *)addr; sprintf(buf, "%#lx (%ldk)", v, v / 1024L); } void num_s2v(void *addr, char *buf) { word32 r = 0; char s = 0; sscanf(buf, "%i%c", &r, &s); switch (s) { case 'k': case 'K': r *= 1024L; break; case 'm': case 'M': r *= 1048576L; break; } *(word32 *)addr = r; } struct { char *short_name; char *long_name; void *addr_of_field; PerFunc val2string; PerFunc string2val; } per_field[] = { { "extender", "Name of program to run as the extender (max 13 chars)", stub_info.go32, str_v2s, str_s2v }, { "version", "Version of GO32 required to run this program", stub_info.required_go32_version, ver_v2s, ver_s2v }, { "minstack", "Minimum amount of stack space (bytes/K/M)", (void *)(&stub_info.min_stack), num_v2s, num_s2v }, { "keepmem", "Maximum amount of virtual memory to keep when spawning", (void *)(&stub_info.max_keep_on_spawn), num_v2s, num_s2v }, { "runfile", "Base name of file to actually run (max 13 chars, \"\"=self)", (void *)(&stub_info.actual_file_to_run), str_v2s, str_s2v }, { "globbing", "Enable command-line wildcard expansion (yes/no)", (void *)(&stub_info.enable_globbing), bool_v2s, bool_s2v, }, { "availmem", "Amount of conventional memory to leave (bytes/K/M)", (void *)(&stub_info.free_conventional_memory), num_v2s, num_s2v }, }; #define NUM_FIELDS (sizeof(per_field) / sizeof(per_field[0])) #define HFORMAT "%-16s %s\n" void give_help(void) { int i; fprintf(stderr, "Usage: stubedit [-v] [-h] filename.exe [field=value . . . ]\n"); fprintf(stderr, "-h = give help -v = view info field=value means set w/o prompt\n"); fprintf(stderr, HFORMAT, "-field-", "-description-"); for (i=0; i < NUM_FIELDS; i++) fprintf(stderr, HFORMAT, per_field[i].short_name, per_field[i].long_name); exit(1); } main(int argc, char **argv) { int view_only = 0; int i; int need_to_save; if (argc > 1 && strcmp(argv[1], "-h") == 0) give_help(); if (argc > 1 && strcmp(argv[1], "-v") == 0) { view_only = 1; argc--; argv++; } if (argc < 2) give_help(); find_info(argv[1]); if (view_only) { char buf[100]; fprintf(stderr, HFORMAT, "-value-", "-field description-"); for (i=0; i<NUM_FIELDS; i++) { if ((int)(per_field[i].addr_of_field) - (int)(&stub_info) < stub_info.struct_length) { per_field[i].val2string(per_field[i].addr_of_field, buf); fprintf(stderr, HFORMAT, buf, per_field[i].long_name); } } exit(0); } if (argc > 2) { int f, got, got_any = 0; char fname[100], fval[100]; for (i=2; i < argc; i++) { fname[0] = 0; fval[0] = 0; sscanf(argv[i], "%[^=]=%s", fname, fval); got = 0; for (f=0; f<NUM_FIELDS; f++) { if (strcmp(per_field[f].short_name, fname) == 0) { got = 1; got_any = 1; if ((int)(per_field[i].addr_of_field) - (int)(&stub_info) < stub_info.struct_length) { per_field[f].string2val(per_field[f].addr_of_field, fval); } else fprintf(stderr, "Warning: This stub does not support field %s\n", fname); } } if (!got) { fprintf(stderr, "Error: %s is not a valid field name.\n", fname); give_help(); } } if (got_any) store_info(argv[1]); return 0; } need_to_save = 0; for (i=0; i<NUM_FIELDS; i++) { char buf[100], *resp; if ((int)(per_field[i].addr_of_field) - (int)(&stub_info) < stub_info.struct_length) { per_field[i].val2string(per_field[i].addr_of_field, buf); if ((resp = pose_question(per_field[i].long_name, buf)) != 0) { per_field[i].string2val(per_field[i].addr_of_field, resp); need_to_save = 1; } } } if (need_to_save) store_info(argv[1]); return 0; }
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.