/* * CONFIG.C * * (C)Copyright 1988, Matthew Dillon, All Rights Reserved. * Permission is granted to distribute for non-profit only. * * config file1 file2 file3.... filen * * Configure one or more executables. The executables must conform to * the Static User Modifiable Data Standard (SUMDS) * * This program configures the static parameters of C programs which * contain the appropriate structures. Unknown parameters may be * configured in raw hex if you know the format. */ #include #define arysize(array) (sizeof(array)/sizeof(array[0])) extern void *malloc(); typedef unsigned char ubyte; typedef unsigned short uword; typedef unsigned long ulong; char Show; char XDebug; main(ac, av) char *av[]; { register short i; FILE *fi; long pos, len; puts("CONFIG V1.00, Matthew Dillon."); for (i = 1; i < ac; ++i) { fi = fopen(av[i], "r+"); if (fi == NULL) { printf("Could not open %s for reading\n", av[i]); continue; } switch(FindData(fi, &pos, &len)) { case -2: printf("%s contains unknown hunk #%ld\n", av[i], pos); break; case -1: printf("%s is not an executable\n", av[i]); break; case 0: printf("could not find configuration header in %s\n", av[i]); break; case 1: switch(Configure(fi, pos, len*4)) { case -3: printf("Unable to malloc %ld bytes\n", len); break; case -2: puts("Error reading data block or badly formatted data"); break; case -1: puts("No 'END ' entry found in header"); break; case 0: puts("No modifications made to file"); break; case 1: puts("File updated"); break; } break; } fclose(fi); } } /* * Search through the beginning of all HUNK_DATA hunks for 'STRT', 0 * * symb: object modules only, not defined here. * HUNK_OVERLAY cannot be handled yet. */ #define HUNK_UNIT 999 /* N, Nlws of name */ #define HUNK_NAME 1000 /* N, Nlws of name */ #define HUNK_CODE 1001 /* N, Nlws of code */ #define HUNK_DATA 1002 /* N, Nlws of data */ #define HUNK_BSS 1003 /* N (Nlws of bss) */ #define HUNK_RELOC32 1004 /* N, (N+1)lws, N ... 0 */ #define HUNK_RELOC16 1005 /* N, (N+1)lws, N ... 0 */ #define HUNK_RELOC8 1006 /* N, (N+1)lws, N ... 0 */ #define HUNK_EXT 1007 /* N, symb,symb... 0 */ #define HUNK_SYMBOL 1008 /* N, symb,symb... 0 */ #define HUNK_DEBUG 1009 /* N, Nlws of debug */ #define HUNK_END 1010 /* - */ #define HUNK_HEADER 1011 /* N, Nlwsname, N.. 0, tabsize, F, L, F-L+1 sizes */ #define HUNK_OVERLAY 1013 /* tabsize, M+2,M+1 ... ovr data table */ #define HUNK_BREAK 1014 /* - */ FindData(fi, ppos, plen) FILE *fi; long *ppos; long *plen; { long type; long len; long pos; long ary[3]; static long buf[256]; if (fread(&type, 4, 1, fi) != 1 || type != HUNK_HEADER) return(-1); for (;;) { if (fread(&len, 4, 1, fi) != 1) return(-1); if (len == 0) break; fseek(fi, len*4, 1); } if (fread(ary, 4, 3, fi) != 3) return(-1); fseek(fi, 4*(ary[2] - ary[1] + 1), 1); while (fread(&type, 4, 1, fi) == 1) { len = 0; if (XDebug) printf("type: %ld\n", type); switch(type) { case HUNK_CODE: fread(&len, 4, 1, fi); break; case HUNK_DATA: fread(&len, 4, 1, fi); /* # of longwords */ pos = ftell(fi); if (len >= 4) { register short i; register short j = (len > arysize(buf)) ? arysize(buf) : len; register long *ptr; fread(buf, j, 4, fi); for (i = 0; i < j; ++i) { ptr = buf + i; if (ptr[0] == 'STRT' && ptr[1] == 0) { *ppos = pos+i*4; *plen = len - i; fseek(fi, *ppos, 0); return(1); } ptr = (long *)((short *)ptr + 1); if (ptr[0] == 'STRT' && ptr[1] == 0) { *ppos = pos+i*4+2; *plen = len - i; fseek(fi, *ppos, 0); return(1); } } } fseek(fi, pos, 0); break; case HUNK_BSS: fread(&len, 4, 1, fi); len = 0; break; case HUNK_RELOC32: case HUNK_RELOC16: case HUNK_RELOC8: for (;;) { if (fread(&len, 4, 1, fi) != 1) return(-1); if (len == 0) break; ++len; fseek(fi, len*4, 1); } break; case HUNK_SYMBOL: for (;;) { if (fread(&len, 4, 1, fi) != 1) return(-1); if (len == 0) break; len = (len + 1) & 0x00FFFFFF; if (len <= 32) /* reading is faster */ fread(buf, len, 4, fi); else /* very long name? */ fseek(fi, len*4, 1); } break; case HUNK_DEBUG: if (fread(&len, 4, 1, fi) != 1) return(-1); break; case HUNK_END: break; default: *ppos = type; return(-2); } fseek(fi, len*4, 1); } return(0); } Configure(fi, pos, len) FILE *fi; long pos; long len; /* bytes */ { register uword *buf = malloc(len+1); register long i; short j; long modified = 0; short numentries = 0; len >>= 1; /* Words */ if (buf == NULL) return(-3); fseek(fi, pos, 0); if (fread(buf, len, 2, fi) != 2) return(-2); for (i = 4; i < len;) { if (buf[i] == 'EN' && buf[i+1] == 'D ' && buf[i+2] == 0) break; ++numentries; i += 4 + ((buf[i+3]+1)>>1); } if (i > len) return(-2); if (i == len) return(-1); len = i; printf("%ld entries found\n\n", numentries); for (i = 4; i < len;) { register long data = (buf[i]<<16)|buf[i+1]; long dlen = buf[i+3]; uword *ptr = buf + i + 4; printf("----(%c%c%c%c,%2ld): ", data>>24, data>>16, data>>8, data, dlen); switch(data) { case 'NW ': puts("NEW WINDOW STRUCTURE"); modified += Edit_WINP(ptr, dlen); break; case 'TEXT': puts("TEXT"); modified += Edit_TEXT(ptr, dlen); break; default: puts("UNKNOWN STRUCTURE, HEX EDIT"); modified += Edit_Hex(ptr, dlen); break; } i += 4 + ((dlen+1)>>1); puts(""); } { long response = (modified) ? 0 : 'n'; char ibuf[64]; while (response != 'y' && response != 'n') { printf("Write data back to file (y/n): "); fflush(stdout); if (gets(ibuf) == NULL) break; response = ibuf[0] | 0x20; } if (response == 'y') { fseek(fi, pos, 0); fwrite(buf, len, 2, fi); return(1); } else { return(0); } } } Edit_WINP(buf, bytes) char *buf; short bytes; { short i; short modified = 0; for (i = 0; i < bytes;) { switch(i) { case 0: /* LeftEdge */ modified += strscanvalue(buf+i, 2, "LeftEdge", "(Negative = Relative to Screen Right)"); i += 2; break; case 2: /* TopEdge */ modified += strscanvalue(buf+i, 2, "TopEdge", "(Negative = Relative to Screen Bottom)"); i += 2; break; case 4: /* Width */ modified += strscanvalue(buf+i, 2, "Width", "(0 = Full Width, < 0 = ScreenWidth - (-width)"); i += 2; break; case 6: /* Height */ modified += strscanvalue(buf+i, 2, "Height", "(0 = Full Height, < 0 = ScreenHeight - (-height)"); i += 2; break; case 8: /* DetailPen */ modified += strscanvalue(buf+i, 1, "DetailPen", NULL); ++i; break; case 9: /* BlockPen */ modified += strscanvalue(buf+i, 1, "BlockPen", NULL); ++i; break; case 10: /* IDCMP */ modified += strscanvalue(buf+i, 4, "IDCMP", NULL); i += 4; break; case 14: /* Flags */ modified += strscanvalue(buf+i, 4, "Flags", NULL); i += 4; break; default: i = bytes; break; } } return(modified); } /* * Edit TEXT. The buffer holds a 'type' string, \0, then space for a text * string. */ Edit_TEXT(lb, len) char *lb; { register short i, slen; char buf[256]; char *prompt = lb; while (*lb) { ++lb; --len; } ++lb; --len; if (len <= 0) { puts("TEXT ERROR: UNTERMINATED BUFFER"); return(0); } loop: printf("%-15s (%ld chars max) (%15s) :", prompt, len - 1, lb); if (gets(buf) == NULL || buf[0] == 0) strcpy(buf, lb); if (strcmp(buf, lb) != 0) { slen = strlen(buf); if (slen > len - 1) { printf("Maximum of %ld chars!", len - 1); goto loop; } strcpy(lb, buf); return(1); } return(0); } Edit_Extended(i, size, lb) short i; char *lb; { printf(" #%ld (Blind entry) ", i); return(scanvalue(lb, size)); } Edit_Hex(lb, len) char *lb; long len; { short modified = 0; short i; puts(" (Unknown Type, blind data entry)"); for (i = 0; i < len; ++i) { printf(" Entry %2ld/%2ld ", i, len-1); modified += scanvalue(lb+i, 1); } return(modified); } strscanvalue(lb, size, prompt, desc) char *lb; char *prompt; char *desc; { if (desc) printf(" note: %s\n", desc); printf("%15s ", prompt); return(scanvalue(lb, size)); } scanvalue(lb, size) ubyte *lb; { register long val; register char *str; short neg; char buf[128]; top: switch(size) { case 1: val = *lb; printf("( $%02x %3ld) :", val, (char)val); break; case 2: val = *(uword *)lb; printf("( $%04x %6ld) :", val, (short)val); break; case 4: val = *(long *)lb; printf("($%08lx %7ld) :", val, val); break; } fflush(stdout); neg = 1; if (gets(buf) && buf[0]) { val = 0; str = buf; if (*str == '-') { neg = -1; ++str; } /* hex */ if (str[0] == '$' || (str[0] == '0' && (str[1]|0x20) == 'x')) { if (*str++ != '$') ++str; for (; *str; ++str) { *str |= 0x20; if (*str >= '0' && *str <= '9') { val = (val << 4) | (*str & 15); continue; } if (*str >= 'a' && *str <= 'f') { val = (val << 4) | (*str - 'a' + 10); continue; } break; } } else if (*str == '%') { /* binary */ for (++str; *str >= '0' && *str <= '1'; ++str) val = (val << 1) | (*str & 1); } else if (*str) { /* decimal */ for (; *str >= '0' && *str <= '9'; ++str) val = val * 10 + *str - '0'; } if (*str) { printf("Illegal char '%c', try again\n ? ", *str); goto top; } } if (neg < 0) val = -val; switch(size) { case 1: if ((ubyte)val != *lb) { *lb = val; return(1); } break; case 2: if ((uword)val != *(uword *)lb) { *(uword *)lb = val; return(1); } break; case 4: if (val != *(long *)lb) { *(long *)lb = val; return(1); } break; } return(0); }