home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / misc / volume1 / 8707 / 5 < prev    next >
Encoding:
Internet Message Format  |  1990-07-13  |  20.5 KB

  1. From: tanner@ki4pv.UUCP
  2. Newsgroups: comp.sources.misc
  3. Subject: A File Patching Package
  4. Message-ID: <2765@ncoast.UUCP>
  5. Date: 3 Jul 87 00:14:34 GMT
  6. Sender: allbery@ncoast.UUCP
  7. Lines: 873
  8. Approved: allbery@ncoast.UUCP
  9. X-Archive: comp.sources.misc/8707/5
  10.  
  11. : "un-pack me with /bin/sh"
  12. # This shar file contains a file patcher known around here as "fddt".
  13. # The "Makefile" is incredibly simple.  The man page explains
  14. # everything (hihi).  I hand-shar'ed the thing, as I don't have a
  15. # "shar" prog running here.  It might unpack anyway.  Try it, after
  16. # inspecting for trojan horse droppings.
  17.  
  18. echo    "unshar: x-fddt.1"
  19. sed s/\^X-// > fddt.1 <<END_OF_FILE
  20. X-.TH FDDT 1
  21. X-.SH NAME
  22. X-fddt \- display and patch files
  23. X-.SH SYNOPSIS
  24. X-.B fddt
  25. X-.I "[-rw]"
  26. X-.I "file"
  27. X-.I "[-patch addr old1=new1 [old2=new2 ...] ]"
  28. X-.SH DESCRIPTION
  29. X-The
  30. X-.I fddt
  31. X-program allows viewing and patching of files, including special
  32. X-files, program binaries, and binary data files.  This is especially
  33. X-helpful on those systems where "adb" won't touch your target file,
  34. X-or where "adb" isn't available.
  35. X-.PP
  36. X-If the
  37. X-.I "-r"
  38. X-argument is given, the file is opened for reading only.
  39. X-If the
  40. X-.I "-w"
  41. X-argument is given, the file is opened for writing only.
  42. X-The default is to open for both read and write.  It is advised that
  43. X-you use the "-r" option on directories and "-w" option on line
  44. X-printers.
  45. X-.PP
  46. X-If the
  47. X-.I "-p"
  48. X-option is not given, the program is interactive and reads commands
  49. X-from the standard input.
  50. X-All of the commands take one or two addresses, which are
  51. X-offsets from the beginning of the file.
  52. X-The addresses are expressed in hex.
  53. X-The first address is the starting address,
  54. X-and the second address is (if given) the ending address.
  55. X-If the second address is omitted, EOF (actually a number greater than
  56. X-the max unix filesize) is assumed.
  57. X-If the first address is omitted, no work is done.
  58. X-Addresses may be separated by a space, comma, or dash.
  59. X-.\"
  60. X-.SH "INTERACTIVE COMMANDS"
  61. X-.IP "\fBd\fP"
  62. X-Display data from the file, starting at the address
  63. X-given.
  64. X-Data are shown as hex numbers and as characters, a la \fIddt\fP.
  65. X-.\"
  66. X-.IP "\fBe\fP"
  67. X-Enter data into the file, starting at the address
  68. X-given.  It prompts with the address, and accepts bytes to be written
  69. X-into the file.  The bytes are written upon receipt of a newline.
  70. X-Bytes must be entered as one or two hex digits.  An EOF (normally
  71. X-ctrl/D or ctrl/Z) will end input, as will an interrupt.
  72. X-.\"
  73. X-.IP "\fBf\fP"
  74. X-Find data in the file, starting at the address
  75. X-given and continuing to the end of file, interrupt, or the second
  76. X-address if given.  It prompts for a series of bytes to be searched
  77. X-for; they must be entered as one or two hex digits each.  One line of
  78. X-bytes may be entered; the search starts upon receipt of the newline.
  79. X-.\"
  80. X-.IP "\fBq,x\fP"
  81. X-Quit.  Also known as exit.
  82. X-.SH "OPTIONS"
  83. X-.IP "\fB-r\fP"
  84. X-The file is opened for reading only.  The "e" command to enter data
  85. X-will not work.  Non-interactive patching will not work.
  86. X-.IP "\fB-w\fP"
  87. X-The file is opened for writing only.  The "d" command to display
  88. X-data and the "f" command to find data will not work.  If patching,
  89. X-the old values must be given as "XX".
  90. X-.IP "\fB-p\fP"
  91. X-The file is to be patched non-interactively.
  92. X-The next argument is the starting address for the patching,
  93. X-and the following arguments are the old and new value substitutions.
  94. X-If the old value given does not match the value found in the file, an
  95. X-error is indicated; use "XX" if the old value is unknown or if the
  96. X-file is open for writing only.
  97. X-If the new value is given as "XX", no value is written.  Allows
  98. X-skipping of bytes in the file.
  99. X-.SH BUGS
  100. X-This prog was originally written to fill a need under ms-dos, where
  101. X-the local debugger won't patch executable files!
  102. X-.PP
  103. X-Most versions of unix won't let you patch a running program.
  104. X-This means, of course, that the prog can't patch itself.
  105. X-.PP
  106. X-There should probably be a way to supress the lseek(2) attempts for
  107. X-non-seekable files.  Displaying or patching your own tty can be
  108. X-amusing.
  109. X-.SH "SEE ALSO"
  110. X-adb(1), debug(ms-dos)
  111. X-.SH "AUTHOR"
  112. X-This program and document were written by Tanner Andrews at
  113. X-CompuData, Inc. in support of the Brother John\(rg project.
  114. X-CompuData, by making them available to you,
  115. X-neither gives up any rights nor assumes any responsibility
  116. X-for damages caused by them.
  117. END_OF_FILE
  118.  
  119. echo "unshar: x-Makefile"
  120. sed s/\^X-// > Makefile <<END_OF_FILE
  121. X-
  122. X-# Makefile for "fddt"
  123. X-
  124. X-# set this as proper (use second one for xenix)
  125. X-CFLAGS =  -O
  126. X-#CFLAGS =   -O -K -Mm2
  127. X-
  128. X-fddt:    fddt.o
  129. X-    $(CC) $(CFLAGS) -o fddt  /lib/cdate.o fddt.o
  130. X-
  131. END_OF_FILE
  132.  
  133. echo "unshar: x-fddt.c"
  134. sed s/\^X-// > fddt.c <<END_OF_FILE
  135. X-
  136. X- /***************************************************************
  137. X-  *                                *
  138. X-  *            disk file patch prog            *
  139. X-  *                                *
  140. X-  ***************************************************************/
  141. X-
  142. X- /*    19-Nov-85  [ki4pv!tanner]                */
  143. X- /*    ed  20-Dec-85  [ki4pv!tanner] -- add find command    */
  144. X- /*    ed  03-Jan-86  [ki4pv!tanner] -- add exit command    */
  145. X- /*    ed  01-Jul-86  [ki4pv!tanner] -- add -p flag        */
  146. X- /*    ed  22-Oct-86  [ki4pv!tanner] -- turn off stdout buffer    */
  147. X-
  148. X-#include  <stdio.h>
  149. X-#include  <signal.h>
  150. X-
  151. X-#define     SZ        0x0100        /* size of things */
  152. X-
  153. X- /*    this program allows someone to apply patches to files
  154. X-  *    of almost any type.  it helps a lot if lseek() will work
  155. X-  *    on the file, but it is not required if the file to be
  156. X-  *    "patched" is a serial device which is really being fed
  157. X-  *    a stream of bytes.
  158. X-  *
  159. X-  *    usage:
  160. X-  *      fddt [-rw] <file>
  161. X-  *    or:
  162. X-  *      fddt [-w] <file> -p <addr> old1=new1 old2=new2 ...
  163. X-  *    where
  164. X-  *      -r    read-only; patches may not be applied
  165. X-  *      -w    write-only; old contents may not be displayed
  166. X-  *      -p    "patch" mode, starts at addr and applies patch
  167. X-  *
  168. X-  *    once a file is selected for editing, the following commands
  169. X-  *    will apply for interactive mode within the prog:
  170. X-  *     d    display data
  171. X-  *     e    enter new values
  172. X-  *     f    find data; will prompt for values
  173. X-  *     q,x    exit
  174. X-  *    all commands take either one or two addresses (if no addr
  175. X-  *    given, no work is done).  the first addr is a starting addr;
  176. X-  *    the second, if given, is an ending addr.  default end is EOF.
  177. X-  *    note that all addresses and data values are to be expressed
  178. X-  *    in hex.  new values being entered are entered as 1-byte hex
  179. X-  *    values.
  180. X-  *
  181. X-  *    patch mode is a way to non-interactively change values in the
  182. X-  *    file being edited.  see the man page.
  183. X-  *
  184. X-  *    warning:  if your unix does not have rdchk(), you may either
  185. X-  *    provide a substitute with ioctl() or eliminate the line of
  186. X-  *    code using it with a return(0) and just use ^C to interrupt
  187. X-  *    commands.  rdchk() appears new with SYS-3, replacing a V7
  188. X-  *    ioctl() call.
  189. X-  *
  190. X-  *    note for cd_txt[] -- this is supplied by a little daemon
  191. X-  *    which creates /lib/cdate.o containing today's date.  the
  192. X-  *    daemon to do this is available from "ki4pv!tanner" upon
  193. X-  *    application.  you could also eliminate the reference.
  194. X-  *
  195. X-  *    This prog and documentation (C) 1987, CompuData, Inc.
  196. X-  *    Permission is granted to use it, so long as this
  197. X-  *    copyright notice remains intact, and so long as you
  198. X-  *    don't try to sell it or claim that you wrote it.
  199. X-  *    By making this program available, CompuData neither gives
  200. X-  *    up any rights in it, nor assumes any responsibility for
  201. X-  *    any damages caused by it.
  202. X-  */
  203. X-
  204. X-      /*  important vars  */
  205. X-
  206. X-static char
  207. X-    tf_blt[] =    "FDDT   vers 1.2a  built %s\n\n",
  208. X-
  209. X-    tf_usg[] =    "? usage:  %s [-rw] <file> [-p <addr> old=new ...]\n",
  210. X-
  211. X-    tf_sup[] =    "%% %s suppressed\n",
  212. X-    tx_rd[] =    "reading",
  213. X-    tx_wr[] =    "writing",
  214. X-
  215. X-    tf_bad[] =    "? %s: bad %s: %s\n",
  216. X-    tf_bdr[] =    "? bad range: %08lX > %08lX\n",
  217. X-    tf_nos[] =    "? no search values\n",
  218. X-    tf_sek[] =    "? can't seek: %08lX\n",
  219. X-    tf_wre[] =    "? write error: file %s, off 0x%08X, n 0x%X\n",
  220. X-
  221. X-    tf_fnd[] =    "found @ 0x%08lX\n",
  222. X-    tf_nfd[] =    "not found, end @ 0x%08lX\n",
  223. X-    tf_8x[] =    "%08lX: ",
  224. X-    tf_2x[] =    "%02X ",
  225. X-
  226. X-    tf_pat[] =    "patching 0x%08lX: ",
  227. X-    tf_pr1[] =    "0x%02X",
  228. X-    tx_prx[] =    " xx ",
  229. X-    tf_per[] =    "read mismatch: exp 0x%02X, got 0x%02X\n",
  230. X-    tx_pex[] =    "patch expr",
  231. X-
  232. X-    tx_int[] =    "** intr **\n";
  233. X-
  234. X-unsigned int _fmode =    0x8000;        /* for ms-dos */
  235. X-
  236. X- /* - - - - */
  237. X-
  238. X-short int
  239. X-    stoppt,            /* "action stopped" flag */
  240. X-    rw_sup,            /* -r or -w flag */
  241. X-    patch,            /* set true if patching */
  242. X-    ed_fd;            /* fd of file to be patched */
  243. X-
  244. X-char
  245. X-    *prog_name,
  246. X-    *inbuf,            /* user input buffer */
  247. X-    *ed_fn,            /* name of file being patched */
  248. X-    *ed_buf,        /* edit buffer */
  249. X-    *match;            /* file match buffer */
  250. X-
  251. X-  /* - - - - - */
  252. X-
  253. X-extern char
  254. X-    cd_txt[];        /* /lib/cdate.o, kept by daemon */
  255. X-
  256. X- /*  = = = = =  */
  257. X-
  258. X-short int
  259. X-    do_hdr(),        /* things to do before any work */
  260. X-    do_lev(),        /* evaluate a long addr */
  261. X-    get_ln(),        /* get series of numbers */
  262. X-    get_st(),        /* get "stopped" flag */
  263. X-    pat_ev(),        /* eval expression for patch */
  264. X-    sig_st();        /* signal handler */
  265. X-
  266. X-void
  267. X-    do_opn(),        /* open the file */
  268. X-    do_pat(),        /* patch the file */
  269. X-    do_edt(),        /* edit the file */
  270. X-    do_dmp(),        /* dump part of file */
  271. X-    do_inp(),        /* input new values to file */
  272. X-    do_src(),        /* find values in file */
  273. X-    usage();
  274. X-
  275. X-  /* - - - - - */
  276. X-
  277. X-extern long int
  278. X-    lseek();
  279. X-
  280. X-extern int
  281. X-    chupper(),        /* $LOCLIB */
  282. X-    dehex();        /* $LOCLIB */
  283. X-    isprint(), iswhite(), isxdigit(),
  284. X-    rdchk();        /* $SYSDEP */ /* pending input check */
  285. X-
  286. X-extern char
  287. X-    *malloc(),
  288. X-    *strbrk(),        /* $LOCLIB */
  289. X-    *strchr();
  290. X-
  291. X-      /*  main block of prog  */
  292. X-
  293. X-main(ac, av)
  294. X-short int ac;
  295. X-char    **av;
  296. X-    {
  297. X-    register char
  298. X-        *p;
  299. X-
  300. X-    fprintf(stderr, tf_blt, cd_txt);
  301. X-
  302. X-    prog_name = **av ? *av : "FDDT";
  303. X-
  304. X-    if  (ac < 2)
  305. X-        usage();
  306. X-
  307. X-    if  (*(p = *++av) == '-')  {    /* have flag */
  308. X-        if  (((rw_sup = chupper(*++p)) != 'R') &&
  309. X-             (rw_sup != 'W'))
  310. X-            usage();
  311. X-        ++av;
  312. X-        }
  313. X-    else
  314. X-        rw_sup = 0;
  315. X-
  316. X-    ed_fn = *av;            /* get working filename */
  317. X-
  318. X-    setbuf(stdout, (char *)0);
  319. X-
  320. X-    if  ((!(ed_buf = malloc(SZ))) ||
  321. X-         (!(match = malloc(2*SZ))) ||
  322. X-         (!(inbuf = malloc(SZ))))  {
  323. X-        fprintf(stderr, "? %s: can't allocate\n", prog_name);
  324. X-        exit(1);
  325. X-        }
  326. X-
  327. X-    signal(SIGINT, sig_st);        /* catch ^C to abort command */
  328. X-
  329. X-    do_opn();            /* open the file */
  330. X-
  331. X-    if  (*++av)
  332. X-        do_pat(av);        /* patch the file */
  333. X-    else
  334. X-        do_edt();        /* edit the file */
  335. X-
  336. X-    if  (close(ed_fd))        /* close the file */
  337. X-        no_clos(ed_fn);
  338. X-
  339. X-    exit(0);
  340. X-
  341. X-    }
  342. X-
  343. X-static void usage()
  344. X-    {
  345. X-
  346. X-    fprintf(stderr, tf_usg, prog_name);
  347. X-    exit(1);
  348. X-
  349. X-    }
  350. X-
  351. X-      /*  open file to be edited  */
  352. X-
  353. X-void do_opn()
  354. X-    {
  355. X-    register short int
  356. X-        mode;
  357. X-
  358. X-    switch (rw_sup)  {        /* select file open mode */
  359. X-        case 'R':
  360. X-            mode = 0;
  361. X-            break;
  362. X-        case 'W':
  363. X-            mode = 1;
  364. X-            break;
  365. X-        default:
  366. X-            mode = 2;
  367. X-        }
  368. X-
  369. X-    if  ((ed_fd = open(ed_fn, mode)) < 0)
  370. X-        no_open(ed_fn);
  371. X-
  372. X-    }
  373. X-
  374. X-      /*  patch the file  */
  375. X-
  376. X-void do_pat(ap)
  377. X-char    **ap;
  378. X-    {
  379. X-    register char
  380. X-        *p;
  381. X-    short int
  382. X-        old, new;
  383. X-    long int
  384. X-        p_addr,            /* patch addr */
  385. X-        tmp;            /* tmp value from eval */
  386. X-    unsigned char
  387. X-        c;            /* in/out data item */
  388. X-
  389. X-    if  ((*(p = *ap) != '-') ||
  390. X-         (chupper(*++p) != 'P'))
  391. X-        usage();
  392. X-
  393. X-    if  (do_lev(*++ap, &p_addr))  {    /* eval addr */
  394. X-        fprintf(stderr, tf_bad, prog_name, "addr", *ap);
  395. X-        exit(1);
  396. X-        }
  397. X-
  398. X-    if  (lseek(ed_fd, p_addr, 0) != p_addr)  {    /* just test */
  399. X-        fprintf(stderr, tf_sek, p_addr);
  400. X-        exit(2);
  401. X-        }
  402. X-
  403. X-    for  ( ; p = *++ap ; ++p_addr )  {
  404. X-        p += pat_ev(p, &old, "old");
  405. X-        if  (*p++ != '=')  {
  406. X-            fprintf(stderr, tf_bad, prog_name, tx_pex, *ap);
  407. X-            exit(3);
  408. X-            }
  409. X-        p += pat_ev(p, &new, "new");
  410. X-        if  (*p)  {
  411. X-            fprintf(stderr, tf_bad, prog_name, tx_pex, *ap);
  412. X-            exit(4);
  413. X-            }
  414. X-        printf(tf_pat, p_addr);
  415. X-        if  (old >= 0)  {        /* match old */
  416. X-            if  (rw_sup == 'R')  {
  417. X-                fprintf(stderr, tf_sup, tx_rd);
  418. X-                exit(5);
  419. X-                }
  420. X-            if  ((lseek(ed_fd, p_addr, 0) != p_addr) ||
  421. X-                 (read(ed_fd, &c, 1) != 1) ||
  422. X-                 (c != old))  {
  423. X-                fprintf(stderr, tf_per, old, c);
  424. X-                exit(6);
  425. X-                }
  426. X-            printf(tf_pr1, old);
  427. X-            }
  428. X-        else
  429. X-            printf(tx_prx);
  430. X-        printf(" -> ");
  431. X-        if  (new >= 0)  {
  432. X-            if  (rw_sup == 'W')  {
  433. X-                fprintf(stderr, tf_sup, tx_wr);
  434. X-                exit(7);
  435. X-                }
  436. X-            c = new;
  437. X-            if  ((lseek(ed_fd, p_addr, 0) != p_addr) ||
  438. X-                 (write(ed_fd, &c, 1) != 1))  {
  439. X-                fprintf(stderr, tf_wre, ed_fn, p_addr, 1);
  440. X-                exit(8);
  441. X-                }
  442. X-            printf(tf_pr1, new);
  443. X-            }
  444. X-        else
  445. X-            printf(tx_prx);
  446. X-        printf(" ok\n");
  447. X-        }
  448. X-
  449. X-    }
  450. X-
  451. X-       /*  patch support: evaluate old/new value  */
  452. X-
  453. X-static short int pat_ev(sp, dp, err)
  454. X-char    *sp, *err;
  455. X-short int *dp;            /* result goes here */
  456. X-    {
  457. X-    register char
  458. X-        *q;
  459. X-    long int
  460. X-        tmp;
  461. X-
  462. X-    if  (chupper(*sp) == 'X')  {
  463. X-        *dp = -1;
  464. X-        return(1);
  465. X-        }
  466. X-    if  (do_lev(sp, &tmp) || (tmp < 0) || (tmp > 0xFF))  {
  467. X-        fprintf(stderr, tf_bad, prog_name, err, sp);
  468. X-        exit(3);
  469. X-        }
  470. X-    *dp = tmp;
  471. X-
  472. X-    for  ( q=sp ; isxdigit(*q) ; ++q );
  473. X-    return((short int)(q - sp));
  474. X-
  475. X-    }
  476. X-
  477. X-      /*  edit the file (top-level interaction)  */
  478. X-
  479. X-void do_edt()
  480. X-    {
  481. X-    register char
  482. X-        *p;
  483. X-    register short int
  484. X-        nrd;
  485. X-
  486. X-    while  (((nrd=read(0, inbuf, 100)) > 0) || get_st())  {
  487. X-        if  (nrd < 0)        /* ^C caused I/O err */
  488. X-            nrd = 0;
  489. X-        *(inbuf+nrd) = 0;    /* null at end-of-input */
  490. X-        if  (p = strchr(inbuf, '\n'))
  491. X-            *p = 0;
  492. X-        p = inbuf;
  493. X-        while (iswhite(*p))
  494. X-            ++p;
  495. X-        switch (chupper(*p))  {
  496. X-            case 'F':
  497. X-                do_src(p+1);
  498. X-                break;
  499. X-            case 'E':
  500. X-                do_inp(p+1);
  501. X-                break;
  502. X-            case 'D':
  503. X-                do_dmp(p+1);
  504. X-                break;
  505. X-            case 'Q':
  506. X-            case 'X':
  507. X-                return;
  508. X-            case '?':
  509. X-                printf("D-display  E-enter  F-find  Q-exit\n");
  510. X-                break;
  511. X-            default:
  512. X-                printf("unknown: %c\n", *p);
  513. X-            case 0:
  514. X-                break;
  515. X-            }
  516. X-        }
  517. X-
  518. X-    }
  519. X-
  520. X-      /*  dump values  */
  521. X-
  522. X-void do_dmp(p)
  523. X-char    *p;
  524. X-    {
  525. X-    register short int
  526. X-        sz, nd;
  527. X-    long int
  528. X-        ed_adr,
  529. X-        ed_cur,
  530. X-        ed_end,
  531. X-        lnend;
  532. X-
  533. X-    if  (do_hdr('R', p, &ed_adr, &ed_end))    /* input bad */
  534. X-        return;
  535. X-
  536. X-    ed_cur = ed_adr;        /* back to start */
  537. X-
  538. X-    do  {
  539. X-        lnend = ed_cur - (ed_cur % 16) + 15;
  540. X-        if  (lnend > ed_end)
  541. X-            lnend = ed_end;
  542. X-        sz = lnend - ed_cur + 1;
  543. X-        if  ((nd = read(ed_fd, ed_buf, sz)) < sz)
  544. X-            sz = nd;
  545. X-        if  (sz < 1)  {
  546. X-            printf("e-o-f\n");
  547. X-            break;
  548. X-            }
  549. X-        printf(tf_8x, ed_cur);
  550. X-        for  ( nd=0 ; nd<sz ; ++nd )  {
  551. X-            printf(tf_2x, *(ed_buf+nd) & 0x00FF);
  552. X-            if  (nd == 7)
  553. X-                fputc(' ', stdout);
  554. X-            }
  555. X-        fputs("  ", stdout);
  556. X-        for  ( nd=0 ; nd<sz ; ++nd )  {
  557. X-            fputc(isprint(*(ed_buf+nd)) ? *(ed_buf+nd) : '.',
  558. X-                        stdout);
  559. X-            if  (nd == 7)
  560. X-                fputc(' ', stdout);
  561. X-            }
  562. X-        fputc('\n', stdout);
  563. X-        }  while ((! get_st()) && ((ed_cur += sz) <= ed_end));
  564. X-
  565. X-    fputc('\n', stdout);
  566. X-
  567. X-    }
  568. X-
  569. X-      /*  enter new values into file  */
  570. X-
  571. X-void do_inp(p)
  572. X-register char    *p;
  573. X-    {
  574. X-    register short int
  575. X-        n;
  576. X-    long int
  577. X-        ed_adr,
  578. X-        ed_cur,
  579. X-        ed_end;
  580. X-
  581. X-    if  (do_hdr('W', p, &ed_adr, &ed_end))    /* command bad */
  582. X-        return;
  583. X-
  584. X-    ed_cur = ed_adr;
  585. X-    for ( ; (n = get_ln(ed_cur)) >= 0  ; )  {
  586. X-        if  ((n > 0) && (write(ed_fd, ed_buf, n) < n))  {
  587. X-            fprintf(stderr, tf_wre, ed_fn, ed_cur, n);
  588. X-            break;
  589. X-            }
  590. X-        if  ((ed_cur += n) > ed_end)    /* gave exit point */
  591. X-            break;
  592. X-        }
  593. X-
  594. X-    }
  595. X-
  596. X-      /*  find values in file  */
  597. X-
  598. X-#define     MATCH        (*(ed_buf+bufm) == *(match+bufo+bufm))
  599. X-
  600. X-void do_src(p)
  601. X-char    *p;
  602. X-    {
  603. X-    register short int
  604. X-        nsrc,                /* # to search for */
  605. X-        nbuf,                /* # chars in buff */
  606. X-        bufo,                /* buffer offset */
  607. X-        bufm,                /* buffer # matched */
  608. X-        nrd;
  609. X-    long int
  610. X-        ed_adr,
  611. X-        ed_cur,
  612. X-        ed_end,
  613. X-        val;
  614. X-
  615. X-    if  (do_hdr('R', p, &ed_adr, &ed_end))    /* input bad */
  616. X-        return;
  617. X-
  618. X-    ed_cur = ed_adr;        /* back to start */
  619. X-
  620. X-    if  ((nsrc = get_ln(0L)) <= 0)  {
  621. X-        printf(tf_nos);
  622. X-        return;
  623. X-        }
  624. X-
  625. X-    printf("searching...");
  626. X-    nrd = nbuf = read(ed_fd, match, 2*SZ);
  627. X-    for  ( bufo=0 ;; )  {
  628. X-        for  ( bufm=0 ; (bufm < nsrc) && MATCH ; ++bufm );
  629. X-        if  (bufm == nsrc)  {
  630. X-            printf(tf_fnd, ed_cur);
  631. X-            return;
  632. X-            }
  633. X-        ++ed_cur;        /* start at next char */
  634. X-        if  (++bufo > SZ)  {    /* must read more */
  635. X-            move(match, match+SZ, SZ);
  636. X-            bufo -= SZ;
  637. X-            nbuf -= SZ;
  638. X-            if  (get_st())    /* input, stop search */
  639. X-                nrd = 0;
  640. X-            if  (nrd && ((nrd=read(ed_fd, match+SZ, SZ)) > 0))
  641. X-                nbuf += nrd;
  642. X-            }
  643. X-        if  ((bufo >= nbuf) || (ed_cur > ed_end))  {
  644. X-            printf(tf_nfd, ed_cur);
  645. X-            return;
  646. X-            }
  647. X-        }
  648. X-
  649. X-    }
  650. X-
  651. X-      /*  common support routines  */
  652. X-
  653. X- /*  handle the command understanding for both display and edit
  654. X-  *  expects
  655. X-  *    sup        'R', 'W' if reading, writing required
  656. X-  *    p        user's input
  657. X-  *    sad, ead    ptrs to display/edit start/end addr
  658. X-  *  returns
  659. X-  *      0        good input
  660. X-  *     -1        didn't
  661. X-  */
  662. X-static short int do_hdr(sup, p, sad, ead)
  663. X-char    sup, *p;
  664. X-long int *sad, *ead;
  665. X-    {
  666. X-
  667. X-    if  (rw_sup && (rw_sup != sup))  {    /* make sure it's OK */
  668. X-        printf(tf_sup, (sup=='R') ? tx_rd : tx_wr);
  669. X-        return;
  670. X-        }
  671. X-
  672. X-    if  (do_lev(p, sad))            /* get starting addr */
  673. X-        return(-1);
  674. X-
  675. X-    *ead = 0x40000000;            /* dflt end addr */
  676. X-
  677. X-    while (iswhite(*p))            /* skip white space */
  678. X-        ++p;
  679. X-
  680. X-    if  ((p = strbrk(p, "-, ")) && do_lev(++p, ead))  {
  681. X-        printf(tf_bad, prog_name, "end", p);
  682. X-        return(-1);
  683. X-        }
  684. X-
  685. X-    if  (*ead < *sad)  {
  686. X-        printf(tf_bdr, *sad, *ead);
  687. X-        return(-1);
  688. X-        }
  689. X-
  690. X-    if  (lseek(ed_fd, *sad, 0) != *sad)  {    /* do the seek */
  691. X-        printf(tf_sek, *sad);
  692. X-        return(-1);
  693. X-        }
  694. X-
  695. X-    return(0);
  696. X-
  697. X-    }
  698. X-
  699. X- /*  evaluate an address
  700. X-  *  expects
  701. X-  *    p    ptr to addr to scan
  702. X-  *    adr    addr to receive value if we found number
  703. X-  *  returns
  704. X-  *     0    worked
  705. X-  *    -1    no addr found
  706. X-  *  note
  707. X-  *    if it works, *adr will be filled in.
  708. X-  */
  709. X-
  710. X-static short int do_lev(p, adr)
  711. X-char    *p;
  712. X-long int *adr;
  713. X-    {
  714. X-    register long int
  715. X-        val;
  716. X-
  717. X-    while (iswhite(*p))        /* skip */
  718. X-        ++p;
  719. X-
  720. X-    if  (! isxdigit(*p))
  721. X-        return(-1);
  722. X-
  723. X-    for  ( val=0 ; isxdigit(*p) ; ++p )
  724. X-        val = (val << 4) + dehex(*p);
  725. X-
  726. X-    if  (*p && (! iswhite(*p)) && (*p != '=') && (*p != '-'))
  727. X-        return(-1);
  728. X-
  729. X-    *adr = val;
  730. X-    return(0);
  731. X-
  732. X-    }
  733. X-
  734. X- /*  get a list of numbers into the edit buffer
  735. X-  *  expects
  736. X-  *    ed_cur    address to be printed in prompt
  737. X-  *  returns
  738. X-  *     -1    trouble
  739. X-  *     n    # bytes specified on line by user
  740. X-  *  fills in ed_buf with the values given
  741. X-  */
  742. X-
  743. X-static short int get_ln(ed_cur)
  744. X-long int ed_cur;
  745. X-    {
  746. X-    register char
  747. X-        *p;
  748. X-    register short int
  749. X-        n;
  750. X-    long int
  751. X-        val;
  752. X-
  753. X-    printf(tf_8x, ed_cur);            /* prompt */
  754. X-    zero(inbuf, SZ);
  755. X-    if  (read(0, p=inbuf, 200) < 1)  {    /* hit EOF */
  756. X-        fputs(" ** OK\n", stdout);
  757. X-        return(-1);
  758. X-        }
  759. X-    for  ( n=0 ; *p ; )  {            /* scan & convert */
  760. X-        if  (do_lev(p, &val) ||
  761. X-            (val > 0x00FF) || (val < 0))  {
  762. X-            printf("bad value: %s\n", p);
  763. X-            n = 0;
  764. X-            break;
  765. X-            }
  766. X-        *(ed_buf+(n++)) = val;
  767. X-        while (isxdigit(*p))
  768. X-            ++p;
  769. X-        while (isxdigit(*p))
  770. X-            ++p;
  771. X-        if  (*p == ',')
  772. X-            ++p;
  773. X-        while (iswhite(*p))
  774. X-            ++p;
  775. X-        }
  776. X-
  777. X-    return(n);
  778. X-
  779. X-    }
  780. X-
  781. X-      /*  user-attention handlers  */
  782. X-
  783. X- /*  user hits ^C, set flag to indicate same
  784. X-  *  note:  under ms-dos, signal() only works for ^C
  785. X-  *    but that's OK.  use MS-C; lattice doesn't have
  786. X-  *    signal(2).
  787. X-  */
  788. X-static short int sig_st()
  789. X-    {
  790. X-
  791. X-    signal(SIGINT, sig_st);        /* continued protection */
  792. X-    printf(tx_int);            /* ack for abuser */
  793. X-    stoppt = 1;            /* set flag */
  794. X-
  795. X-    }
  796. X-
  797. X- /*  routine to see if user wants to stop command
  798. X-  *  checks/resets "stoppt" flag set by ^C
  799. X-  *  if machine has rdchk() uses that to see if pending input
  800. X-  */
  801. X- /* $SYSDEP */
  802. X-static short int get_st()
  803. X-    {
  804. X-
  805. X-    if  (stoppt)  {            /* hit ^C */
  806. X-        stoppt = 0;        /* clear it */
  807. X-        return(1);
  808. X-        }
  809. X-
  810. X-    return(rdchk(0) > 0);        /* pending input */
  811. X-
  812. X-    }
  813. X-
  814. X-      /*  local library routines  */
  815. X-
  816. X- /*  these routines normally live in a local library.  the names
  817. X-  *  are actually left-overs from CP/M days.
  818. X-  */
  819. X-#ifndef    DONT_NEED
  820. X- /*  convert a hex digit  */
  821. X-int dehex(c)
  822. X-int    c;
  823. X-    {
  824. X-    if  ((c >= '0') && (c <= '9'))
  825. X-        return(c - '0');
  826. X-    if  ((c >= 'A') && (c <= 'F'))
  827. X-        return(c + 10 - 'A');
  828. X-    if  ((c >= 'a') && (c <= 'f'))
  829. X-        return(c + 10 - 'a');
  830. X-    return(-1);
  831. X-    }
  832. X-
  833. X- /*  find character in "breakset"  */
  834. X-char *strbrk(s1, s2)
  835. X-register char *s1, *s2;
  836. X-    {
  837. X-
  838. X-    if  (s1 && s2)                /* have strings */
  839. X-        for  ( ; *s1 ; ++s1 )        /* scan string */
  840. X-            if  (strchr(s2, *s1))    /* match any? */
  841. X-                return(s1);    /* yup, winner */
  842. X-
  843. X-    return((char *)0);
  844. X-
  845. X-    }
  846. X-
  847. X- /*  case conversion -- don't trust "toupper" or "tolower  */
  848. X-int chupper(c)
  849. X-int    c;
  850. X-    {
  851. X-    return(((c >= 'a') && (c <= 'z')) ? (c - ('a'-'A')) : c);
  852. X-    }
  853. X-
  854. X-#endif
  855. X-
  856. END_OF_FILE
  857.