home *** CD-ROM | disk | FTP | other *** search
- From: tanner@ki4pv.UUCP
- Newsgroups: comp.sources.misc
- Subject: A File Patching Package
- Message-ID: <2765@ncoast.UUCP>
- Date: 3 Jul 87 00:14:34 GMT
- Sender: allbery@ncoast.UUCP
- Lines: 873
- Approved: allbery@ncoast.UUCP
- X-Archive: comp.sources.misc/8707/5
-
- : "un-pack me with /bin/sh"
- # This shar file contains a file patcher known around here as "fddt".
- # The "Makefile" is incredibly simple. The man page explains
- # everything (hihi). I hand-shar'ed the thing, as I don't have a
- # "shar" prog running here. It might unpack anyway. Try it, after
- # inspecting for trojan horse droppings.
-
- echo "unshar: x-fddt.1"
- sed s/\^X-// > fddt.1 <<END_OF_FILE
- X-.TH FDDT 1
- X-.SH NAME
- X-fddt \- display and patch files
- X-.SH SYNOPSIS
- X-.B fddt
- X-.I "[-rw]"
- X-.I "file"
- X-.I "[-patch addr old1=new1 [old2=new2 ...] ]"
- X-.SH DESCRIPTION
- X-The
- X-.I fddt
- X-program allows viewing and patching of files, including special
- X-files, program binaries, and binary data files. This is especially
- X-helpful on those systems where "adb" won't touch your target file,
- X-or where "adb" isn't available.
- X-.PP
- X-If the
- X-.I "-r"
- X-argument is given, the file is opened for reading only.
- X-If the
- X-.I "-w"
- X-argument is given, the file is opened for writing only.
- X-The default is to open for both read and write. It is advised that
- X-you use the "-r" option on directories and "-w" option on line
- X-printers.
- X-.PP
- X-If the
- X-.I "-p"
- X-option is not given, the program is interactive and reads commands
- X-from the standard input.
- X-All of the commands take one or two addresses, which are
- X-offsets from the beginning of the file.
- X-The addresses are expressed in hex.
- X-The first address is the starting address,
- X-and the second address is (if given) the ending address.
- X-If the second address is omitted, EOF (actually a number greater than
- X-the max unix filesize) is assumed.
- X-If the first address is omitted, no work is done.
- X-Addresses may be separated by a space, comma, or dash.
- X-.\"
- X-.SH "INTERACTIVE COMMANDS"
- X-.IP "\fBd\fP"
- X-Display data from the file, starting at the address
- X-given.
- X-Data are shown as hex numbers and as characters, a la \fIddt\fP.
- X-.\"
- X-.IP "\fBe\fP"
- X-Enter data into the file, starting at the address
- X-given. It prompts with the address, and accepts bytes to be written
- X-into the file. The bytes are written upon receipt of a newline.
- X-Bytes must be entered as one or two hex digits. An EOF (normally
- X-ctrl/D or ctrl/Z) will end input, as will an interrupt.
- X-.\"
- X-.IP "\fBf\fP"
- X-Find data in the file, starting at the address
- X-given and continuing to the end of file, interrupt, or the second
- X-address if given. It prompts for a series of bytes to be searched
- X-for; they must be entered as one or two hex digits each. One line of
- X-bytes may be entered; the search starts upon receipt of the newline.
- X-.\"
- X-.IP "\fBq,x\fP"
- X-Quit. Also known as exit.
- X-.SH "OPTIONS"
- X-.IP "\fB-r\fP"
- X-The file is opened for reading only. The "e" command to enter data
- X-will not work. Non-interactive patching will not work.
- X-.IP "\fB-w\fP"
- X-The file is opened for writing only. The "d" command to display
- X-data and the "f" command to find data will not work. If patching,
- X-the old values must be given as "XX".
- X-.IP "\fB-p\fP"
- X-The file is to be patched non-interactively.
- X-The next argument is the starting address for the patching,
- X-and the following arguments are the old and new value substitutions.
- X-If the old value given does not match the value found in the file, an
- X-error is indicated; use "XX" if the old value is unknown or if the
- X-file is open for writing only.
- X-If the new value is given as "XX", no value is written. Allows
- X-skipping of bytes in the file.
- X-.SH BUGS
- X-This prog was originally written to fill a need under ms-dos, where
- X-the local debugger won't patch executable files!
- X-.PP
- X-Most versions of unix won't let you patch a running program.
- X-This means, of course, that the prog can't patch itself.
- X-.PP
- X-There should probably be a way to supress the lseek(2) attempts for
- X-non-seekable files. Displaying or patching your own tty can be
- X-amusing.
- X-.SH "SEE ALSO"
- X-adb(1), debug(ms-dos)
- X-.SH "AUTHOR"
- X-This program and document were written by Tanner Andrews at
- X-CompuData, Inc. in support of the Brother John\(rg project.
- X-CompuData, by making them available to you,
- X-neither gives up any rights nor assumes any responsibility
- X-for damages caused by them.
- END_OF_FILE
-
- echo "unshar: x-Makefile"
- sed s/\^X-// > Makefile <<END_OF_FILE
- X-
- X-# Makefile for "fddt"
- X-
- X-# set this as proper (use second one for xenix)
- X-CFLAGS = -O
- X-#CFLAGS = -O -K -Mm2
- X-
- X-fddt: fddt.o
- X- $(CC) $(CFLAGS) -o fddt /lib/cdate.o fddt.o
- X-
- END_OF_FILE
-
- echo "unshar: x-fddt.c"
- sed s/\^X-// > fddt.c <<END_OF_FILE
- X-
- X- /***************************************************************
- X- * *
- X- * disk file patch prog *
- X- * *
- X- ***************************************************************/
- X-
- X- /* 19-Nov-85 [ki4pv!tanner] */
- X- /* ed 20-Dec-85 [ki4pv!tanner] -- add find command */
- X- /* ed 03-Jan-86 [ki4pv!tanner] -- add exit command */
- X- /* ed 01-Jul-86 [ki4pv!tanner] -- add -p flag */
- X- /* ed 22-Oct-86 [ki4pv!tanner] -- turn off stdout buffer */
- X-
- X-#include <stdio.h>
- X-#include <signal.h>
- X-
- X-#define SZ 0x0100 /* size of things */
- X-
- X- /* this program allows someone to apply patches to files
- X- * of almost any type. it helps a lot if lseek() will work
- X- * on the file, but it is not required if the file to be
- X- * "patched" is a serial device which is really being fed
- X- * a stream of bytes.
- X- *
- X- * usage:
- X- * fddt [-rw] <file>
- X- * or:
- X- * fddt [-w] <file> -p <addr> old1=new1 old2=new2 ...
- X- * where
- X- * -r read-only; patches may not be applied
- X- * -w write-only; old contents may not be displayed
- X- * -p "patch" mode, starts at addr and applies patch
- X- *
- X- * once a file is selected for editing, the following commands
- X- * will apply for interactive mode within the prog:
- X- * d display data
- X- * e enter new values
- X- * f find data; will prompt for values
- X- * q,x exit
- X- * all commands take either one or two addresses (if no addr
- X- * given, no work is done). the first addr is a starting addr;
- X- * the second, if given, is an ending addr. default end is EOF.
- X- * note that all addresses and data values are to be expressed
- X- * in hex. new values being entered are entered as 1-byte hex
- X- * values.
- X- *
- X- * patch mode is a way to non-interactively change values in the
- X- * file being edited. see the man page.
- X- *
- X- * warning: if your unix does not have rdchk(), you may either
- X- * provide a substitute with ioctl() or eliminate the line of
- X- * code using it with a return(0) and just use ^C to interrupt
- X- * commands. rdchk() appears new with SYS-3, replacing a V7
- X- * ioctl() call.
- X- *
- X- * note for cd_txt[] -- this is supplied by a little daemon
- X- * which creates /lib/cdate.o containing today's date. the
- X- * daemon to do this is available from "ki4pv!tanner" upon
- X- * application. you could also eliminate the reference.
- X- *
- X- * This prog and documentation (C) 1987, CompuData, Inc.
- X- * Permission is granted to use it, so long as this
- X- * copyright notice remains intact, and so long as you
- X- * don't try to sell it or claim that you wrote it.
- X- * By making this program available, CompuData neither gives
- X- * up any rights in it, nor assumes any responsibility for
- X- * any damages caused by it.
- X- */
- X-
- X- /* important vars */
- X-
- X-static char
- X- tf_blt[] = "FDDT vers 1.2a built %s\n\n",
- X-
- X- tf_usg[] = "? usage: %s [-rw] <file> [-p <addr> old=new ...]\n",
- X-
- X- tf_sup[] = "%% %s suppressed\n",
- X- tx_rd[] = "reading",
- X- tx_wr[] = "writing",
- X-
- X- tf_bad[] = "? %s: bad %s: %s\n",
- X- tf_bdr[] = "? bad range: %08lX > %08lX\n",
- X- tf_nos[] = "? no search values\n",
- X- tf_sek[] = "? can't seek: %08lX\n",
- X- tf_wre[] = "? write error: file %s, off 0x%08X, n 0x%X\n",
- X-
- X- tf_fnd[] = "found @ 0x%08lX\n",
- X- tf_nfd[] = "not found, end @ 0x%08lX\n",
- X- tf_8x[] = "%08lX: ",
- X- tf_2x[] = "%02X ",
- X-
- X- tf_pat[] = "patching 0x%08lX: ",
- X- tf_pr1[] = "0x%02X",
- X- tx_prx[] = " xx ",
- X- tf_per[] = "read mismatch: exp 0x%02X, got 0x%02X\n",
- X- tx_pex[] = "patch expr",
- X-
- X- tx_int[] = "** intr **\n";
- X-
- X-unsigned int _fmode = 0x8000; /* for ms-dos */
- X-
- X- /* - - - - */
- X-
- X-short int
- X- stoppt, /* "action stopped" flag */
- X- rw_sup, /* -r or -w flag */
- X- patch, /* set true if patching */
- X- ed_fd; /* fd of file to be patched */
- X-
- X-char
- X- *prog_name,
- X- *inbuf, /* user input buffer */
- X- *ed_fn, /* name of file being patched */
- X- *ed_buf, /* edit buffer */
- X- *match; /* file match buffer */
- X-
- X- /* - - - - - */
- X-
- X-extern char
- X- cd_txt[]; /* /lib/cdate.o, kept by daemon */
- X-
- X- /* = = = = = */
- X-
- X-short int
- X- do_hdr(), /* things to do before any work */
- X- do_lev(), /* evaluate a long addr */
- X- get_ln(), /* get series of numbers */
- X- get_st(), /* get "stopped" flag */
- X- pat_ev(), /* eval expression for patch */
- X- sig_st(); /* signal handler */
- X-
- X-void
- X- do_opn(), /* open the file */
- X- do_pat(), /* patch the file */
- X- do_edt(), /* edit the file */
- X- do_dmp(), /* dump part of file */
- X- do_inp(), /* input new values to file */
- X- do_src(), /* find values in file */
- X- usage();
- X-
- X- /* - - - - - */
- X-
- X-extern long int
- X- lseek();
- X-
- X-extern int
- X- chupper(), /* $LOCLIB */
- X- dehex(); /* $LOCLIB */
- X- isprint(), iswhite(), isxdigit(),
- X- rdchk(); /* $SYSDEP */ /* pending input check */
- X-
- X-extern char
- X- *malloc(),
- X- *strbrk(), /* $LOCLIB */
- X- *strchr();
- X-
- X- /* main block of prog */
- X-
- X-main(ac, av)
- X-short int ac;
- X-char **av;
- X- {
- X- register char
- X- *p;
- X-
- X- fprintf(stderr, tf_blt, cd_txt);
- X-
- X- prog_name = **av ? *av : "FDDT";
- X-
- X- if (ac < 2)
- X- usage();
- X-
- X- if (*(p = *++av) == '-') { /* have flag */
- X- if (((rw_sup = chupper(*++p)) != 'R') &&
- X- (rw_sup != 'W'))
- X- usage();
- X- ++av;
- X- }
- X- else
- X- rw_sup = 0;
- X-
- X- ed_fn = *av; /* get working filename */
- X-
- X- setbuf(stdout, (char *)0);
- X-
- X- if ((!(ed_buf = malloc(SZ))) ||
- X- (!(match = malloc(2*SZ))) ||
- X- (!(inbuf = malloc(SZ)))) {
- X- fprintf(stderr, "? %s: can't allocate\n", prog_name);
- X- exit(1);
- X- }
- X-
- X- signal(SIGINT, sig_st); /* catch ^C to abort command */
- X-
- X- do_opn(); /* open the file */
- X-
- X- if (*++av)
- X- do_pat(av); /* patch the file */
- X- else
- X- do_edt(); /* edit the file */
- X-
- X- if (close(ed_fd)) /* close the file */
- X- no_clos(ed_fn);
- X-
- X- exit(0);
- X-
- X- }
- X-
- X-static void usage()
- X- {
- X-
- X- fprintf(stderr, tf_usg, prog_name);
- X- exit(1);
- X-
- X- }
- X-
- X- /* open file to be edited */
- X-
- X-void do_opn()
- X- {
- X- register short int
- X- mode;
- X-
- X- switch (rw_sup) { /* select file open mode */
- X- case 'R':
- X- mode = 0;
- X- break;
- X- case 'W':
- X- mode = 1;
- X- break;
- X- default:
- X- mode = 2;
- X- }
- X-
- X- if ((ed_fd = open(ed_fn, mode)) < 0)
- X- no_open(ed_fn);
- X-
- X- }
- X-
- X- /* patch the file */
- X-
- X-void do_pat(ap)
- X-char **ap;
- X- {
- X- register char
- X- *p;
- X- short int
- X- old, new;
- X- long int
- X- p_addr, /* patch addr */
- X- tmp; /* tmp value from eval */
- X- unsigned char
- X- c; /* in/out data item */
- X-
- X- if ((*(p = *ap) != '-') ||
- X- (chupper(*++p) != 'P'))
- X- usage();
- X-
- X- if (do_lev(*++ap, &p_addr)) { /* eval addr */
- X- fprintf(stderr, tf_bad, prog_name, "addr", *ap);
- X- exit(1);
- X- }
- X-
- X- if (lseek(ed_fd, p_addr, 0) != p_addr) { /* just test */
- X- fprintf(stderr, tf_sek, p_addr);
- X- exit(2);
- X- }
- X-
- X- for ( ; p = *++ap ; ++p_addr ) {
- X- p += pat_ev(p, &old, "old");
- X- if (*p++ != '=') {
- X- fprintf(stderr, tf_bad, prog_name, tx_pex, *ap);
- X- exit(3);
- X- }
- X- p += pat_ev(p, &new, "new");
- X- if (*p) {
- X- fprintf(stderr, tf_bad, prog_name, tx_pex, *ap);
- X- exit(4);
- X- }
- X- printf(tf_pat, p_addr);
- X- if (old >= 0) { /* match old */
- X- if (rw_sup == 'R') {
- X- fprintf(stderr, tf_sup, tx_rd);
- X- exit(5);
- X- }
- X- if ((lseek(ed_fd, p_addr, 0) != p_addr) ||
- X- (read(ed_fd, &c, 1) != 1) ||
- X- (c != old)) {
- X- fprintf(stderr, tf_per, old, c);
- X- exit(6);
- X- }
- X- printf(tf_pr1, old);
- X- }
- X- else
- X- printf(tx_prx);
- X- printf(" -> ");
- X- if (new >= 0) {
- X- if (rw_sup == 'W') {
- X- fprintf(stderr, tf_sup, tx_wr);
- X- exit(7);
- X- }
- X- c = new;
- X- if ((lseek(ed_fd, p_addr, 0) != p_addr) ||
- X- (write(ed_fd, &c, 1) != 1)) {
- X- fprintf(stderr, tf_wre, ed_fn, p_addr, 1);
- X- exit(8);
- X- }
- X- printf(tf_pr1, new);
- X- }
- X- else
- X- printf(tx_prx);
- X- printf(" ok\n");
- X- }
- X-
- X- }
- X-
- X- /* patch support: evaluate old/new value */
- X-
- X-static short int pat_ev(sp, dp, err)
- X-char *sp, *err;
- X-short int *dp; /* result goes here */
- X- {
- X- register char
- X- *q;
- X- long int
- X- tmp;
- X-
- X- if (chupper(*sp) == 'X') {
- X- *dp = -1;
- X- return(1);
- X- }
- X- if (do_lev(sp, &tmp) || (tmp < 0) || (tmp > 0xFF)) {
- X- fprintf(stderr, tf_bad, prog_name, err, sp);
- X- exit(3);
- X- }
- X- *dp = tmp;
- X-
- X- for ( q=sp ; isxdigit(*q) ; ++q );
- X- return((short int)(q - sp));
- X-
- X- }
- X-
- X- /* edit the file (top-level interaction) */
- X-
- X-void do_edt()
- X- {
- X- register char
- X- *p;
- X- register short int
- X- nrd;
- X-
- X- while (((nrd=read(0, inbuf, 100)) > 0) || get_st()) {
- X- if (nrd < 0) /* ^C caused I/O err */
- X- nrd = 0;
- X- *(inbuf+nrd) = 0; /* null at end-of-input */
- X- if (p = strchr(inbuf, '\n'))
- X- *p = 0;
- X- p = inbuf;
- X- while (iswhite(*p))
- X- ++p;
- X- switch (chupper(*p)) {
- X- case 'F':
- X- do_src(p+1);
- X- break;
- X- case 'E':
- X- do_inp(p+1);
- X- break;
- X- case 'D':
- X- do_dmp(p+1);
- X- break;
- X- case 'Q':
- X- case 'X':
- X- return;
- X- case '?':
- X- printf("D-display E-enter F-find Q-exit\n");
- X- break;
- X- default:
- X- printf("unknown: %c\n", *p);
- X- case 0:
- X- break;
- X- }
- X- }
- X-
- X- }
- X-
- X- /* dump values */
- X-
- X-void do_dmp(p)
- X-char *p;
- X- {
- X- register short int
- X- sz, nd;
- X- long int
- X- ed_adr,
- X- ed_cur,
- X- ed_end,
- X- lnend;
- X-
- X- if (do_hdr('R', p, &ed_adr, &ed_end)) /* input bad */
- X- return;
- X-
- X- ed_cur = ed_adr; /* back to start */
- X-
- X- do {
- X- lnend = ed_cur - (ed_cur % 16) + 15;
- X- if (lnend > ed_end)
- X- lnend = ed_end;
- X- sz = lnend - ed_cur + 1;
- X- if ((nd = read(ed_fd, ed_buf, sz)) < sz)
- X- sz = nd;
- X- if (sz < 1) {
- X- printf("e-o-f\n");
- X- break;
- X- }
- X- printf(tf_8x, ed_cur);
- X- for ( nd=0 ; nd<sz ; ++nd ) {
- X- printf(tf_2x, *(ed_buf+nd) & 0x00FF);
- X- if (nd == 7)
- X- fputc(' ', stdout);
- X- }
- X- fputs(" ", stdout);
- X- for ( nd=0 ; nd<sz ; ++nd ) {
- X- fputc(isprint(*(ed_buf+nd)) ? *(ed_buf+nd) : '.',
- X- stdout);
- X- if (nd == 7)
- X- fputc(' ', stdout);
- X- }
- X- fputc('\n', stdout);
- X- } while ((! get_st()) && ((ed_cur += sz) <= ed_end));
- X-
- X- fputc('\n', stdout);
- X-
- X- }
- X-
- X- /* enter new values into file */
- X-
- X-void do_inp(p)
- X-register char *p;
- X- {
- X- register short int
- X- n;
- X- long int
- X- ed_adr,
- X- ed_cur,
- X- ed_end;
- X-
- X- if (do_hdr('W', p, &ed_adr, &ed_end)) /* command bad */
- X- return;
- X-
- X- ed_cur = ed_adr;
- X- for ( ; (n = get_ln(ed_cur)) >= 0 ; ) {
- X- if ((n > 0) && (write(ed_fd, ed_buf, n) < n)) {
- X- fprintf(stderr, tf_wre, ed_fn, ed_cur, n);
- X- break;
- X- }
- X- if ((ed_cur += n) > ed_end) /* gave exit point */
- X- break;
- X- }
- X-
- X- }
- X-
- X- /* find values in file */
- X-
- X-#define MATCH (*(ed_buf+bufm) == *(match+bufo+bufm))
- X-
- X-void do_src(p)
- X-char *p;
- X- {
- X- register short int
- X- nsrc, /* # to search for */
- X- nbuf, /* # chars in buff */
- X- bufo, /* buffer offset */
- X- bufm, /* buffer # matched */
- X- nrd;
- X- long int
- X- ed_adr,
- X- ed_cur,
- X- ed_end,
- X- val;
- X-
- X- if (do_hdr('R', p, &ed_adr, &ed_end)) /* input bad */
- X- return;
- X-
- X- ed_cur = ed_adr; /* back to start */
- X-
- X- if ((nsrc = get_ln(0L)) <= 0) {
- X- printf(tf_nos);
- X- return;
- X- }
- X-
- X- printf("searching...");
- X- nrd = nbuf = read(ed_fd, match, 2*SZ);
- X- for ( bufo=0 ;; ) {
- X- for ( bufm=0 ; (bufm < nsrc) && MATCH ; ++bufm );
- X- if (bufm == nsrc) {
- X- printf(tf_fnd, ed_cur);
- X- return;
- X- }
- X- ++ed_cur; /* start at next char */
- X- if (++bufo > SZ) { /* must read more */
- X- move(match, match+SZ, SZ);
- X- bufo -= SZ;
- X- nbuf -= SZ;
- X- if (get_st()) /* input, stop search */
- X- nrd = 0;
- X- if (nrd && ((nrd=read(ed_fd, match+SZ, SZ)) > 0))
- X- nbuf += nrd;
- X- }
- X- if ((bufo >= nbuf) || (ed_cur > ed_end)) {
- X- printf(tf_nfd, ed_cur);
- X- return;
- X- }
- X- }
- X-
- X- }
- X-
- X- /* common support routines */
- X-
- X- /* handle the command understanding for both display and edit
- X- * expects
- X- * sup 'R', 'W' if reading, writing required
- X- * p user's input
- X- * sad, ead ptrs to display/edit start/end addr
- X- * returns
- X- * 0 good input
- X- * -1 didn't
- X- */
- X-static short int do_hdr(sup, p, sad, ead)
- X-char sup, *p;
- X-long int *sad, *ead;
- X- {
- X-
- X- if (rw_sup && (rw_sup != sup)) { /* make sure it's OK */
- X- printf(tf_sup, (sup=='R') ? tx_rd : tx_wr);
- X- return;
- X- }
- X-
- X- if (do_lev(p, sad)) /* get starting addr */
- X- return(-1);
- X-
- X- *ead = 0x40000000; /* dflt end addr */
- X-
- X- while (iswhite(*p)) /* skip white space */
- X- ++p;
- X-
- X- if ((p = strbrk(p, "-, ")) && do_lev(++p, ead)) {
- X- printf(tf_bad, prog_name, "end", p);
- X- return(-1);
- X- }
- X-
- X- if (*ead < *sad) {
- X- printf(tf_bdr, *sad, *ead);
- X- return(-1);
- X- }
- X-
- X- if (lseek(ed_fd, *sad, 0) != *sad) { /* do the seek */
- X- printf(tf_sek, *sad);
- X- return(-1);
- X- }
- X-
- X- return(0);
- X-
- X- }
- X-
- X- /* evaluate an address
- X- * expects
- X- * p ptr to addr to scan
- X- * adr addr to receive value if we found number
- X- * returns
- X- * 0 worked
- X- * -1 no addr found
- X- * note
- X- * if it works, *adr will be filled in.
- X- */
- X-
- X-static short int do_lev(p, adr)
- X-char *p;
- X-long int *adr;
- X- {
- X- register long int
- X- val;
- X-
- X- while (iswhite(*p)) /* skip */
- X- ++p;
- X-
- X- if (! isxdigit(*p))
- X- return(-1);
- X-
- X- for ( val=0 ; isxdigit(*p) ; ++p )
- X- val = (val << 4) + dehex(*p);
- X-
- X- if (*p && (! iswhite(*p)) && (*p != '=') && (*p != '-'))
- X- return(-1);
- X-
- X- *adr = val;
- X- return(0);
- X-
- X- }
- X-
- X- /* get a list of numbers into the edit buffer
- X- * expects
- X- * ed_cur address to be printed in prompt
- X- * returns
- X- * -1 trouble
- X- * n # bytes specified on line by user
- X- * fills in ed_buf with the values given
- X- */
- X-
- X-static short int get_ln(ed_cur)
- X-long int ed_cur;
- X- {
- X- register char
- X- *p;
- X- register short int
- X- n;
- X- long int
- X- val;
- X-
- X- printf(tf_8x, ed_cur); /* prompt */
- X- zero(inbuf, SZ);
- X- if (read(0, p=inbuf, 200) < 1) { /* hit EOF */
- X- fputs(" ** OK\n", stdout);
- X- return(-1);
- X- }
- X- for ( n=0 ; *p ; ) { /* scan & convert */
- X- if (do_lev(p, &val) ||
- X- (val > 0x00FF) || (val < 0)) {
- X- printf("bad value: %s\n", p);
- X- n = 0;
- X- break;
- X- }
- X- *(ed_buf+(n++)) = val;
- X- while (isxdigit(*p))
- X- ++p;
- X- while (isxdigit(*p))
- X- ++p;
- X- if (*p == ',')
- X- ++p;
- X- while (iswhite(*p))
- X- ++p;
- X- }
- X-
- X- return(n);
- X-
- X- }
- X-
- X- /* user-attention handlers */
- X-
- X- /* user hits ^C, set flag to indicate same
- X- * note: under ms-dos, signal() only works for ^C
- X- * but that's OK. use MS-C; lattice doesn't have
- X- * signal(2).
- X- */
- X-static short int sig_st()
- X- {
- X-
- X- signal(SIGINT, sig_st); /* continued protection */
- X- printf(tx_int); /* ack for abuser */
- X- stoppt = 1; /* set flag */
- X-
- X- }
- X-
- X- /* routine to see if user wants to stop command
- X- * checks/resets "stoppt" flag set by ^C
- X- * if machine has rdchk() uses that to see if pending input
- X- */
- X- /* $SYSDEP */
- X-static short int get_st()
- X- {
- X-
- X- if (stoppt) { /* hit ^C */
- X- stoppt = 0; /* clear it */
- X- return(1);
- X- }
- X-
- X- return(rdchk(0) > 0); /* pending input */
- X-
- X- }
- X-
- X- /* local library routines */
- X-
- X- /* these routines normally live in a local library. the names
- X- * are actually left-overs from CP/M days.
- X- */
- X-#ifndef DONT_NEED
- X- /* convert a hex digit */
- X-int dehex(c)
- X-int c;
- X- {
- X- if ((c >= '0') && (c <= '9'))
- X- return(c - '0');
- X- if ((c >= 'A') && (c <= 'F'))
- X- return(c + 10 - 'A');
- X- if ((c >= 'a') && (c <= 'f'))
- X- return(c + 10 - 'a');
- X- return(-1);
- X- }
- X-
- X- /* find character in "breakset" */
- X-char *strbrk(s1, s2)
- X-register char *s1, *s2;
- X- {
- X-
- X- if (s1 && s2) /* have strings */
- X- for ( ; *s1 ; ++s1 ) /* scan string */
- X- if (strchr(s2, *s1)) /* match any? */
- X- return(s1); /* yup, winner */
- X-
- X- return((char *)0);
- X-
- X- }
- X-
- X- /* case conversion -- don't trust "toupper" or "tolower */
- X-int chupper(c)
- X-int c;
- X- {
- X- return(((c >= 'a') && (c <= 'z')) ? (c - ('a'-'A')) : c);
- X- }
- X-
- X-#endif
- X-
- END_OF_FILE
-