home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1994 March / Source_Code_CD-ROM_Walnut_Creek_March_1994.iso / compsrcs / misc / volume31 / pdksh / patch06b < prev    next >
Encoding:
Text File  |  1992-08-13  |  44.3 KB  |  2,101 lines

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