home *** CD-ROM | disk | FTP | other *** search
/ NetNews Usenet Archive 1992 #18 / NN_1992_18.iso / spool / comp / sources / misc / 3804 < prev    next >
Encoding:
Text File  |  1992-08-14  |  44.5 KB  |  2,107 lines

  1. Newsgroups: comp.sources.misc
  2. Path: sparky!kent
  3. From: sjg@zen.void.oz.au (Simon J. Gerraty)
  4. Subject:  v31i075:  pdksh - Public Domain Korn Shell, Patch06b/2
  5. Message-ID: <1992Aug14.144322.21706@sparky.imd.sterling.com>
  6. Followup-To: comp.sources.d
  7. X-Md4-Signature: f152eb945962077c781d4f85dc9ac548
  8. Sender: kent@sparky.imd.sterling.com (Kent Landfield)
  9. Organization: Sterling Software
  10. References: <csm-v31i074=pdksh.093459@sparky.IMD.Sterling.COM>
  11. Date: Fri, 14 Aug 1992 14:43:22 GMT
  12. Approved: kent@sparky.imd.sterling.com
  13. Lines: 2092
  14.  
  15. Submitted-by: sjg@zen.void.oz.au (Simon J. Gerraty)
  16. Posting-number: Volume 31, Issue 75
  17. Archive-name: pdksh/patch06b
  18. Environment: UNIX
  19. Patch-To: pdksh: Volume 25, Issue 47-55
  20.  
  21. This is the second part of patch06.
  22.  
  23. Apply this patch by changing directory to the root
  24. of the source tree and using the command:
  25.  
  26.     patch -p0 < this_file
  27.  
  28. *** sh/history.c.old    Tue May 12 13:42:00 1992
  29. --- sh/history.c    Mon Aug 10 22:02:44 1992
  30. ***************
  31. *** 5,12 ****
  32.    */
  33.   
  34.   #ifndef lint
  35. ! static char *RCSid = "$Id: history.c,v 1.2 1992/04/25 08:33:28 sjg Exp $";
  36.   #endif
  37.   
  38.   #include "stdh.h"
  39.   #include <errno.h>
  40. --- 5,23 ----
  41.    */
  42.   
  43.   #ifndef lint
  44. ! static char *RCSid = "$Id: history.c,v 1.3 1992/08/10 12:02:44 sjg Exp $";
  45.   #endif
  46. + /*
  47. +  *    This file contains
  48. +  *    a)    the original in-memory history  mechanism
  49. +  *    b)    a simple file saving history mechanism done by  sjg@zen
  50. +  *        define EASY_HISTORY to get this
  51. +  *    c)    a more complicated mechanism done by  pc@hillside.co.uk
  52. +  *        that more closely follows the real ksh way of doing
  53. +  *        things. You need to have the mmap system call for this
  54. +  *        to work on your system
  55. +  */
  56. + #ifdef EASY_HISTORY
  57.   
  58.   #include "stdh.h"
  59.   #include <errno.h>
  60. ***************
  61. *** 13,22 ****
  62.   #include <setjmp.h>
  63.   #include "sh.h"
  64.   
  65. - char   *histrpl();
  66. - char  **current;
  67. - int    curpos;
  68.   static FILE *hist_fh = NULL;
  69.   static FILE *hist_open ARGS((char *mode));
  70.   #ifndef HISTFILE
  71. --- 24,29 ----
  72. ***************
  73. *** 23,29 ****
  74. --- 30,80 ----
  75.   # define HISTFILE ".pdksh_hist"
  76.   #endif
  77.   
  78. + #else
  79. + /*    Defines and includes for the complicated case */
  80. + #include "stdh.h"
  81. + #include <sys/types.h>
  82. + #include <sys/stat.h>
  83. + #include <sys/file.h>
  84. + #include <sys/mman.h>
  85. + #include <errno.h>
  86. + #include <setjmp.h>
  87. + #include "sh.h"
  88. + int    histsize = HISTORY;    /* size of saved history */
  89. + char   **history;        /* saved commands */
  90. + char  **histptr;        /* last history item */
  91. + int    histpush;        /* number of pushed fc commands */
  92. + /*
  93. +  *    variables for handling the data file
  94. +  */
  95. + static char    *hname;
  96. + static int    histfd;
  97. + static int    hsize;
  98. + static int    hstarted;
  99. + static int hist_count_lines ARGS((unsigned char *, int));
  100. + static int hist_shrink ARGS((unsigned char *, int));
  101. + static unsigned char *hist_skip_back ARGS((unsigned char *,int *,int));
  102. + static void histload ARGS((Source *, unsigned char *, int));
  103. + static void histinsert ARGS((Source *, int, unsigned char *));
  104. + static void writehistfile ARGS((int, char *));
  105. + static int sprinkle ARGS((int));
  106. + #ifdef MAP_FILE
  107. + #define    MAP_FLAGS    MAP_FILE|MAP_PRIVATE
  108. + #else
  109. + #define    MAP_FLAGS    MAP_PRIVATE
  110. + #endif
  111. + #endif    /* of EASY_HISTORY */
  112.     
  113. + char   *histrpl();
  114. + char  **current;
  115. + int    curpos;
  116.   c_fc(wp)
  117.       register char **wp;
  118.   {
  119. ***************
  120. *** 93,99 ****
  121. --- 144,154 ----
  122.           else
  123.               histrpl(*hp, pat, rep, gflag);
  124.           histbackup();
  125. + #ifdef EASY_HISTORY
  126.           histsave(line); 
  127. + #else
  128. +         histsave(source->line+1, line, 1);
  129. + #endif
  130.           histpush--; 
  131.           line[0] = '\0';
  132.           return 0;
  133. ***************
  134. *** 155,161 ****
  135. --- 210,220 ----
  136.       setvbuf(f, (char *)NULL, _IOFBF, BUFSIZ);
  137.       /* we push the editted lines onto the history list */
  138.       while (fgets(line, sizeof(line), f) != NULL) {
  139. + #ifdef EASY_HISTORY
  140.           histsave(line); 
  141. + #else
  142. +         histsave(source->line, line, 1); 
  143. + #endif
  144.           histpush--; 
  145.       }
  146.       line[0] = '\0';
  147. ***************
  148. *** 181,207 ****
  149.   }
  150.   
  151.   /*
  152. -  * save command in history
  153. -  */
  154. - void
  155. - histsave(cmd)
  156. -     char *cmd;
  157. - {
  158. -     register char **hp = histptr;
  159. -     char *cp;
  160. -     if (++hp >= history + HISTORY) { /* remove oldest command */
  161. -         afree((void*)*history, APERM);
  162. -         for (hp = history; hp < history + HISTORY - 1; hp++)
  163. -             hp[0] = hp[1];
  164. -     }
  165. -     *hp = strsave(cmd, APERM);
  166. -     if ((cp = strchr(*hp, '\n')) != NULL)
  167. -         *cp = '\0';
  168. -     histptr = hp;
  169. - }
  170. - /*
  171.    * get pointer to history given pattern
  172.    * pattern is a number or string
  173.    */
  174. --- 240,245 ----
  175. ***************
  176. *** 260,265 ****
  177. --- 298,397 ----
  178.   }
  179.   
  180.   /*
  181. +  * Return the current position.
  182. +  */
  183. + char **
  184. + histpos()
  185. + {
  186. +     return current;
  187. + }
  188. + int
  189. + histN()
  190. + {
  191. +     return curpos;
  192. + }
  193. + int
  194. + histnum(n)
  195. + {
  196. +     int    last = histptr - history;
  197. +     if (n < 0 || n >= last) {
  198. +         current = histptr;
  199. +         curpos = last;
  200. +         return last;
  201. +     }  else {
  202. +         current = &history[n];
  203. +         curpos = n;
  204. +         return n;
  205. +     }
  206. + }
  207. + /*
  208. +  * This will become unecessary if histget is modified to allow
  209. +  * searching from positions other than the end, and in either 
  210. +  * direction.
  211. +  */
  212. + char *
  213. + findhist(start, fwd, str)
  214. +     int    start;
  215. +     int    fwd;
  216. +     char     *str;
  217. + {
  218. +     int     pos = start;
  219. +     char     *line, *last;
  220. +     /* XXX check that we are valid after this */
  221. +     if (fwd)
  222. +         pos++;
  223. +     else
  224. +         pos--;
  225. +     histnum(pos);
  226. +     line = *histpos();
  227. +     do {
  228. +         last = line;
  229. +         if (strstr(line, str) != 0) {
  230. +             /* keep position current */
  231. +             return (line);
  232. +         }
  233. +         if (fwd)
  234. +             pos++;
  235. +         else
  236. +             pos--;
  237. +         histnum(pos);
  238. +         line = *histpos();
  239. +     } while (line && *line && line != last && pos>0);
  240. +     histnum(start);
  241. +     if (pos <= 0)
  242. +         return (char*)-1; /* TODO */
  243. +     return NULL;
  244. + }
  245. + #ifdef EASY_HISTORY
  246. + /*
  247. +  * save command in history
  248. +  */
  249. + void
  250. + histsave(cmd)
  251. +     char *cmd;
  252. + {
  253. +     register char **hp = histptr;
  254. +     char *cp;
  255. +     if (++hp >= history + HISTORY) { /* remove oldest command */
  256. +         afree((void*)*history, APERM);
  257. +         for (hp = history; hp < history + HISTORY - 1; hp++)
  258. +             hp[0] = hp[1];
  259. +     }
  260. +     *hp = strsave(cmd, APERM);
  261. +     if ((cp = strchr(*hp, '\n')) != NULL)
  262. +         *cp = '\0';
  263. +     histptr = hp;
  264. + }
  265. + /*
  266.    * 92-04-25 <sjg@zen>
  267.    * A simple history file implementation.
  268.    * At present we only save the history when we exit.
  269. ***************
  270. *** 293,298 ****
  271. --- 425,433 ----
  272.     
  273.   }
  274.   
  275. + void
  276. + init_histvec()
  277. + {    ;    }
  278.   
  279.   /*
  280.    * save our history.
  281. ***************
  282. *** 351,426 ****
  283.     return fopen(rcp, mode);
  284.   }
  285.   
  286.   
  287.   
  288.   /*
  289. !  * Return the current position.
  290.    */
  291. ! char **
  292. ! histpos()
  293.   {
  294. !     return current;
  295.   }
  296.   
  297. ! int
  298. ! histN()
  299.   {
  300. !     return curpos;
  301.   }
  302.   
  303. ! int
  304. ! histnum(n)
  305.   {
  306. !     int    last = histptr - history;
  307.   
  308. !     if (n < 0 || n >= last) {
  309. !         current = histptr;
  310. !         curpos = last;
  311. !         return last;
  312. !     }  else {
  313. !         current = &history[n];
  314. !         curpos = n;
  315. !         return n;
  316.       }
  317.   }
  318.   
  319.   /*
  320. !  * This will become unecessary if histget is modified to allow
  321. !  * searching from positions other than the end, and in either 
  322. !  * direction.
  323.    */
  324. ! char *
  325. ! findhist(start, fwd, str)
  326. !     int    start;
  327. !     int    fwd;
  328. !     char     *str;
  329.   {
  330. !     int     pos = start;
  331. !     char     *line, *last;
  332.   
  333. !     /* XXX check that we are valid after this */
  334. !     if (fwd)
  335. !         pos++;
  336. !     else
  337. !         pos--;
  338. !     histnum(pos);
  339. !     line = *histpos();
  340. !     do {
  341. !         last = line;
  342. !         if (strstr(line, str) != 0) {
  343. !             /* keep position current */
  344. !             return (line);
  345.           }
  346. !         if (fwd)
  347. !             pos++;
  348. !         else
  349. !             pos--;
  350. !         histnum(pos);
  351. !         line = *histpos();
  352. !     } while (line && *line && line != last && pos>0);
  353.   
  354. !     histnum(start);
  355. !     if (pos <= 0)
  356. !         return (char*)-1; /* TODO */
  357.       return NULL;
  358.   }
  359. --- 486,974 ----
  360.     return fopen(rcp, mode);
  361.   }
  362.   
  363. + #else /* EASY_HISTORY */
  364.   
  365. + /*
  366. +  *    Routines added by Peter Collinson BSDI(Europe)/Hillside Systems to
  367. +  *    a) permit HISTSIZE to control number of lines of history stored
  368. +  *    b) maintain a physical history file
  369. +  *
  370. +  *    It turns out that there is a lot of ghastly hackery here
  371. +  */
  372.   
  373.   /*
  374. !  * save command in history
  375.    */
  376. ! void
  377. ! histsave(lno, cmd, dowrite)
  378. !     int lno;
  379. !     char *cmd;
  380. !     int dowrite;
  381.   {
  382. !     register char **hp;
  383. !     char *cp;
  384. !     cmd = strsave(cmd, APERM);
  385. !     if ((cp = strchr(cmd, '\n')) != NULL)
  386. !         *cp = '\0';
  387. !     if (histfd && dowrite)
  388. !         writehistfile(lno, cmd);
  389. !     hp = histptr;
  390. !         
  391. !     if (++hp >= history + histsize) { /* remove oldest command */
  392. !         afree((void*)*history, APERM);
  393. !         for (hp = history; hp < history + histsize - 1; hp++)
  394. !             hp[0] = hp[1];
  395. !     }
  396. !     *hp = cmd;
  397. !     histptr = hp;
  398.   }
  399.   
  400. ! /*
  401. !  *    set history
  402. !  *    this means reallocating the dataspace
  403. !  */
  404. ! void
  405. ! sethistsize(n)
  406. !     int n;
  407.   {
  408. !     int    offset;
  409. !     
  410. !     if (n != histsize) {
  411. !         offset = histptr - history;
  412. !         history = (char **)aresize(history, n*sizeof(char *), APERM);
  413. !         if (n < histsize && offset > histsize)
  414. !             offset = histsize;
  415. !         histsize = n;
  416. !         histptr = history + offset;
  417. !     }
  418.   }
  419.   
  420. ! /*
  421. !  *    set history file
  422. !  *    This can mean reloading/resetting/starting history file
  423. !  *    maintenance
  424. !  */
  425. ! void
  426. ! sethistfile(name)
  427. !     char *name;
  428.   {
  429. !     /* if not started then nothing to do */
  430. !     if (hstarted == 0)
  431. !         return;
  432.   
  433. !     /* if the name is the same as the name we have */
  434. !     if (hname && strcmp(hname, name) == 0)
  435. !         return;
  436. !     /*
  437. !      * its a new name - possibly
  438. !      */
  439. !     if (histfd) {
  440. !         /* yes the file is open */
  441. !         (void) close(histfd);
  442. !         histfd = 0;
  443. !         hsize = 0;
  444. !         afree(hname, APERM);
  445. !         hname = NULL;
  446. !         /* let's reset the history */
  447. !         histptr = history - 1;
  448. !         source->line = 0;
  449.       }
  450. +     hist_init(source);
  451.   }
  452.   
  453.   /*
  454. !  *    initialise the history vector
  455.    */
  456. ! void
  457. ! init_histvec()
  458.   {
  459. !     if (history == (char **)NULL) {
  460. !         history = (char **)alloc(histsize*sizeof (char *), APERM);
  461. !         histptr = history-1;
  462. !     }
  463. ! }
  464. !     
  465. ! /*
  466. !  *    Write history data to a file nominated by HISTFILE
  467. !  *    if HISTFILE is unset then history still happens, but
  468. !  *    the data is not written to a file
  469. !  *    All copies of ksh looking at the file will maintain the
  470. !  *    same history. This is ksh behaviour.
  471. !  *
  472. !  *    This stuff uses mmap()
  473. !  *    if your system ain't got it - then you'll have to undef HISTORYFILE
  474. !  */
  475. !     
  476. ! /*
  477. !  *    Open a history file
  478. !  *    Format is:
  479. !  *    Bytes 1, 2: HMAGIC - just to check that we are dealing with
  480. !  *            the correct object
  481. !  *    Then follows a number of stored commands
  482. !  *    Each command is
  483. !  *    <command byte><command number(4 bytes)><bytes><null>
  484. !  */
  485. ! #define HMAGIC1        0xab
  486. ! #define HMAGIC2        0xcd
  487. ! #define COMMAND        0xff
  488.   
  489. ! void
  490. ! hist_init(s)
  491. !     Source *s;
  492. ! {
  493. !     unsigned char    *base;
  494. !     int    lines;
  495. !     int    bytes;
  496. !     
  497. !     hstarted = 1;
  498. !     
  499. !     if (flag[FTALKING] == 0)
  500. !         return;
  501. !     hname = strval(global("HISTFILE"));
  502. !     if (hname == NULL)
  503. !         return;
  504. !     hname = strsave(hname, APERM);
  505. !   retry:
  506. !     /* we have a file and are interactive */
  507. !     if ((histfd = open(hname, O_RDWR|O_CREAT|O_APPEND, 0600)) < 0)
  508. !         return;
  509. !     histfd = fcntl(histfd, F_DUPFD, FDBASE);
  510. !     
  511. !     (void) fcntl(histfd, F_SETFD, 1); /* close on exec */
  512. !     
  513. !     (void) flock(histfd, LOCK_EX);
  514. !     hsize = lseek(histfd, 0L, L_XTND);
  515. !     if (hsize == 0) {
  516. !         /* add magic */
  517. !         if (sprinkle(histfd)) {
  518. !             hist_finish();
  519. !             return;
  520.           }
  521. !     }
  522. !     else if (hsize > 0) {
  523. !         /*
  524. !          * we have some data
  525. !          */
  526. !         base = (unsigned char *)mmap(0, hsize, PROT_READ, MAP_FLAGS, histfd, 0);
  527. !         /*
  528. !          * check on its validity
  529. !          */
  530. !         if ((int)base == -1 || *base != HMAGIC1 || base[1] != HMAGIC2) {
  531. !             if ((int)base !=  -1)
  532. !                 munmap((caddr_t)base, hsize);
  533. !             hist_finish();
  534. !             unlink(hname);
  535. !             goto retry;
  536. !         }
  537. !         if (hsize > 2) {
  538. !             lines = hist_count_lines(base+2, hsize-2);
  539. !             if (lines > histsize) {
  540. !                 /* we need to make the file smaller */
  541. !                 if (hist_shrink(base, hsize))
  542. !                     unlink(hname);
  543. !                 munmap((caddr_t)base, hsize);
  544. !                 hist_finish();
  545. !                 goto retry;
  546. !             }
  547. !         }
  548. !         histload(s, base+2, hsize-2);
  549. !         munmap((caddr_t)base, hsize);
  550. !     }
  551. !     (void) flock(histfd, LOCK_UN);
  552. !     hsize = lseek(histfd, 0L, L_XTND);
  553. ! }
  554.   
  555. ! typedef enum state {
  556. !     shdr,        /* expecting a header */
  557. !     sline,        /* looking for a null byte to end the line */
  558. !     sn1,        /* bytes 1 to 4 of a line no */
  559. !     sn2, sn3, sn4,
  560. ! } State;
  561. ! static int
  562. ! hist_count_lines(base, bytes)
  563. !     register unsigned char *base;
  564. !     register int bytes;
  565. ! {
  566. !     State state = shdr;
  567. !     register lines = 0;
  568. !     
  569. !     while (bytes--) {
  570. !         switch (state)
  571. !         {
  572. !         case shdr:
  573. !             if (*base == COMMAND)
  574. !                 state = sn1;
  575. !             break;
  576. !         case sn1:
  577. !             state = sn2; break;
  578. !         case sn2:
  579. !             state = sn3; break;
  580. !         case sn3:
  581. !             state = sn4; break;
  582. !         case sn4:
  583. !             state = sline; break;
  584. !         case sline:
  585. !             if (*base == '\0')
  586. !                 lines++, state = shdr;
  587. !         }
  588. !         base++;
  589. !     }
  590. !     return lines;
  591. ! }
  592. ! /*
  593. !  *    Shrink the history file to histsize lines
  594. !  */
  595. ! static int
  596. ! hist_shrink(oldbase, oldbytes)
  597. !     unsigned char *oldbase;
  598. !     int oldbytes;
  599. ! {
  600. !     int fd;
  601. !     char    nfile[1024];
  602. !     struct    stat statb;
  603. !     unsigned char *nbase = oldbase;
  604. !     int nbytes = oldbytes;
  605. !     nbase = hist_skip_back(nbase, &nbytes, histsize);
  606. !     if (nbase == NULL)
  607. !         return 1;
  608. !     if (nbase == oldbase)
  609. !         return 0;
  610. !     
  611. !     /*
  612. !      *    create temp file
  613. !      */
  614. !     (void) sprintf(nfile, "%s.%d", hname, getpid());
  615. !     if ((fd = creat(nfile, 0600)) < 0)
  616. !         return 1;
  617. !     if (sprinkle(fd)) {
  618. !         close(fd);
  619. !         unlink(nfile);
  620. !         return 1;
  621. !     }
  622. !     if (write(fd, nbase, nbytes) != nbytes) {
  623. !         close(fd);
  624. !         unlink(nfile);
  625. !         return 1;
  626. !     }
  627. !     /*
  628. !      *    worry about who owns this file
  629. !      */
  630. !     if (fstat(histfd, &statb) >= 0)
  631. !         fchown(fd, statb.st_uid, statb.st_gid);
  632. !     close(fd);
  633. !     
  634. !     /*
  635. !      *    rename
  636. !      */
  637. !     if (rename(nfile, hname) < 0)
  638. !         return 1;
  639. !     return 0;
  640. ! }
  641. !     
  642. ! /*
  643. !  *    find a pointer to the data `no' back from the end of the file
  644. !  *    return the pointer and the number of bytes left
  645. !  */
  646. ! static unsigned char *
  647. ! hist_skip_back(base, bytes, no)
  648. !     unsigned char *base;
  649. !     int *bytes;
  650. !     int no;
  651. ! {
  652. !     register int lines = 0;
  653. !     register unsigned char *ep;
  654. !     
  655. !     for (ep = base + *bytes; ep > base; ep--)
  656. !     {
  657. !         while (*ep != COMMAND) {
  658. !             if (--ep == base)
  659. !                 break;
  660. !         }
  661. !         if (++lines == no) {
  662. !             *bytes = *bytes - ((char *)ep - (char *)base);
  663. !             return ep;
  664. !         }
  665. !     }
  666. !     if (ep > base)
  667. !         return base;
  668.       return NULL;
  669.   }
  670. + /*
  671. +  *    load the history structure from the stored data
  672. +  */
  673. + static void
  674. + histload(s, base, bytes)
  675. +     Source *s;
  676. +     register unsigned char *base;
  677. +     register int bytes;
  678. + {
  679. +     State state;
  680. +     int    lno;
  681. +     unsigned char    *line;
  682. +     
  683. +     for (state = shdr; bytes-- > 0; base++) {
  684. +         switch (state) {
  685. +         case shdr:
  686. +             if (*base == COMMAND)
  687. +                 state = sn1;
  688. +             break;
  689. +         case sn1:
  690. +             lno = (((*base)&0xff)<<24);
  691. +             state = sn2;
  692. +             break;
  693. +         case sn2:
  694. +             lno |= (((*base)&0xff)<<16);
  695. +             state = sn3;
  696. +             break;
  697. +         case sn3:
  698. +             lno |= (((*base)&0xff)<<8);
  699. +             state = sn4;
  700. +             break;
  701. +         case sn4:
  702. +             lno |= (*base)&0xff;
  703. +             line = base+1;
  704. +             state = sline;
  705. +             break;
  706. +         case sline:
  707. +             if (*base == '\0') {
  708. +                 /* worry about line numbers */
  709. +                 if (histptr >= history && lno-1 != s->line) {
  710. +                     /* a replacement ? */
  711. +                     histinsert(s, lno, line);
  712. +                 }
  713. +                 else {
  714. +                     s->line = lno;
  715. +                     histsave(lno, (char *)line, 0);
  716. +                 }
  717. +                 state = shdr;
  718. +             }
  719. +         }
  720. +     }
  721. + }
  722. +                 
  723. + /*
  724. +  *    Insert a line into the history at a specified number
  725. +  */
  726. + static void
  727. + histinsert(s, lno, line)
  728. +     Source *s;
  729. +     int lno;
  730. +     unsigned char *line;
  731. + {
  732. +     register char **hp;
  733. +     
  734. +     if (lno >= s->line-(histptr-history) && lno <= s->line) {
  735. +         hp = &histptr[lno-s->line];
  736. +         if (*hp)
  737. +             afree((void*)*hp, APERM);
  738. +         *hp = strsave((char *)line, APERM);
  739. +     }
  740. + }
  741. + /*
  742. +  *    write a command to the end of the history file
  743. +  *    This *MAY* seem easy but it's also necessary to check
  744. +  *    that the history file has not changed in size.
  745. +  *    If it has - then some other shell has written to it
  746. +  *    and we should read those commands to update our history
  747. +  */
  748. + static void
  749. + writehistfile(lno, cmd)
  750. +     int lno;
  751. +     char *cmd;
  752. + {
  753. +     int    sizenow;
  754. +     unsigned char    *base;
  755. +     unsigned char    *new;
  756. +     int    bytes;
  757. +     char    hdr[5];
  758. +     
  759. +     (void) flock(histfd, LOCK_EX);
  760. +     sizenow = lseek(histfd, 0L, L_XTND);
  761. +     if (sizenow != hsize) {
  762. +         /*
  763. +          *    Things have changed
  764. +          */
  765. +         if (sizenow > hsize) {
  766. +             /* someone has added some lines */
  767. +             bytes = sizenow - hsize;
  768. +             base = (unsigned char *)mmap(0, sizenow, PROT_READ, MAP_FLAGS, histfd, 0);
  769. +             if ((int)base == -1)
  770. +                 goto bad;
  771. +             new = base + hsize;
  772. +             if (*new != COMMAND) {
  773. +                 munmap((caddr_t)base, sizenow);
  774. +                 goto bad;
  775. +             }
  776. +             source->line--;
  777. +             histload(source, new, bytes);
  778. +             source->line++;
  779. +             lno = source->line;
  780. +             munmap((caddr_t)base, sizenow);
  781. +             hsize = sizenow;
  782. +         } else {
  783. +             /* it has shrunk */
  784. +             /* but to what? */
  785. +             /* we'll give up for now */
  786. +             goto bad;
  787. +         }
  788. +     }
  789. +     /*
  790. +      *    we can write our bit now
  791. +      */
  792. +     hdr[0] = COMMAND;
  793. +     hdr[1] = (lno>>24)&0xff;
  794. +     hdr[2] = (lno>>16)&0xff;
  795. +     hdr[3] = (lno>>8)&0xff;
  796. +     hdr[4] = lno&0xff;
  797. +     (void) write(histfd, hdr, 5);
  798. +     (void) write(histfd, cmd, strlen(cmd)+1);
  799. +     hsize = lseek(histfd, 0L, L_XTND);
  800. +     (void) flock(histfd, LOCK_UN);
  801. +     return;
  802. + bad:
  803. +     hist_finish();
  804. + }
  805. + void
  806. + hist_finish()
  807. + {
  808. +     (void) flock(histfd, LOCK_UN);
  809. +     (void) close(histfd);
  810. +     histfd = 0;
  811. + }
  812. + /*
  813. +  *    add magic to the history file
  814. +  */
  815. + static int
  816. + sprinkle(fd)
  817. +     int fd;
  818. + {
  819. +     static char mag[] = { HMAGIC1, HMAGIC2 };
  820. +     return(write(fd, mag, 2) != 2);
  821. + }
  822. + #endif
  823. *** sh/io.c.old    Tue May 12 13:42:00 1992
  824. --- sh/io.c    Mon Aug 10 22:02:49 1992
  825. ***************
  826. *** 3,9 ****
  827.    */
  828.   
  829.   #ifndef lint
  830. ! static char *RCSid = "$Id: io.c,v 1.2 1992/04/25 08:33:28 sjg Exp $";
  831.   #endif
  832.   
  833.   #include "stdh.h"
  834. --- 3,9 ----
  835.    */
  836.   
  837.   #ifndef lint
  838. ! static char *RCSid = "$Id: io.c,v 1.3 1992/08/10 12:02:49 sjg Exp $";
  839.   #endif
  840.   
  841.   #include "stdh.h"
  842. ***************
  843. *** 99,109 ****
  844. --- 99,114 ----
  845.       if (shf[fd] != NULL)
  846.           return;
  847.       if (fd <= 2)
  848. + #ifndef _BSDI
  849.   #ifdef _MINIX
  850.           /* ? */;
  851.   #else
  852.           _iob[fd]._flag = 0; /* re-use stdin, stdout, stderr */
  853.   #endif
  854. + #else
  855. +         /* Chris Torek's stdio replacement */
  856. +         __sF[fd]._flags = 0;
  857. + #endif
  858.       shf[fd] = fdopen(fd, "r+");
  859.       if (shf[fd] == NULL)
  860.           return;
  861. ***************
  862. *** 117,123 ****
  863. --- 122,131 ----
  864.       int fd;
  865.   {
  866.       if (shf[fd] != NULL) {
  867. + #ifndef _BSDI
  868. +         /* Chris Torek's stdio replacement */
  869.           fseek(shf[fd], 0L, 1); /* V7 derived */
  870. + #endif
  871.           fflush(shf[fd]);    /* standard C */
  872.       }
  873.   }
  874. *** sh/jobs.c.old    Tue May 12 13:42:00 1992
  875. --- sh/jobs.c    Mon Aug 10 22:02:52 1992
  876. ***************
  877. *** 2,8 ****
  878.    * Process and job control
  879.    */
  880.   #ifndef lint
  881. ! static char *RCSid = "$Id: jobs.c,v 1.4 1992/04/27 07:14:26 sjg Exp $";
  882.   #endif
  883.   
  884.   /*
  885. --- 2,8 ----
  886.    * Process and job control
  887.    */
  888.   #ifndef lint
  889. ! static char *RCSid = "$Id: jobs.c,v 1.5 1992/08/10 12:02:52 sjg Exp $";
  890.   #endif
  891.   
  892.   /*
  893. ***************
  894. *** 14,23 ****
  895.    *    make %+ be jobs, %- be jobs->next.
  896.    *    do not JFREE members of pipeline.
  897.    *    consider procs[] related critical sections.
  898. -  *    signal(SIGCHLD, j_sigchld) should be
  899. -  *    sigaction(SIGCHLD, sigchld, NULL),
  900. -  *    with sigchld.sa_flags = SA_RESTART.
  901. -  *    There is a simple work-around if there is no SA_RESTART.
  902.    */
  903.   
  904.   #include "stdh.h"
  905. --- 14,19 ----
  906. ***************
  907. *** 29,34 ****
  908. --- 25,34 ----
  909.   #include <sys/wait.h>
  910.   #include "sh.h"
  911.   #ifdef JOBS
  912. + #ifdef _BSDI
  913. + #define _BSD
  914. + #define WIFCORED(x) WCOREDUMP(x)
  915. + #endif
  916.   #ifdef _BSD
  917.   #include <sys/ioctl.h>
  918.   #else
  919. ***************
  920. *** 101,107 ****
  921. --- 101,111 ----
  922.   #else
  923.   #define WAIT_T int
  924.   #endif
  925. + #ifdef _BSDI
  926. + #undef WAIT_T
  927. + #define WAIT_T int
  928.   #endif
  929. + #endif
  930.   #ifndef SA_RESTART
  931.   #define SA_RESTART    0
  932.   #endif
  933. ***************
  934. *** 313,319 ****
  935.       j->state = JRUN;
  936.   
  937.       /* stdio buffer must be flushed and invalidated */
  938. !     for (i = 0; i < NUFILE; i++)
  939.           flushshf(i);
  940.   
  941.       /* create child process */
  942. --- 317,323 ----
  943.       j->state = JRUN;
  944.   
  945.       /* stdio buffer must be flushed and invalidated */
  946. !     for (i = (flags&XXWHL) ? 1 : 0; i < NUFILE; i++)
  947.           flushshf(i);
  948.   
  949.       /* create child process */
  950. *** sh/lex.c.old    Tue May 12 13:42:00 1992
  951. --- sh/lex.c    Mon Aug 10 22:02:55 1992
  952. ***************
  953. *** 3,9 ****
  954.    */
  955.   
  956.   #ifndef lint
  957. ! static char *RCSid = "$Id: lex.c,v 1.2 1992/04/25 08:33:28 sjg Exp $";
  958.   #endif
  959.   
  960.   #include "stdh.h"
  961. --- 3,9 ----
  962.    */
  963.   
  964.   #ifndef lint
  965. ! static char *RCSid = "$Id: lex.c,v 1.3 1992/08/10 12:02:55 sjg Exp $";
  966.   #endif
  967.   
  968.   #include "stdh.h"
  969. ***************
  970. *** 15,23 ****
  971. --- 15,25 ----
  972.   #include "expand.h"
  973.   
  974.       int    ttyfd = -1;        /* tty fd for edit and jobs */
  975. + #ifdef EASY_HISTORY
  976.       char   *history[HISTORY];    /* saved commands */
  977.       char  **histptr = history - 1;    /* last history item */
  978.       int    histpush;        /* number of pushed fc commands */
  979. + #endif
  980.   
  981.   /* we set s->str to NULLSTR instead of "", so that ungetsc() works */
  982.   static    char    nullstr [] = {0, 0};
  983. ***************
  984. *** 561,567 ****
  985. --- 563,573 ----
  986.                       s->line--;
  987.                   } else {
  988.                       s->str = &line[c];
  989. + #ifdef EASY_HISTORY
  990.                       histsave(s->str);
  991. + #else
  992. +                     histsave(s->line, s->str, 1);
  993. + #endif
  994.                   }
  995.               }
  996.               break;
  997. *** sh/lex.h.old    Tue May 12 13:42:00 1992
  998. --- sh/lex.h    Mon Aug 10 22:02:58 1992
  999. ***************
  1000. *** 2,8 ****
  1001.    * Source input, lexer and parser
  1002.    */
  1003.   
  1004. ! /* $Id: lex.h,v 1.2 1992/04/25 08:33:28 sjg Exp $ */
  1005.   
  1006.   #define    IDENT    64
  1007.   
  1008. --- 2,8 ----
  1009.    * Source input, lexer and parser
  1010.    */
  1011.   
  1012. ! /* $Id: lex.h,v 1.3 1992/08/10 12:02:58 sjg Exp $ */
  1013.   
  1014.   #define    IDENT    64
  1015.   
  1016. ***************
  1017. *** 79,84 ****
  1018. --- 79,85 ----
  1019.   #define    REDIR    275
  1020.   #define    MPAREN    276        /* () */
  1021.   #define    MDPAREN    277        /* (( )) */
  1022. + #define SELECT    278        /* ksh */
  1023.   #define    YYERRCODE 300
  1024.   
  1025.   /* flags to yylex */
  1026. ***************
  1027. *** 103,109 ****
  1028. --- 104,115 ----
  1029.   
  1030.   #define    HISTORY    100        /* size of saved history */
  1031.   
  1032. + #ifdef EASY_HISTORY
  1033.   extern    char   *history [HISTORY];    /* saved commands */
  1034. + #else
  1035. + extern    int    histsize;    /* history size */
  1036. + extern    char  **history;    /* saved commands */
  1037. + #endif
  1038.   extern    char  **histptr;    /* last history item */
  1039.   extern    int    histpush;    /* number of pushed fc commands */
  1040.   
  1041. *** sh/main.c.old    Tue May 12 13:42:00 1992
  1042. --- sh/main.c    Mon Aug 10 22:03:00 1992
  1043. ***************
  1044. *** 3,9 ****
  1045.    */
  1046.   
  1047.   #ifndef lint
  1048. ! static char *RCSid = "$Id: main.c,v 1.4 1992/04/29 06:25:47 sjg Exp $";
  1049.   #endif
  1050.   
  1051.   #define    Extern                /* define Externs in sh.h */
  1052. --- 3,9 ----
  1053.    */
  1054.   
  1055.   #ifndef lint
  1056. ! static char *RCSid = "$Id: main.c,v 1.5 1992/08/10 12:03:00 sjg Exp $";
  1057.   #endif
  1058.   
  1059.   #define    Extern                /* define Externs in sh.h */
  1060. ***************
  1061. *** 37,45 ****
  1062.   
  1063.   static    const    char   initsubs [] = 
  1064.   #ifdef sun                /* sun's don't have a real /bin */
  1065. !   "${SHELL:=/bin/sh} ${PATH:=/usr/bin:/usr/ucb:.} ${HOME:=/} ${PS1:=$ } ${PS2:=> } ${MAILCHECK:=600}";
  1066.   #else
  1067. !   "${SHELL:=/bin/sh} ${PATH:=/bin:/usr/bin:.} ${HOME:=/} ${PS1:=$ } ${PS2:=> } ${MAILCHECK:=600}";
  1068.   #endif
  1069.   
  1070.   static    const    char *initcoms [] = {
  1071. --- 37,45 ----
  1072.   
  1073.   static    const    char   initsubs [] = 
  1074.   #ifdef sun                /* sun's don't have a real /bin */
  1075. !   "${SHELL:=/bin/sh} ${PATH:=/usr/bin:/usr/ucb:.} ${HOME:=/} ${PS1:=$ } ${PS2:=> } ${PS3:=#? } ${MAILCHECK:=600}";
  1076.   #else
  1077. !   "${SHELL:=/bin/sh} ${PATH:=/bin:/usr/bin:.} ${HOME:=/} ${PS1:=$ } ${PS2:=> } ${PS3:=#? } ${MAILCHECK:=600}";
  1078.   #endif
  1079.   
  1080.   static    const    char *initcoms [] = {
  1081. ***************
  1082. *** 52,58 ****
  1083.         "history=fc -l", "r=fc -e -", "nohup=nohup ",
  1084.         "login=exec login", "newgrp=exec newgrp",
  1085.         "type=whence -v", "functions=typeset -f",
  1086. !       "echo=print", "true=:", "false=let", "[=\\[", NULL,
  1087.       NULL
  1088.   };
  1089.   
  1090. --- 52,64 ----
  1091.         "history=fc -l", "r=fc -e -", "nohup=nohup ",
  1092.         "login=exec login", "newgrp=exec newgrp",
  1093.         "type=whence -v", "functions=typeset -f",
  1094. !       "echo=print", "true=:", "false=let", "[=\\[",
  1095. ! #ifdef JOBS
  1096. !       "suspend=kill -STOP $$",
  1097. ! #endif
  1098. !       NULL,
  1099. !     
  1100.       NULL
  1101.   };
  1102.   
  1103. ***************
  1104. *** 135,140 ****
  1105. --- 141,148 ----
  1106.       tinit(&lexicals, APERM);
  1107.       tinit(&homedirs, APERM);
  1108.   
  1109. +     init_histvec();
  1110. +     
  1111.       /* import enviroment */
  1112.       if (envp != NULL)
  1113.           for (wp = envp; *wp != NULL; wp++)
  1114. ***************
  1115. *** 236,242 ****
  1116.           (void) fd_clexec(ttyfd);
  1117.   #endif
  1118.   #ifdef EMACS
  1119. !         x_init_emacs();
  1120.   #endif
  1121.       }
  1122.   
  1123. --- 244,250 ----
  1124.           (void) fd_clexec(ttyfd);
  1125.   #endif
  1126.   #ifdef EMACS
  1127. !           x_init_emacs();
  1128.   #endif
  1129.       }
  1130.   
  1131. *** sh/patchlevel.h.old    Tue May 12 13:42:00 1992
  1132. --- sh/patchlevel.h    Mon Aug 10 22:03:03 1992
  1133. ***************
  1134. *** 1,6 ****
  1135.   /*
  1136.    * PD KSH
  1137. !  * $Id: patchlevel.h,v 4.5 1992/05/12 09:30:34 sjg Exp $
  1138.    */
  1139.   #define VERSION        4
  1140. ! #define PATCHLEVEL    5
  1141. --- 1,6 ----
  1142.   /*
  1143.    * PD KSH
  1144. !  * $Id: patchlevel.h,v 4.6 1992/08/10 12:03:03 sjg Exp $
  1145.    */
  1146.   #define VERSION        4
  1147. ! #define PATCHLEVEL    6
  1148. *** sh/proto.h.old    Tue May 12 13:42:00 1992
  1149. --- sh/proto.h    Mon Aug 10 22:03:05 1992
  1150. ***************
  1151. *** 1,7 ****
  1152.   /*
  1153.    * prototypes for PD-KSH
  1154.    * originally generated using "cproto.c 3.5 92/04/11 19:28:01 cthuang "
  1155. !  * $Id: proto.h,v 1.1 1992/04/25 08:29:02 sjg Exp $
  1156.    */
  1157.   #ifndef ARGS
  1158.   #if defined(__STDC__) || defined(__cplusplus)
  1159. --- 1,7 ----
  1160.   /*
  1161.    * prototypes for PD-KSH
  1162.    * originally generated using "cproto.c 3.5 92/04/11 19:28:01 cthuang "
  1163. !  * $Id: proto.h,v 1.2 1992/08/10 12:03:05 sjg Exp $
  1164.    */
  1165.   #ifndef ARGS
  1166.   #if defined(__STDC__) || defined(__cplusplus)
  1167. ***************
  1168. *** 74,79 ****
  1169. --- 74,80 ----
  1170.   bool_t     x_mode         ARGS((bool_t onoff));
  1171.   int     promptlen     ARGS((char *cp));
  1172.   int     init_editmode     ARGS((void));
  1173. + void     set_editmode     ARGS((char *ed));
  1174.   /* emacs.c */
  1175.   int     x_emacs         ARGS((char *buf, size_t len));
  1176.   void     x_redraw     ARGS((int limit));
  1177. ***************
  1178. *** 85,90 ****
  1179. --- 86,92 ----
  1180.   char *    substitute     ARGS((char const *cp, int f));
  1181.   char **    eval         ARGS((char **ap, int f));
  1182.   char *    evalstr         ARGS((char *cp, int f));
  1183. + char *    evalonestr     ARGS((char *cp, int f));
  1184.   /* exec.c */
  1185.   int     execute         ARGS((struct op *t, volatile int flags));
  1186.   int     shcomexec     ARGS((char **wp));
  1187. ***************
  1188. *** 93,98 ****
  1189. --- 95,101 ----
  1190.   struct tbl *    findcom     ARGS((char *name, int insert));
  1191.   int     flushcom     ARGS((int all));
  1192.   char *    search         ARGS((char *name, char *path, int mode));
  1193. + int    pr_menu         ARGS((char **ap, int usestored));
  1194.   /* expr.c */
  1195.   void     evalerr         ARGS((char *err));
  1196.   long     evaluate     ARGS((const char *expr));
  1197. ***************
  1198. *** 102,108 ****
  1199. --- 105,117 ----
  1200.   /* history.c */
  1201.   int     c_fc          ARGS((register char **wp));
  1202.   void     histbackup     ARGS((void));
  1203. + #ifdef EASY_HISTORY
  1204.   void     histsave     ARGS((char *cmd));
  1205. + #else
  1206. + void    sethistsize     ARGS((int n));
  1207. + void    sethistfile     ARGS((char *name));
  1208. + void    histsave     ARGS((int lno, char *cmd, int dowrite));
  1209. + #endif
  1210.   char **    histget          ARGS((char *str));
  1211.   char *    histrpl          ARGS((char *s, char *pat, char *rep, int global));
  1212.   void     hist_init     ARGS((Source *s));
  1213. *** sh/sh.h.old    Tue May 12 13:42:00 1992
  1214. --- sh/sh.h    Mon Aug 10 22:03:08 1992
  1215. ***************
  1216. *** 2,8 ****
  1217.    * Public Domain Bourne/Korn shell
  1218.    */
  1219.   
  1220. ! /* $Id: sh.h,v 1.3 1992/04/25 08:29:52 sjg Exp $ */
  1221.   
  1222.   #include "config.h"
  1223.   
  1224. --- 2,8 ----
  1225.    * Public Domain Bourne/Korn shell
  1226.    */
  1227.   
  1228. ! /* $Id: sh.h,v 1.4 1992/08/10 12:03:08 sjg Exp $ */
  1229.   
  1230.   #include "config.h"
  1231.   
  1232. ***************
  1233. *** 15,20 ****
  1234. --- 15,24 ----
  1235.   #define    SHELL    "/bin/sh"    /* shell to exec scripts */
  1236.   #endif
  1237.   
  1238. + #ifdef _BSD
  1239. + #define memmove(dst, src, n)    bcopy((src), (dst), (n))
  1240. + #endif
  1241.   /* some people object to this use of __STDC__ */
  1242.   #ifdef __STDC__
  1243.   #define    ARGS(args)    args    /* prototype declaration */
  1244. ***************
  1245. *** 143,148 ****
  1246. --- 147,153 ----
  1247.   void    resetopts();
  1248.   void    histsave();
  1249.   void    histlist();
  1250. + int    pr_menu ARGS((char **, int));
  1251.   
  1252.   void    j_init ARGS((void));
  1253.   void    j_exit ARGS((void));
  1254. *** sh/syn.c.old    Tue May 12 13:42:00 1992
  1255. --- sh/syn.c    Mon Aug 10 22:03:10 1992
  1256. ***************
  1257. *** 3,9 ****
  1258.    */
  1259.   
  1260.   #ifndef lint
  1261. ! static char *RCSid = "$Id: syn.c,v 1.2 1992/04/25 08:33:28 sjg Exp $";
  1262.   #endif
  1263.   
  1264.   #include "stdh.h"
  1265. --- 3,9 ----
  1266.    */
  1267.   
  1268.   #ifndef lint
  1269. ! static char *RCSid = "$Id: syn.c,v 1.3 1992/08/10 12:03:10 sjg Exp $";
  1270.   #endif
  1271.   
  1272.   #include "stdh.h"
  1273. ***************
  1274. *** 258,264 ****
  1275.           break;
  1276.   
  1277.         case FOR:
  1278. !         t = newtp(TFOR);
  1279.           musthave(LWORD, 0);
  1280.           t->str = strsave(ident, ATEMP);
  1281.           multiline++;
  1282. --- 258,265 ----
  1283.           break;
  1284.   
  1285.         case FOR:
  1286. !       case SELECT:
  1287. !         t = newtp((c == FOR) ? TFOR: TSELECT);
  1288.           musthave(LWORD, 0);
  1289.           t->str = strsave(ident, ATEMP);
  1290.           multiline++;
  1291. ***************
  1292. *** 505,510 ****
  1293. --- 506,512 ----
  1294.       int    val;
  1295.   } restab[] = {
  1296.       "for",        FOR,
  1297. +     "select",    SELECT,
  1298.       "case",        CASE,
  1299.       "esac",        ESAC,
  1300.       "while",    WHILE,
  1301. *** sh/table.h.old    Tue May 12 13:42:00 1992
  1302. --- sh/table.h    Mon Aug 10 22:03:13 1992
  1303. ***************
  1304. *** 1,4 ****
  1305. ! /* $Id: table.h,v 1.2 1992/04/25 08:33:28 sjg Exp $ */
  1306.   
  1307.   /*
  1308.    * generic hashed associative table for commands and variables.
  1309. --- 1,4 ----
  1310. ! /* $Id: table.h,v 1.3 1992/08/10 12:03:13 sjg Exp $ */
  1311.   
  1312.   /*
  1313.    * generic hashed associative table for commands and variables.
  1314. ***************
  1315. *** 94,99 ****
  1316. --- 94,105 ----
  1317.   #define    V_MAIL    5
  1318.   #define    V_MAILPATH 6
  1319.   #define    V_RANDOM 7
  1320. + #ifndef EASY_HISTORY
  1321. + #define V_HISTSIZE 8
  1322. + #define V_HISTFILE 9
  1323. + #endif
  1324. + #define V_FCEDIT 10
  1325. + #define V_COLUMNS 11
  1326.   
  1327.   Extern    Area   *lastarea;    /* area of last variable/function looked up */
  1328.   Extern    char   *path;        /* PATH value */
  1329. *** sh/trap.c.old    Tue May 12 13:42:00 1992
  1330. --- sh/trap.c    Mon Aug 10 22:03:15 1992
  1331. ***************
  1332. *** 3,9 ****
  1333.    */
  1334.   
  1335.   #ifndef lint
  1336. ! static char *RCSid = "$Id: trap.c,v 1.2 1992/04/24 12:01:38 sjg Exp $";
  1337.   #endif
  1338.   
  1339.   #include "stdh.h"
  1340. --- 3,9 ----
  1341.    */
  1342.   
  1343.   #ifndef lint
  1344. ! static char *RCSid = "$Id: trap.c,v 1.3 1992/08/10 12:03:15 sjg Exp $";
  1345.   #endif
  1346.   
  1347.   #include "stdh.h"
  1348. ***************
  1349. *** 101,107 ****
  1350.       int i;
  1351.   {
  1352.       trap = sigtraps[i].set = 1;
  1353. !     if (i == SIGINT && e.type == E_PARSE)
  1354.           /* dangerous but necessary to deal with BSD silly signals */
  1355.           longjmp(e.jbuf, 1);
  1356.   #ifdef USE_SIGACT
  1357. --- 101,107 ----
  1358.       int i;
  1359.   {
  1360.       trap = sigtraps[i].set = 1;
  1361. !     if (i == SIGINT && (e.type == E_PARSE || e.type == E_LOOP))
  1362.           /* dangerous but necessary to deal with BSD silly signals */
  1363.           longjmp(e.jbuf, 1);
  1364.   #ifdef USE_SIGACT
  1365. *** sh/tree.h.old    Tue May 12 13:42:00 1992
  1366. --- sh/tree.h    Mon Aug 10 22:03:18 1992
  1367. ***************
  1368. *** 2,8 ****
  1369.    * command trees for compile/execute
  1370.    */
  1371.   
  1372. ! /* $Id: tree.h,v 1.2 1992/04/25 08:33:28 sjg Exp $ */
  1373.   
  1374.   #define    NOBLOCK    ((struct op *)NULL)
  1375.   #define    NOWORD    ((char *)NULL)
  1376. --- 2,8 ----
  1377.    * command trees for compile/execute
  1378.    */
  1379.   
  1380. ! /* $Id: tree.h,v 1.3 1992/08/10 12:03:18 sjg Exp $ */
  1381.   
  1382.   #define    NOBLOCK    ((struct op *)NULL)
  1383.   #define    NOWORD    ((char *)NULL)
  1384. ***************
  1385. *** 40,45 ****
  1386. --- 40,46 ----
  1387.   #define    TFUNCT    17        /* function name { command; } */
  1388.   #define    TTIME    18        /* time pipeline */
  1389.   #define    TEXEC    19        /* fork/exec eval'd TCOM */
  1390. + #define TSELECT    20        /* select */
  1391.   
  1392.   /*
  1393.    * prefix codes for words in command tree
  1394. ***************
  1395. *** 86,91 ****
  1396. --- 87,93 ----
  1397.   #define    XPIPEO    BIT(3)        /* output is pipe */
  1398.   #define    XPIPE    (XPIPEI|XPIPEO)    /* member of pipe */
  1399.   #define    XXCOM    BIT(4)        /* dup2 xcomfd to 1 */
  1400. + #define XXWHL    BIT(6)        /* don't flush stdin before fork */
  1401.   
  1402.   /*
  1403.    * flags to control expansion of words
  1404. *** sh/tty.h.old    Tue May 12 13:42:00 1992
  1405. --- sh/tty.h    Mon Aug 10 22:03:23 1992
  1406. ***************
  1407. *** 28,34 ****
  1408.   #include <sys/ioctl.h>
  1409.   #endif
  1410.   #else
  1411. ! #ifdef    mips
  1412.   #include <termios.h>
  1413.   #else
  1414.   #include <termio.h>
  1415. --- 28,34 ----
  1416.   #include <sys/ioctl.h>
  1417.   #endif
  1418.   #else
  1419. ! #ifdef    _POSIX_TERM
  1420.   #include <termios.h>
  1421.   #else
  1422.   #include <termio.h>
  1423. *** sh/do_ulimit.c.old    Tue May 12 13:42:00 1992
  1424. --- sh/do_ulimit.c    Mon Aug 10 22:02:23 1992
  1425. ***************
  1426. *** 13,19 ****
  1427.   */
  1428.   
  1429.   #ifndef lint
  1430. ! static char *RCSid = "$Id: do_ulimit.c,v 1.2 1992/04/25 08:33:28 sjg Exp $";
  1431.   #endif
  1432.   
  1433.   #include "stdh.h"
  1434. --- 13,23 ----
  1435.   */
  1436.   
  1437.   #ifndef lint
  1438. ! static char *RCSid = "$Id: do_ulimit.c,v 1.3 1992/08/10 12:02:23 sjg Exp $";
  1439. ! #endif
  1440. ! #ifdef _BSDI
  1441. ! #define _BSD    1
  1442.   #endif
  1443.   
  1444.   #include "stdh.h"
  1445. *** sh/var.c.old    Tue May 12 13:42:00 1992
  1446. --- sh/var.c    Mon Aug 10 22:03:25 1992
  1447. ***************
  1448. *** 1,5 ****
  1449.   #ifndef lint
  1450. ! static char *RCSid = "$Id: var.c,v 1.2 1992/04/25 08:33:28 sjg Exp $";
  1451.   #endif
  1452.   
  1453.   #include "stdh.h"
  1454. --- 1,5 ----
  1455.   #ifndef lint
  1456. ! static char *RCSid = "$Id: var.c,v 1.3 1992/08/10 12:03:25 sjg Exp $";
  1457.   #endif
  1458.   
  1459.   #include "stdh.h"
  1460. ***************
  1461. *** 491,515 ****
  1462.   /*
  1463.    * handle special variables with side effects - PATH, SECONDS.
  1464.    */
  1465.   static int
  1466.   special(name)
  1467.       register char * name;
  1468.   {
  1469. !     if (strcmp("PATH", name) == 0)
  1470.           return V_PATH;
  1471. !     if (strcmp("IFS", name) == 0)
  1472.           return V_IFS;
  1473. !     if (strcmp("SECONDS", name) == 0)
  1474.           return V_SECONDS;
  1475. !     if (strcmp("OPTIND", name) == 0)
  1476.           return V_OPTIND;
  1477. !     if (strcmp("MAIL", name) == 0)
  1478.           return V_MAIL;
  1479. !     if (strcmp("MAILPATH", name) == 0)
  1480.           return V_MAILPATH;
  1481. !     if (strcmp("RANDOM", name) == 0)
  1482.           return V_RANDOM;
  1483.       return V_NONE;
  1484.   }
  1485.   
  1486. --- 491,525 ----
  1487.   /*
  1488.    * handle special variables with side effects - PATH, SECONDS.
  1489.    */
  1490. ! #define STREQ(a, b) ((*a) == (*b) && strcmp((a), (b)) == 0)
  1491.   static int
  1492.   special(name)
  1493.       register char * name;
  1494.   {
  1495. !     if (STREQ("PATH", name))
  1496.           return V_PATH;
  1497. !     if (STREQ("IFS", name))
  1498.           return V_IFS;
  1499. !     if (STREQ("SECONDS", name))
  1500.           return V_SECONDS;
  1501. !     if (STREQ("OPTIND", name))
  1502.           return V_OPTIND;
  1503. !     if (STREQ("MAIL", name))
  1504.           return V_MAIL;
  1505. !     if (STREQ("MAILPATH", name))
  1506.           return V_MAILPATH;
  1507. !     if (STREQ("RANDOM", name))
  1508.           return V_RANDOM;
  1509. + #ifndef EASY_HISTORY
  1510. +     if (STREQ("HISTSIZE", name))
  1511. +         return V_HISTSIZE;
  1512. +     if (STREQ("HISTFILE", name))
  1513. +         return V_HISTFILE;
  1514. + #endif
  1515. +     if (STREQ("FCEDIT", name))
  1516. +         return V_FCEDIT;
  1517. +     if (STREQ("COLUMNS", name))
  1518. +         return V_COLUMNS;
  1519.       return V_NONE;
  1520.   }
  1521.   
  1522. ***************
  1523. *** 535,540 ****
  1524. --- 545,557 ----
  1525.           setint(vp, (rand() & 0x7fff));
  1526.           vp->flag |= SPECIAL;
  1527.           break;
  1528. + #ifndef EASY_HISTORY
  1529. +     case V_HISTSIZE:
  1530. +         vp->flag &= ~ SPECIAL;
  1531. +         setint(vp, histsize);
  1532. +         vp->flag |= SPECIAL;
  1533. +         break;
  1534. + #endif
  1535.       }
  1536.   }
  1537.   
  1538. ***************
  1539. *** 569,574 ****
  1540. --- 586,608 ----
  1541.           vp->flag &= ~ SPECIAL;
  1542.           srand((unsigned int)intval(vp));
  1543.           vp->flag |= SPECIAL;
  1544. +         break;
  1545. + #ifndef EASY_HISTORY
  1546. +       case V_HISTSIZE:
  1547. +         vp->flag &= ~ SPECIAL;
  1548. +         sethistsize(intval(vp));
  1549. +         vp->flag |= SPECIAL;
  1550. +         break;
  1551. +       case V_HISTFILE:
  1552. +         sethistfile(strval(vp));
  1553. +         break;
  1554. + #endif
  1555. +       case V_FCEDIT:
  1556. +         set_editmode(strval(vp));
  1557. +         break;
  1558. +       case V_COLUMNS:
  1559. +         if ((x_cols = intval(vp)) <= 0)
  1560. +           x_cols=80;
  1561.           break;
  1562.       }
  1563.   }
  1564. *** sh/version.c.old    Tue May 12 13:42:00 1992
  1565. --- sh/version.c    Mon Aug 10 22:03:29 1992
  1566. ***************
  1567. *** 3,9 ****
  1568.    */
  1569.   
  1570.   #ifndef lint
  1571. ! static char *RCSid = "$Id: version.c,v 1.4 1992/05/12 09:30:37 sjg Exp $";
  1572.   #endif
  1573.   
  1574.   #include "stdh.h"
  1575. --- 3,9 ----
  1576.    */
  1577.   
  1578.   #ifndef lint
  1579. ! static char *RCSid = "$Id: version.c,v 1.5 1992/08/10 12:03:29 sjg Exp $";
  1580.   #endif
  1581.   
  1582.   #include "stdh.h"
  1583. ***************
  1584. *** 12,21 ****
  1585.   #include "patchlevel.h"
  1586.   
  1587.   char ksh_version [] =
  1588. !     "KSH_VERSION=@(#)PD KSH v4.5 92/05/12";
  1589.   
  1590.   /***
  1591.   $Log: version.c,v $
  1592.    * Revision 1.4  1992/05/12  09:30:37  sjg
  1593.    * see ChangeLog
  1594.    *
  1595. --- 12,25 ----
  1596.   #include "patchlevel.h"
  1597.   
  1598.   char ksh_version [] =
  1599. !     "KSH_VERSION=@(#)PD KSH v4.6 92/08/10";
  1600.   
  1601.   /***
  1602.   $Log: version.c,v $
  1603. +  * Revision 1.5  1992/08/10  12:03:29  sjg
  1604. +  * Update for patch06.
  1605. +  * Contributions from Peter Collinson, Neil Smithline and sjg
  1606. +  *
  1607.    * Revision 1.4  1992/05/12  09:30:37  sjg
  1608.    * see ChangeLog
  1609.    *
  1610. *** sh/vi.c.old    Tue May 12 13:42:00 1992
  1611. --- sh/vi.c    Mon Aug 10 22:03:31 1992
  1612. ***************
  1613. *** 9,15 ****
  1614.   #ifdef VI
  1615.   
  1616.   #ifndef lint
  1617. ! static char *RCSid = "$Id: vi.c,v 1.2 1992/04/25 08:33:28 sjg Exp $";
  1618.   #endif
  1619.   
  1620.   #include "stdh.h"
  1621. --- 9,15 ----
  1622.   #ifdef VI
  1623.   
  1624.   #ifndef lint
  1625. ! static char *RCSid = "$Id: vi.c,v 1.3 1992/08/10 12:03:31 sjg Exp $";
  1626.   #endif
  1627.   
  1628.   #include "stdh.h"
  1629. ***************
  1630. *** 25,31 ****
  1631.   
  1632.   #define CMDLEN        256
  1633.   #define Ctrl(c)        (c&0x1f)
  1634. - #define    bcopy(src, dst, len)    memmove(dst, src, len)
  1635.   extern    int    histN();
  1636.   
  1637.   static int      nextstate   ARGS((int ch));
  1638. --- 25,30 ----
  1639. ***************
  1640. *** 90,96 ****
  1641.   #endif
  1642.       0,    0,    C_,    C_,    M_,    C_,    0,    C_|S_,
  1643.       M_,    0,    0,    0,    0,    0,    0,    0,
  1644. !     0,    0,    0,    M_,    0,    0,    0,    C_|S_,
  1645.       0,    C_,    M_,    C_,    C_,    M_,    M_|X_,    C_,
  1646.       0,    C_,    0,    0,    0,    0,    C_,    0,
  1647.       C_,    0,    C_,    C_,    M_|X_,    0,    0,    M_,
  1648. --- 89,95 ----
  1649.   #endif
  1650.       0,    0,    C_,    C_,    M_,    C_,    0,    C_|S_,
  1651.       M_,    0,    0,    0,    0,    0,    0,    0,
  1652. !     0,    0,    0,    M_,    0,    C_,    0,    C_|S_,
  1653.       0,    C_,    M_,    C_,    C_,    M_,    M_|X_,    C_,
  1654.       0,    C_,    0,    0,    0,    0,    C_,    0,
  1655.       C_,    0,    C_,    C_,    M_|X_,    0,    0,    M_,
  1656. ***************
  1657. *** 478,485 ****
  1658.                   inslen--;
  1659.               es->cursor--;
  1660.               if (insert != REPLACE) {
  1661. !                 bcopy(&es->cbuf[es->cursor+1],
  1662. !                         &es->cbuf[es->cursor],
  1663.                           es->linelen - es->cursor);
  1664.                   es->linelen--;
  1665.               }
  1666. --- 477,484 ----
  1667.                   inslen--;
  1668.               es->cursor--;
  1669.               if (insert != REPLACE) {
  1670. !                 memmove(&es->cbuf[es->cursor],
  1671. !                         &es->cbuf[es->cursor+1],
  1672.                           es->linelen - es->cursor);
  1673.                   es->linelen--;
  1674.               }
  1675. ***************
  1676. *** 489,495 ****
  1677.       case Ctrl('U'):
  1678.           if (es->cursor != 0) {
  1679.               inslen = 0;
  1680. !             bcopy(&es->cbuf[es->cursor], es->cbuf,
  1681.                           es->linelen - es->cursor);
  1682.               es->linelen -= es->cursor;
  1683.               es->cursor = 0;
  1684. --- 488,494 ----
  1685.       case Ctrl('U'):
  1686.           if (es->cursor != 0) {
  1687.               inslen = 0;
  1688. !             memmove(es->cbuf, &es->cbuf[es->cursor],
  1689.                           es->linelen - es->cursor);
  1690.               es->linelen -= es->cursor;
  1691.               es->cursor = 0;
  1692. ***************
  1693. *** 499,505 ****
  1694.       case Ctrl('W'):
  1695.           if (es->cursor != 0) {
  1696.               tcursor = backword(1);
  1697. !             bcopy(&es->cbuf[es->cursor], &es->cbuf[tcursor],
  1698.                           es->linelen - es->cursor);
  1699.               es->linelen -= es->cursor - tcursor;
  1700.               if (inslen < es->cursor - tcursor)
  1701. --- 498,504 ----
  1702.       case Ctrl('W'):
  1703.           if (es->cursor != 0) {
  1704.               tcursor = backword(1);
  1705. !             memmove(&es->cbuf[tcursor], &es->cbuf[es->cursor],
  1706.                           es->linelen - es->cursor);
  1707.               es->linelen -= es->cursor - tcursor;
  1708.               if (inslen < es->cursor - tcursor)
  1709. ***************
  1710. *** 515,521 ****
  1711.               return -1;
  1712.           ibuf[inslen++] = ch;
  1713.           if (insert == INSERT) {
  1714. !             bcopy(&es->cbuf[es->cursor], &es->cbuf[es->cursor+1],
  1715.                       es->linelen - es->cursor);
  1716.               es->linelen++;
  1717.           }
  1718. --- 514,520 ----
  1719.               return -1;
  1720.           ibuf[inslen++] = ch;
  1721.           if (insert == INSERT) {
  1722. !             memmove(&es->cbuf[es->cursor+1], &es->cbuf[es->cursor],
  1723.                       es->linelen - es->cursor);
  1724.               es->linelen++;
  1725.           }
  1726. ***************
  1727. *** 553,563 ****
  1728.       } else {
  1729.           if (isundoable(*cmd)) {
  1730.               undo->winleft = es->winleft;
  1731. !             bcopy(es->cbuf, undo->cbuf, es->linelen);
  1732.               undo->linelen = es->linelen;
  1733.               undo->cursor = es->cursor;
  1734.               lastac = argcnt;
  1735. !             bcopy(cmd, lastcmd, MAXVICMD);
  1736.           }
  1737.           switch (*cmd) {
  1738.   
  1739. --- 552,562 ----
  1740.       } else {
  1741.           if (isundoable(*cmd)) {
  1742.               undo->winleft = es->winleft;
  1743. !             memmove(undo->cbuf, es->cbuf, es->linelen);
  1744.               undo->linelen = es->linelen;
  1745.               undo->cursor = es->cursor;
  1746.               lastac = argcnt;
  1747. !             memmove(lastcmd, cmd, MAXVICMD);
  1748.           }
  1749.           switch (*cmd) {
  1750.   
  1751. ***************
  1752. *** 849,855 ****
  1753.                   return -1;
  1754.               return 1;
  1755.   
  1756. !         case '*': {
  1757.               int    rval = 0;
  1758.               int    start, end;
  1759.               char    *toglob = undo->cbuf;
  1760. --- 848,855 ----
  1761.                   return -1;
  1762.               return 1;
  1763.   
  1764. !         case '*':
  1765. !         case '=': {
  1766.               int    rval = 0;
  1767.               int    start, end;
  1768.               char    *toglob = undo->cbuf;
  1769. ***************
  1770. *** 867,874 ****
  1771.               while (end < es->linelen && !isspace(es->cbuf[end]))
  1772.                   end++;
  1773.               /* use undo buffer to build word up in */
  1774. !             bcopy(&es->cbuf[start], toglob, end-start);
  1775. !             if (*toglob != '~' && toglob[end-start-1] != '*') {
  1776.                   toglob[end-start] = '*';
  1777.                   toglob[end-start+1] = '\0';
  1778.               } else
  1779. --- 867,874 ----
  1780.               while (end < es->linelen && !isspace(es->cbuf[end]))
  1781.                   end++;
  1782.               /* use undo buffer to build word up in */
  1783. !             memmove(toglob, &es->cbuf[start], end-start);
  1784. !             if (toglob[end-start-1] != '*') {
  1785.                   toglob[end-start] = '*';
  1786.                   toglob[end-start+1] = '\0';
  1787.               } else
  1788. ***************
  1789. *** 878,913 ****
  1790.               if (strcmp(ap[0], toglob) == 0 && ap[1] == (char *) 0)
  1791.                   rval = -1;
  1792.               /* restore undo buffer that we used temporarily */
  1793. !             bcopy(es->cbuf, toglob, es->linelen);
  1794.               if (rval < 0)
  1795.                   return rval;
  1796. !             del_range(start, end);
  1797. !             es->cursor = start;
  1798. !             while (1) {
  1799. !                 if (putbuf(*ap, strlen(*ap), 0) != 0) {
  1800. !                     rval = -1;
  1801. !                     break;
  1802.                   }
  1803. -                 if (*++ap == (char *) 0)
  1804. -                     break;
  1805. -                 if (putbuf(" ", 1, 0) != 0) {
  1806. -                     rval = -1;
  1807. -                     break;
  1808. -                 }
  1809. -             }
  1810.   #if 0
  1811. !             /*
  1812. !              * this is definitely wrong
  1813. !              */
  1814. !             for (ap = ap2; *ap; ap++)
  1815. !                 free(*ap);
  1816.   
  1817. !             free(ap2);
  1818.   #endif
  1819.   
  1820. !             modified = 1;
  1821. !             insert = INSERT;
  1822. !             refresh(0);
  1823.               if (rval != 0)
  1824.                   return rval;
  1825.               }
  1826. --- 878,926 ----
  1827.               if (strcmp(ap[0], toglob) == 0 && ap[1] == (char *) 0)
  1828.                   rval = -1;
  1829.               /* restore undo buffer that we used temporarily */
  1830. !             memmove(toglob, es->cbuf, es->linelen);
  1831.               if (rval < 0)
  1832.                   return rval;
  1833. !             if (*cmd == '=') {
  1834. !                 fputc('\n', shlout);
  1835. !                 pr_menu(ap2, 0);
  1836. !                 fflush(shlout);
  1837. !                 if (es->linelen != 0)
  1838. !                     es->cursor++;
  1839. !                 redraw_line();
  1840. !                 insert = INSERT;
  1841. !                 state = VNORMAL;
  1842. !                 return 0;
  1843. !             } else {
  1844. !                 del_range(start, end);
  1845. !                 es->cursor = start;
  1846. !                 while (1) {
  1847. !                     if (putbuf(*ap, strlen(*ap), 0) != 0) {
  1848. !                         rval = -1;
  1849. !                         break;
  1850. !                     }
  1851. !                     if (*++ap == (char *) 0)
  1852. !                         break;
  1853. !                     if (putbuf(" ", 1, 0) != 0) {
  1854. !                         rval = -1;
  1855. !                         break;
  1856. !                     }
  1857.                   }
  1858.   #if 0
  1859. !                 /*
  1860. !                  * this is definitely wrong
  1861. !                  */
  1862. !                 for (ap = ap2; *ap; ap++)
  1863. !                     free(*ap);
  1864.   
  1865. !                 free(ap2);
  1866.   #endif
  1867.   
  1868. !                 modified = 1;
  1869. !                 insert = INSERT;
  1870. !                 refresh(0);
  1871. !             }
  1872.               if (rval != 0)
  1873.                   return rval;
  1874.               }
  1875. ***************
  1876. *** 1081,1087 ****
  1877.   {
  1878.       yanklen = b - a;
  1879.       if (yanklen != 0)
  1880. !         bcopy(&es->cbuf[a], ybuf, yanklen);
  1881.   }
  1882.   
  1883.   static int
  1884. --- 1094,1100 ----
  1885.   {
  1886.       yanklen = b - a;
  1887.       if (yanklen != 0)
  1888. !         memmove(ybuf, &es->cbuf[a], yanklen);
  1889.   }
  1890.   
  1891.   static int
  1892. ***************
  1893. *** 1130,1136 ****
  1894.   
  1895.   save_cbuf()
  1896.   {
  1897. !     bcopy(es->cbuf, holdbuf, es->linelen);
  1898.       holdlen = es->linelen;
  1899.       holdbuf[holdlen] = '\0';
  1900.   }
  1901. --- 1143,1149 ----
  1902.   
  1903.   save_cbuf()
  1904.   {
  1905. !     memmove(holdbuf, es->cbuf, es->linelen);
  1906.       holdlen = es->linelen;
  1907.       holdbuf[holdlen] = '\0';
  1908.   }
  1909. ***************
  1910. *** 1139,1145 ****
  1911.   {
  1912.       es->cursor = 0;
  1913.       es->linelen = holdlen;
  1914. !     bcopy(holdbuf, es->cbuf, holdlen);
  1915.   }
  1916.   
  1917.   static
  1918. --- 1152,1158 ----
  1919.   {
  1920.       es->cursor = 0;
  1921.       es->linelen = holdlen;
  1922. !     memmove(es->cbuf, holdbuf, holdlen);
  1923.   }
  1924.   
  1925.   static
  1926. ***************
  1927. *** 1184,1194 ****
  1928.       } else {
  1929.           if (es->linelen + len >= es->cbufsize - 1)
  1930.               return -1;
  1931. !         bcopy(&es->cbuf[es->cursor], &es->cbuf[es->cursor + len],
  1932.               es->linelen - es->cursor);
  1933.           es->linelen += len;
  1934.       }
  1935. !     bcopy(buf, &es->cbuf[es->cursor], len);
  1936.       es->cursor += len;
  1937.       return 0;
  1938.   }
  1939. --- 1197,1207 ----
  1940.       } else {
  1941.           if (es->linelen + len >= es->cbufsize - 1)
  1942.               return -1;
  1943. !         memmove(&es->cbuf[es->cursor + len], &es->cbuf[es->cursor],
  1944.               es->linelen - es->cursor);
  1945.           es->linelen += len;
  1946.       }
  1947. !     memmove(&es->cbuf[es->cursor], buf, len);
  1948.       es->cursor += len;
  1949.       return 0;
  1950.   }
  1951. ***************
  1952. *** 1209,1215 ****
  1953.       int    a, b;
  1954.   {
  1955.       if (es->linelen != b)
  1956. !         bcopy(&es->cbuf[b], &es->cbuf[a], es->linelen - b);
  1957.       es->linelen -= b - a;
  1958.   }
  1959.   
  1960. --- 1222,1228 ----
  1961.       int    a, b;
  1962.   {
  1963.       if (es->linelen != b)
  1964. !         memmove(&es->cbuf[a], &es->cbuf[b], es->linelen - b);
  1965.       es->linelen -= b - a;
  1966.   }
  1967.   
  1968. ***************
  1969. *** 1396,1402 ****
  1970.       if (save)
  1971.           save_cbuf();
  1972.       es->linelen = strlen(hptr);
  1973. !     bcopy(hptr, es->cbuf, es->linelen);
  1974.       es->cursor = 0;
  1975.       return 0;
  1976.   }
  1977. --- 1409,1415 ----
  1978.       if (save)
  1979.           save_cbuf();
  1980.       es->linelen = strlen(hptr);
  1981. !     memmove(es->cbuf, hptr, es->linelen);
  1982.       es->cursor = 0;
  1983.       return 0;
  1984.   }
  1985. ***************
  1986. *** 1423,1429 ****
  1987.       if (save)
  1988.           save_cbuf();
  1989.       es->linelen = strlen(hptr);
  1990. !     bcopy(hptr, es->cbuf, es->linelen);
  1991.       es->cursor = 0;
  1992.       return histN();
  1993.   }
  1994. --- 1436,1442 ----
  1995.       if (save)
  1996.           save_cbuf();
  1997.       es->linelen = strlen(hptr);
  1998. !     memmove(es->cbuf, hptr, es->linelen);
  1999.       es->cursor = 0;
  2000.       return histN();
  2001.   }
  2002. ***************
  2003. *** 1435,1441 ****
  2004.       x_putc('\n');
  2005.       x_flush();
  2006.       pprompt(prompt);
  2007. !     cur_col = 2;
  2008.       morec = ' ';
  2009.   }
  2010.   
  2011. --- 1448,1454 ----
  2012.       x_putc('\n');
  2013.       x_flush();
  2014.       pprompt(prompt);
  2015. !     cur_col = pwidth;
  2016.       morec = ' ';
  2017.   }
  2018.   
  2019. ***************
  2020. *** 1640,1646 ****
  2021.           return -1;
  2022.   
  2023.       if (es->cbuf != buf) {
  2024. !         bcopy(es->cbuf, buf, es->linelen);
  2025.           buf[es->linelen] = '\n';
  2026.       } else
  2027.           es->cbuf[es->linelen] = '\n';
  2028. --- 1653,1659 ----
  2029.           return -1;
  2030.   
  2031.       if (es->cbuf != buf) {
  2032. !         memmove(buf, es->cbuf, es->linelen);
  2033.           buf[es->linelen] = '\n';
  2034.       } else
  2035.           es->cbuf[es->linelen] = '\n';
  2036. *** /tmp/pdksh/bug-report    Tue May 12 13:42:00 1992
  2037. --- bug-report    Mon Aug 10 22:59:11 1992
  2038. ***************
  2039. *** 2,8 ****
  2040.   Subject: [area]: [synopsis]   [replace with actual area and short description]
  2041.   
  2042.   VERSION:
  2043. !     PD KSH: 4.5 12-May-1992
  2044.       [Official patches will edit this line to indicate the patch level]
  2045.   
  2046.   MACHINE and OPERATING SYSTEM:
  2047. --- 2,8 ----
  2048.   Subject: [area]: [synopsis]   [replace with actual area and short description]
  2049.   
  2050.   VERSION:
  2051. !     PD KSH: 4.6 02-Aug-92
  2052.       [Official patches will edit this line to indicate the patch level]
  2053.   
  2054.   MACHINE and OPERATING SYSTEM:
  2055.  
  2056. exit 0 # Just in case...
  2057.