ftp.nice.ch/pub/next/developer/languages/c/djgpp-NS.s.tar.gz#/djgpp/go32/stubedit.c

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.