/* Copyright (C) 1998 DJ Delorie, see COPYING.DJ for details */ /* Copyright (C) 1997 DJ Delorie, see COPYING.DJ for details */ /* Copyright (C) 1996 DJ Delorie, see COPYING.DJ for details */ /* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */ #include #include #include #include #ifdef __DJGPP__ #include #endif #include "../../include/stubinfo.h" unsigned long size_of_stubinfo = 0; char *client_stub_info; static unsigned long exe_start = 0; static unsigned char buf[4]; void find_info(char *filename) { FILE *f; unsigned char header[4]; 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); } if (fseek(f, 8L, 0) != 0 || fread(&buf, 1, 2, f) != 2) { printf("Error: %s could not read\n", filename); exit(1); } exe_start = buf[0]*16 + buf[1]*16*256; if (fseek(f, exe_start, 0) != 0 || fread(test_magic, 1, 16, f) != 16 || memcmp(test_magic, "go32stub", 8) != 0) { printf("Error: %s is not a go32 v2.0 or higher stub\n", filename); exit(1); } fread(header, 4, 1, f); size_of_stubinfo = (header[0]) | (header[1]<<8) | (header[2])<<16 | (header[3]<<24); fseek(f, exe_start, 0); client_stub_info = (char *)malloc(size_of_stubinfo); fread(client_stub_info, size_of_stubinfo, 1, 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, exe_start, 0); fwrite(client_stub_info, 1, size_of_stubinfo, 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, int len) { if (*(char *)addr == 0) strcpy(buf, "\"\""); else { buf[len] = 0; strncpy(buf, (char *)addr, len); } } void str_s2v(void *addr, char *buf, int len) { if (strcmp(buf, "\"\"") == 0) *(char *)addr = 0; else { ((char *)addr)[len-1] = 0; strncpy((char *)addr, buf, len); } } void str_v2s8(void *addr, char *buf) { str_v2s(addr, buf, 8); } void str_s2v8(void *addr, char *buf) { str_s2v(addr, buf, 8); } void str_v2s16(void *addr, char *buf) { str_v2s(addr, buf, 16); } void str_s2v16(void *addr, char *buf) { str_s2v(addr, buf, 16); } void num_v2s(void *addr, char *buf) { unsigned char *c = (unsigned char *)addr; unsigned long v = c[0] + (c[1]<<8) + (c[2]<<16) + (c[3]<<24); sprintf(buf, "%#lx (%ldk)", v, v / 1024L); } void num_s2v(void *addr, char *buf, int max) { unsigned char *c = (unsigned char *)addr; unsigned long r = 0; char s = 0; sscanf(buf, "%li%c", &r, &s); switch (s) { case 'k': case 'K': r *= 1024L; break; case 'm': case 'M': r *= 1048576L; break; } if (max && r > (unsigned long)max) { printf("Warning: %ld reduced to %d\n", r, max); r = max; } c[0] = r; c[1] = r>>8; c[2] = r>>16; c[3] = r>>24; } struct { char *short_name; char *long_name; int offset_of_field; PerFunc val2string; PerFunc string2val; int max; } per_field[] = { { "minstack", "Minimum amount of stack space (bytes/K/M)", STUBINFO_MINSTACK, (PerFunc)num_v2s, (PerFunc)num_s2v, 0 }, { "bufsize", "Size of real-memory transfer buffer (bytes/K/M)", STUBINFO_MINKEEP, (PerFunc)num_v2s, (PerFunc)num_s2v, 0xfe00 }, { "runfile", "Base name of file to actually run (max 8 chars, \"\"=self)", STUBINFO_BASENAME, (PerFunc)str_v2s8, (PerFunc)str_s2v8, 0 }, { "argv0", "Value to pass as file component of argv[0] (max 16 chars, \"\"=default)", STUBINFO_ARGV0, (PerFunc)str_v2s16, (PerFunc)str_s2v16, 0 }, { "dpmi", "Program to load to provide DPMI services (if needed)", STUBINFO_DPMI_SERVER, (PerFunc)str_v2s16, (PerFunc)str_s2v16, 0 } }; #define NUM_FIELDS (sizeof(per_field) / sizeof(per_field[0])) #define HFORMAT "%-16s %s\n" void give_help(void) { size_t 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); } int main(int argc, char **argv) { int view_only = 0; size_t 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 2) { int got, got_any = 0; size_t f; char fname[100], fval[100]; for (i=2; i < (size_t)argc; i++) { fname[0] = 0; fval[0] = 0; sscanf(argv[i], "%[^=]=%s", fname, fval); got = 0; for (f=0; f