xref: /netbsd-src/sys/arch/amiga/stand/binpatch/binpatch.c (revision 9f2b1defb521b0c81854a912c748909480ce8149)
1*9f2b1defSdholland /*	$NetBSD: binpatch.c,v 1.15 2016/05/30 03:02:58 dholland Exp $	*/
222087826Schopps 
322087826Schopps /* Author: Markus Wild mw@eunet.ch ???   */
422087826Schopps /* Modified: Rob Leland leland@mitre.org */
5276eff6bSchopps 
67dac6517Smw #include <sys/types.h>
77dac6517Smw #include <a.out.h>
822087826Schopps #include <fcntl.h>
97dac6517Smw #include <stdio.h>
1022087826Schopps #include <stdlib.h>
1122087826Schopps #include <string.h>
1222087826Schopps #include <unistd.h>
137dac6517Smw 
14f1e1796cSchopps #ifdef __NetBSD__
15f1e1796cSchopps /*
16f1e1796cSchopps  * assume NMAGIC files are linked at 0 (for kernel)
17f1e1796cSchopps  */
18f1e1796cSchopps #undef N_TXTADDR
19f1e1796cSchopps #define N_TXTADDR(ex) \
20f1e1796cSchopps 	((N_GETMAGIC2(ex) == (ZMAGIC|0x10000) || N_GETMAGIC2(ex) == NMAGIC) ? \
21e8cc3884Sthorpej 	0 : AOUT_LDPGSZ)
22f1e1796cSchopps #endif
23f1e1796cSchopps 
2422087826Schopps 
25fca656f5Sthorpej static char synusage[] =
26fca656f5Sthorpej "NAME\n"
27fca656f5Sthorpej "\t%s - Allows the patching of BSD binaries\n"
28fca656f5Sthorpej "SYNOPSIS\n"
29fca656f5Sthorpej "\t%s [-HELP]\n"
30fca656f5Sthorpej "\t%s [-b|-w|-l] -s symbol[[[index]][=value]] binary\n"
31fca656f5Sthorpej "\t%s [-b|-w|-l] [-o offset] -s symbol [-r value] binary\n"
32fca656f5Sthorpej "\t%s [-b|-w|-l] [-o offset] -a address [-r value] binary\n";
33c72886c6Sdholland 
34fca656f5Sthorpej static char desusage[] =
35fca656f5Sthorpej "DESCRIPTION\n"
36fca656f5Sthorpej "\tAllows the patching of BSD binaries, for example, a distributed\n"
37fca656f5Sthorpej "\tkernel. Recient additions allows the user to index into an array\n"
38fca656f5Sthorpej "\tand assign a value. Binpatch has internal variables to allow\n"
39fca656f5Sthorpej "\tyou to test it on itself under NetBSD.\n"
40fca656f5Sthorpej "OPTIONS\n"
41fca656f5Sthorpej "\t-a  patch variable by specifying address in hex\n"
42fca656f5Sthorpej "\t-b  symbol or address to be patched is 1 byte\n"
43fca656f5Sthorpej "\t-l  symbol or address to be patched is 4 bytes  (default)\n"
44fca656f5Sthorpej "\t-o  offset to begin patching value relative to symbol or address\n"
45fca656f5Sthorpej "\t-r  replace value, and print out previous value to stdout\n"
46fca656f5Sthorpej "\t-s  patch variable by specifying symbol name. Use '[]'\n"
47fca656f5Sthorpej "\t    to specify the 'index'. If '-b, -w or -l' not specified\n"
48fca656f5Sthorpej "\t    then index value is used like an offset. Also can use '='\n"
49fca656f5Sthorpej "\t    to assign value\n"
50fca656f5Sthorpej "\t-w  symbol or address to be patched is 2 bytes\n"
51fca656f5Sthorpej "EXAMPLES\n"
52fca656f5Sthorpej "\tThis should print 100 (this is a nice reality check...)\n"
53fca656f5Sthorpej "\t\tbinpatch -l -s _hz netbsd\n"
54fca656f5Sthorpej "\tNow it gets more advanced, replace the value:\n"
55fca656f5Sthorpej "\t\tbinpatch -l -s _sbic_debug -r 1 netbsd\n"
56fca656f5Sthorpej "\tNow patch a variable at a given 'index' not offset,\n"
57fca656f5Sthorpej "\tunder NetBSD you must use '', under AmigaDos CLI '' is optional.:\n"
58fca656f5Sthorpej "\t\tbinpatch -w -s '_vieww[4]' -r 0 a.out\n"
59fca656f5Sthorpej "\tsame as\n"
60fca656f5Sthorpej "\t\tbinpatch -w -o 8 -s _vieww -r 0 a.out\n"
61fca656f5Sthorpej "\tAnother example of using []\n"
62fca656f5Sthorpej "\t\tbinpatch -s '_viewl[4]' -r 0 a.out\n"
63fca656f5Sthorpej "\tsame as\n"
64fca656f5Sthorpej "\t\tbinpatch -o 4 -s _viewl -r 0 a.out\n"
65fca656f5Sthorpej "\tOne last example using '=' and []\n"
66fca656f5Sthorpej "\t\tbinpatch -w -s '_vieww[4]=2' a.out\n"
67fca656f5Sthorpej "\tSo if the kernel is not finding your drives, you could enable\n"
68fca656f5Sthorpej "\tall available debugging options, helping to shed light on that problem.\n"
69fca656f5Sthorpej "\t\tbinpatch -l -s _sbic_debug -r 1 netbsd	scsi-level\n"
70fca656f5Sthorpej "\t\tbinpatch -l -s _sddebug -r 1 netbsd	sd-level (disk-driver)\n"
71fca656f5Sthorpej "\t\tbinpatch -l -s _acdebug -r 1 netbsd	autoconfig-level\n"
72fca656f5Sthorpej "SEE ALSO\n"
73fca656f5Sthorpej "\tbinpatch.c binpatch(1)\n";
7422087826Schopps 
757dac6517Smw extern char *optarg;
767dac6517Smw extern int optind;
777dac6517Smw 
78d0338842Stsutsui void error(char *) __attribute__((__noreturn__));
7922087826Schopps static void Synopsis(char *program_name);
8022087826Schopps static void Usage(char *program_name);
8122087826Schopps static u_long FindAssign(char *symbol, u_long *rvalue);
8222087826Schopps static void FindOffset(char *symbol, u_long *index);
837dac6517Smw 
8422087826Schopps /* The following variables are so binpatch can be tested on itself */
857dac6517Smw int test = 1;
867dac6517Smw int testbss;
877dac6517Smw char foo = 23;
8822087826Schopps char  viewb[10] = {0,0,1,0,1,1,0,1,1,1};
8922087826Schopps short vieww[10] = {0,0,1,0,1,1,0,1,1,1};
9022087826Schopps long  viewl[10] = {0,0,1,0,1,1,0,1,1,1};
9122087826Schopps /* End of test binpatch variables */
92c72886c6Sdholland 
937dac6517Smw int
main(int argc,char * argv[])9422087826Schopps main(int argc, char *argv[])
957dac6517Smw {
967dac6517Smw 	struct exec e;
977dac6517Smw 	int c;
9865e7c711Smw 	u_long addr = 0, offset = 0;
99964a5c8eSdholland 	/* Related to offset */
100964a5c8eSdholland 	u_long index = 0;
1017dac6517Smw 	u_long replace = 0, do_replace = 0;
1027dac6517Smw 	char *symbol = 0;
103964a5c8eSdholland 	/* default to long */
104964a5c8eSdholland 	char size = 4;
105964a5c8eSdholland 	/* Flag to say size option was set, used with index */
106964a5c8eSdholland 	char size_opt = 0;
1077dac6517Smw 	char *fname;
108964a5c8eSdholland 	/* Program name */
109964a5c8eSdholland 	char *pgname = argv[0];
1107dac6517Smw 	int fd;
1117dac6517Smw 	int type, off;
1127dac6517Smw 	u_long  lval;
1137dac6517Smw 	u_short sval;
1147dac6517Smw 	u_char  cval;
1157dac6517Smw 
1167dac6517Smw 
117964a5c8eSdholland 	while ((c = getopt(argc, argv, "H:a:bwlr:s:o:")) != -1) {
118964a5c8eSdholland 		switch (c) {
11922087826Schopps 		case 'H':
12022087826Schopps 			Usage(argv[0]);
12122087826Schopps 			break;
1227dac6517Smw 		case 'a':
123964a5c8eSdholland 			if (addr || symbol) {
1247dac6517Smw 				error("only one address/symbol allowed");
125964a5c8eSdholland 			}
126964a5c8eSdholland 			if (!strncmp(optarg, "0x", 2)) {
1277dac6517Smw 				sscanf(optarg, "%x", &addr);
128964a5c8eSdholland 			} else {
1297dac6517Smw 				addr = atoi(optarg);
130964a5c8eSdholland 			}
131964a5c8eSdholland 			if (!addr) {
1327dac6517Smw 				error("invalid address");
133964a5c8eSdholland 			}
1347dac6517Smw 			break;
1357dac6517Smw 
1367dac6517Smw 		case 'b':
1377dac6517Smw 			size = 1;
13822087826Schopps 			size_opt = 1;
1397dac6517Smw 			break;
1407dac6517Smw 
1417dac6517Smw 		case 'w':
1427dac6517Smw 			size = 2;
14322087826Schopps 			size_opt = 1;
1447dac6517Smw 			break;
1457dac6517Smw 
1467dac6517Smw 		case 'l':
1477dac6517Smw 			size = 4;
14822087826Schopps 			size_opt = 1;
1497dac6517Smw 			break;
1507dac6517Smw 
1517dac6517Smw 		case 'r':
1527dac6517Smw 			do_replace = 1;
153964a5c8eSdholland 			if (!strncmp(optarg, "0x", 2)) {
1547dac6517Smw 				sscanf(optarg, "%x", &replace);
155964a5c8eSdholland 			} else {
1567dac6517Smw 				replace = atoi(optarg);
157964a5c8eSdholland 			}
1587dac6517Smw 			break;
1597dac6517Smw 
1607dac6517Smw 		case 's':
161964a5c8eSdholland 			if (addr || symbol) {
1627dac6517Smw 				error("only one address/symbol allowed");
163964a5c8eSdholland 			}
1647dac6517Smw 			symbol = optarg;
1657dac6517Smw 			break;
16665e7c711Smw 
16765e7c711Smw 		case 'o':
168964a5c8eSdholland 			if (offset) {
16965e7c711Smw 				error("only one offset allowed");
170964a5c8eSdholland 			}
171964a5c8eSdholland 			if (!strncmp(optarg, "0x", 2)) {
17265e7c711Smw 				sscanf(optarg, "%x", &offset);
173964a5c8eSdholland 			} else {
17465e7c711Smw 				offset = atoi(optarg);
175964a5c8eSdholland 			}
17665e7c711Smw 			break;
177964a5c8eSdholland 		}
178964a5c8eSdholland 		/* end while switch() */
179964a5c8eSdholland 	}
1807dac6517Smw 
181964a5c8eSdholland 	if (argc > 1) {
182964a5c8eSdholland 		if (addr || symbol) {
1837dac6517Smw 			argv += optind;
1847dac6517Smw 			argc -= optind;
1857dac6517Smw 
186964a5c8eSdholland 			if (argc < 1) {
1877dac6517Smw 				error("No file to patch.");
188964a5c8eSdholland 			}
1897dac6517Smw 
1907dac6517Smw 			fname = argv[0];
191964a5c8eSdholland 			if ((fd = open(fname, 0)) < 0) {
1927dac6517Smw 				error("Can't open file");
193964a5c8eSdholland 			}
1947dac6517Smw 
1957dac6517Smw 			if (read(fd, &e, sizeof(e)) != sizeof(e)
196964a5c8eSdholland 			    || N_BADMAG(e)) {
1977dac6517Smw 				error("Not a valid executable.");
198964a5c8eSdholland 			}
1997dac6517Smw 
2007dac6517Smw 			/* fake mid, so the N_ macros work on the amiga.. */
2017dac6517Smw 			e.a_midmag |= 127 << 16;
2027dac6517Smw 
203964a5c8eSdholland 			if (symbol) {
2047dac6517Smw 				struct nlist nl[2];
205964a5c8eSdholland 
206964a5c8eSdholland 				if (offset == 0) {
20722087826Schopps 					u_long new_do_replace = 0;
208c72886c6Sdholland 
209964a5c8eSdholland 					new_do_replace = FindAssign(symbol,
210964a5c8eSdholland 								&replace);
21122087826Schopps 					if (new_do_replace && do_replace)
212964a5c8eSdholland 						error("Cannot use both '=' "
213964a5c8eSdholland 						      "and '-r' option!");
21422087826Schopps 					FindOffset(symbol, &index);
215964a5c8eSdholland 					if (size_opt) {
216964a5c8eSdholland 						/* Treat like an index */
217964a5c8eSdholland 						offset = index*size;
218964a5c8eSdholland 					} else {
219964a5c8eSdholland 						/* Treat like an offset */
220964a5c8eSdholland 						offset = index;
221964a5c8eSdholland 					}
22222087826Schopps 					if (new_do_replace)
22322087826Schopps 						do_replace = new_do_replace;
22422087826Schopps 				}
2257dac6517Smw 				nl[0].n_un.n_name = symbol;
2267dac6517Smw 				nl[1].n_un.n_name = 0;
227964a5c8eSdholland 				if (nlist(fname, nl) != 0) {
228*9f2b1defSdholland 					fprintf(stderr, "Symbol is %s ",
229*9f2b1defSdholland 						symbol);
2307dac6517Smw 					error("Symbol not found.");
23122087826Schopps 				}
2327dac6517Smw 				addr = nl[0].n_value;
2337dac6517Smw 				type = nl[0].n_type & N_TYPE;
234964a5c8eSdholland 			} else {
2357dac6517Smw 				type = N_UNDF;
236964a5c8eSdholland 				if (addr >= N_TXTADDR(e) &&
237964a5c8eSdholland 				    addr < N_DATADDR(e)) {
2387dac6517Smw 					type = N_TEXT;
239964a5c8eSdholland 				} else if (addr >= N_DATADDR(e) &&
240964a5c8eSdholland 				    addr < N_DATADDR(e) + e.a_data) {
2417dac6517Smw 					type = N_DATA;
2427dac6517Smw 				}
243964a5c8eSdholland 			}
24465e7c711Smw 			addr += offset;
2457dac6517Smw 
246964a5c8eSdholland 			/*
247964a5c8eSdholland 			 * if replace-mode, have to reopen the file
248964a5c8eSdholland 			 * for writing. Can't do that from the
249964a5c8eSdholland 			 * beginning, or nlist() will not work (at
250964a5c8eSdholland 			 * least not under AmigaDOS)
251964a5c8eSdholland 			 */
252964a5c8eSdholland 			if (do_replace) {
2537dac6517Smw 				close(fd);
254964a5c8eSdholland 				if ((fd = open(fname, 2)) == -1) {
2557dac6517Smw 					error("Can't reopen file for writing.");
2567dac6517Smw 				}
257964a5c8eSdholland 			}
2587dac6517Smw 
259964a5c8eSdholland 			if (type != N_TEXT && type != N_DATA) {
260964a5c8eSdholland 				error("address/symbol is not in text "
261964a5c8eSdholland 				      "or data section.");
262964a5c8eSdholland 			}
2637dac6517Smw 
264964a5c8eSdholland 			if (type == N_TEXT) {
2657dac6517Smw 				off = addr - N_TXTADDR(e) + N_TXTOFF(e);
266964a5c8eSdholland 			} else {
2677dac6517Smw 				off = addr - N_DATADDR(e) + N_DATOFF(e);
268964a5c8eSdholland 			}
2697dac6517Smw 
270964a5c8eSdholland 			if (lseek(fd, off, 0) == -1) {
2717dac6517Smw 				error("lseek");
272964a5c8eSdholland 			}
2737dac6517Smw 
274964a5c8eSdholland 			/*
275964a5c8eSdholland 			 * not beautiful, but works on big and little
276964a5c8eSdholland 			 * endian machines
277964a5c8eSdholland 			 */
278964a5c8eSdholland 			switch (size) {
2797dac6517Smw 			case 1:
280964a5c8eSdholland 				if (read(fd, &cval, 1) != 1) {
2817dac6517Smw 					error("cread");
282964a5c8eSdholland 				}
2837dac6517Smw 				lval = cval;
2847dac6517Smw 				break;
2857dac6517Smw 
2867dac6517Smw 			case 2:
287964a5c8eSdholland 				if (read(fd, &sval, 2) != 2) {
2887dac6517Smw 					error("sread");
289964a5c8eSdholland 				}
2907dac6517Smw 				lval = sval;
2917dac6517Smw 				break;
2927dac6517Smw 
2937dac6517Smw 			case 4:
294964a5c8eSdholland 				if (read(fd, &lval, 4) != 4) {
2957dac6517Smw 					error("lread");
296964a5c8eSdholland 				}
2977dac6517Smw 				break;
29822087826Schopps 			}/* switch size */
2997dac6517Smw 
3007dac6517Smw 
301964a5c8eSdholland 			if (symbol) {
302964a5c8eSdholland 				printf("%s(0x%x): %d (0x%x)\n", symbol, addr,
303964a5c8eSdholland 					lval, lval);
304964a5c8eSdholland 			} else {
3057dac6517Smw 				printf("0x%x: %d (0x%x)\n", addr, lval, lval);
306964a5c8eSdholland 			}
3077dac6517Smw 
308964a5c8eSdholland 			if (do_replace) {
309964a5c8eSdholland 				if (lseek(fd, off, 0) == -1) {
3107dac6517Smw 					error("write-lseek");
311964a5c8eSdholland 				}
312964a5c8eSdholland 				switch (size) {
3137dac6517Smw 				case 1:
3147dac6517Smw 					cval = replace;
315964a5c8eSdholland 					if (cval != replace) {
3167dac6517Smw 						error("byte-value overflow.");
317964a5c8eSdholland 					}
318964a5c8eSdholland 					if (write(fd, &cval, 1) != 1) {
3197dac6517Smw 						error("cwrite");
320964a5c8eSdholland 					}
3217dac6517Smw 					break;
3227dac6517Smw 
3237dac6517Smw 				case 2:
3247dac6517Smw 					sval = replace;
325964a5c8eSdholland 					if (sval != replace) {
3267dac6517Smw 						error("word-value overflow.");
327964a5c8eSdholland 					}
328964a5c8eSdholland 					if (write(fd, &sval, 2) != 2) {
3297dac6517Smw 						error("swrite");
330964a5c8eSdholland 					}
3317dac6517Smw 					break;
3327dac6517Smw 
3337dac6517Smw 				case 4:
334964a5c8eSdholland 					if (write(fd, &replace, 4) != 4) {
3357dac6517Smw 						error("lwrite");
336964a5c8eSdholland 					}
3377dac6517Smw 					break;
338964a5c8eSdholland 				}
339964a5c8eSdholland 				/* end switch(size) */
340964a5c8eSdholland 			}
341964a5c8eSdholland 			/* end if (do_replace) */
3427dac6517Smw 
3437dac6517Smw 			close(fd);
344964a5c8eSdholland 		} else {
345964a5c8eSdholland 			/* not (addr || symbol) */
34622087826Schopps 			error("Must specify either address or symbol.");
3477dac6517Smw 		}
348964a5c8eSdholland 	} else {
349964a5c8eSdholland 		/* if argc <= 1 */
35022087826Schopps 		Synopsis(pgname);
35122087826Schopps 	}
352964a5c8eSdholland 
353964a5c8eSdholland 	return 0;
354964a5c8eSdholland }
355964a5c8eSdholland /* end main () */
3567dac6517Smw 
3577dac6517Smw 
3587dac6517Smw 
359964a5c8eSdholland void
error(char * str)360964a5c8eSdholland error(char *str)
3617dac6517Smw {
3627dac6517Smw 	fprintf(stderr, "%s\n", str);
3637dac6517Smw 	exit(1);
3647dac6517Smw }
36522087826Schopps 
36622087826Schopps /* Give user very short help to avoid scrolling screen much */
367964a5c8eSdholland static void
Synopsis(char * pgname)368964a5c8eSdholland Synopsis(char *pgname)
36922087826Schopps {
37022087826Schopps 	fprintf(stdout, synusage, pgname, pgname, pgname, pgname, pgname);
37122087826Schopps }
37222087826Schopps 
37322087826Schopps 
374964a5c8eSdholland static void
Usage(char * pgname)375964a5c8eSdholland Usage(char *pgname)
37622087826Schopps {
37722087826Schopps 	Synopsis(pgname);
37822087826Schopps 	fprintf(stdout, desusage);
37922087826Schopps 	exit(0);
38022087826Schopps }
38122087826Schopps 
38222087826Schopps 
383964a5c8eSdholland /*
384964a5c8eSdholland  * FindOffset() - Determine if there is an offset, -or- index
385964a5c8eSdholland  * embedded in the symbol.
386964a5c8eSdholland  *
387964a5c8eSdholland  * If there is, return it, and truncate symbol to exclude the [...].
388964a5c8eSdholland  *
389964a5c8eSdholland  * Example: If view is declared as short view[10],
390964a5c8eSdholland  *                and we want to index the 3rd. element.
391964a5c8eSdholland  *                which is offset = (3 -1)*sizeof(short) =4.
392964a5c8eSdholland  *          we would use view[4], which becomes view,4.
393964a5c8eSdholland  *
394964a5c8eSdholland  *          The way the code is implemented the [value] is
395964a5c8eSdholland  *          treated as a index if-and-only-if a '-b -w -l' option
396964a5c8eSdholland  *          was given. Otherwise it is treated like an offset.
397964a5c8eSdholland  *           See above documentation in for of help!
39822087826Schopps  */
399964a5c8eSdholland static void
FindOffset(char * symbol,u_long * index)400964a5c8eSdholland FindOffset(char *symbol, u_long *index)
40122087826Schopps {
402964a5c8eSdholland 	/* Start of '[', now line must contain matching']' */
403964a5c8eSdholland 	char *sb = strchr(symbol, '[');
404964a5c8eSdholland 
405964a5c8eSdholland 	/* End of ']' */
406964a5c8eSdholland 	char *eb = strchr(symbol, ']');
407964a5c8eSdholland 
408964a5c8eSdholland 	/* symbol size */
409964a5c8eSdholland 	short sz = strlen(symbol);
410964a5c8eSdholland 
411964a5c8eSdholland 	if (sb) {
412964a5c8eSdholland 		if (eb && (eb > sb)) {
413964a5c8eSdholland 			if ((eb - symbol) == (sz - 1)) {
414964a5c8eSdholland 				/* Start of index */
415964a5c8eSdholland 				char *sindex;
41622087826Schopps 				u_long newindex = 0;
417964a5c8eSdholland 
418964a5c8eSdholland 				/*
419964a5c8eSdholland 				 * In the future we could get fancy
420964a5c8eSdholland 				 * and parse the sindex string for
421964a5c8eSdholland 				 * mathmatical expressions like: (3 -
422964a5c8eSdholland 				 * 1)*2 = 4 from above example, ugh
423964a5c8eSdholland 				 * forget I mentioned ot :-) !
42422087826Schopps 				 */
42522087826Schopps 				sindex = sb + 1;
42622087826Schopps 				*eb = '\0';
42722087826Schopps 				newindex = (u_long)atoi(sindex);
428964a5c8eSdholland 				if (*index == 0) {
42922087826Schopps 					*index = newindex;
430964a5c8eSdholland 					/* Make _view[3] look like _view */
431964a5c8eSdholland 					*sb = '\0';
432964a5c8eSdholland 				} else {
433964a5c8eSdholland 					fprintf(stderr, "Error index can "
434964a5c8eSdholland 						"only be specified once!\n");
43522087826Schopps 				}
436964a5c8eSdholland 			} else {
437964a5c8eSdholland 				fprintf(stderr, "Error: Garbage "
438964a5c8eSdholland 					"trailing ']'\n");
43922087826Schopps 			}
440964a5c8eSdholland 		} else {
44122087826Schopps 			fprintf(stderr, "Error ']' in symbol before '[' !\n");
44222087826Schopps 		}
443964a5c8eSdholland 	}
444964a5c8eSdholland 	/* end if sb != 0 */
445964a5c8eSdholland }
446964a5c8eSdholland /* end FindOffset */
44722087826Schopps 
448964a5c8eSdholland /*
449964a5c8eSdholland  * FindAssign : Scans symbol name for an '=number' strips it off of
450964a5c8eSdholland  * the symbol and proceeds.
45122087826Schopps  */
452964a5c8eSdholland static u_long
FindAssign(char * symbol,u_long * rvalue)453964a5c8eSdholland FindAssign(char *symbol, u_long *rvalue)
45422087826Schopps {
455964a5c8eSdholland 	/* Assign symbol some number */
456964a5c8eSdholland 	char *ce = rindex(symbol, '=');
457c72886c6Sdholland 
458964a5c8eSdholland 	/* This should point at some number, no spaces allowed */
459964a5c8eSdholland 	char *cn = ce + 1;
460964a5c8eSdholland 
461964a5c8eSdholland 	/* flag for do_replace */
462964a5c8eSdholland 	u_long dr = 0;
463964a5c8eSdholland 
464964a5c8eSdholland 	if (ce) {
465964a5c8eSdholland 		/* number of variaables scanned in */
466964a5c8eSdholland 		int nscan;
467964a5c8eSdholland 
46822087826Schopps 		/* get the number to assign to symbol and strip off = */
469cb81c2ddSdholland 		for (cn=ce + 1; *cn==' '; cn++)
47022087826Schopps 			;
471964a5c8eSdholland 		if (!strncmp(cn, "0x", 2)) {
47222087826Schopps 			nscan = sscanf(cn, "%x", rvalue);
473964a5c8eSdholland 		} else {
47422087826Schopps 			nscan = sscanf(cn, "%d", rvalue);
475964a5c8eSdholland 		}
476964a5c8eSdholland 		if (nscan != 1) {
47722087826Schopps 			error("Invalid value following '='");
478964a5c8eSdholland 		}
47922087826Schopps 		dr = 1;
480964a5c8eSdholland 		/* Now were left with just symbol */
481964a5c8eSdholland 		*ce = '\0';
482964a5c8eSdholland 	}
483964a5c8eSdholland 	/* end if (ce) */
48422087826Schopps 	return(dr);
485964a5c8eSdholland }
486964a5c8eSdholland /* end FindAssign */
487