home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1994 March / Source_Code_CD-ROM_Walnut_Creek_March_1994.iso / compsrcs / misc / volume37 / newing / part02 < prev    next >
Encoding:
Text File  |  1993-05-29  |  53.9 KB  |  1,925 lines

  1. Newsgroups: comp.sources.misc
  2. From: slantin@eis.calstate.edu (Sam Lantinga)
  3. Subject: v37i093:  newing - interface for your program, Part02/03
  4. Message-ID: <1993May29.183555.27590@sparky.imd.sterling.com>
  5. X-Md4-Signature: 47cd8065a92348035bb64f0868a5ddce
  6. Sender: kent@sparky.imd.sterling.com (Kent Landfield)
  7. Organization: Calif State Univ/Electronic Information Services
  8. Date: Sat, 29 May 1993 18:35:55 GMT
  9. Approved: kent@sparky.imd.sterling.com
  10.  
  11. Submitted-by: slantin@eis.calstate.edu (Sam Lantinga)
  12. Posting-number: Volume 37, Issue 93
  13. Archive-name: newing/part02
  14. Environment: UNIX
  15.  
  16. #! /bin/sh
  17. # This is a shell archive.  Remove anything before this line, then feed it
  18. # into a shell via "sh file" or similar.  To overwrite existing files,
  19. # type "sh file -c".
  20. # Contents:  config.c help-err.c history.c mem.c misc.c newing.c
  21. #   newing.h newing.hlp.UU trigger.c
  22. # Wrapped by kent@sparky on Sat May 29 13:21:07 1993
  23. PATH=/bin:/usr/bin:/usr/ucb:/usr/local/bin:/usr/lbin ; export PATH
  24. echo If this archive is complete, you will see the following message:
  25. echo '          "shar: End of archive 2 (of 3)."'
  26. if test -f 'config.c' -a "${1}" != "-c" ; then 
  27.   echo shar: Will not clobber existing file \"'config.c'\"
  28. else
  29.   echo shar: Extracting \"'config.c'\" \(3944 characters\)
  30.   sed "s/^X//" >'config.c' <<'END_OF_FILE'
  31. X
  32. X/* config.c   Shareware Copyright by Sam Lantinga    5/6/93    */
  33. X
  34. X#include    <sys/types.h>
  35. X#include    <stdio.h>
  36. X#include    <sys/stat.h>
  37. X#include    <signal.h>
  38. X
  39. X/*#define DEBUG        /* Provides extra debugging info */
  40. X
  41. Xint exists(file)
  42. Xchar *file;
  43. X{
  44. X    struct stat statbuf;
  45. X
  46. X    if ( stat(file, &statbuf) == 0 )
  47. X        return(1);
  48. X    else
  49. X        return(0);
  50. X}
  51. X
  52. X
  53. Xmain()
  54. X{
  55. X    int  irix=0;
  56. X    char cflags[BUFSIZ], ldflags[BUFSIZ];
  57. X    char line[BUFSIZ];
  58. X    FILE *makefile;
  59. X
  60. X    if ( exists("Makefile") )
  61. X    {
  62. X        fprintf(stderr, "Makefile already exists.  Continue?  [y/n] ");
  63. X        fgets(line, BUFSIZ-1, stdin);
  64. X        if ( line[0] == 'y' )
  65. X            printf("Continuing...\n");
  66. X        else
  67. X        {
  68. X            printf("Configuration aborted. Exiting.\n");
  69. X            exit(0);
  70. X        }
  71. X    }
  72. X
  73. X    if ( (makefile=fopen("Makefile", "w")) == NULL )
  74. X    {
  75. X        perror("Can't create Makefile");
  76. X        printf("Configuration aborted. Exiting.\n");
  77. X        exit(2);
  78. X    }
  79. X
  80. X#ifdef DEBUG
  81. X    sprintf(cflags, " -g -DDEBUG");
  82. X#else
  83. X    sprintf(cflags, " -O");
  84. X#endif
  85. X    sprintf(ldflags, "");
  86. X
  87. X    if ( grep("/usr/include/unistd.h", "_getpty") )
  88. X    {
  89. X        strcat(cflags, " -DIRIX");
  90. X        irix=1;
  91. X    }
  92. X    if ( grep("/usr/include/utmp.h", "ut_host") )
  93. X        strcat(cflags, " -DHAVE_UTHOST");
  94. X
  95. X    if ( exists("/usr/include/termio.h") )
  96. X        strcat(cflags, " -DHAVE_TERMIO_H");
  97. X    if ( exists("/usr/include/sys/bsdtty.h") )
  98. X        strcat(cflags, " -DHAVE_BSDTTY_H");
  99. X    if ( exists("/usr/include/sys/inet.h") )
  100. X        strcat(cflags, " -DNEED_INET_H");
  101. X    if ( exists("/usr/include/sys/select.h") )
  102. X        strcat(cflags, " -DNEED_SELECT_H");
  103. X    if ( exists("/usr/lib/libtermcap.a") )
  104. X    {
  105. X        strcat(cflags, " -DHAVE_TERMCAP");
  106. X        strcat(ldflags, " -ltermcap");
  107. X    }
  108. X    if ( exists("/usr/lib/libnet.a") )
  109. X        strcat(ldflags, " -lnet");
  110. X    if ( exists("/usr/lib/libnsl_s.a") )
  111. X        strcat(ldflags, " -lnsl_s");
  112. X
  113. X    /* Solaris 2.1 */
  114. X    if ( exists("/usr/lib/libsocket.a") )
  115. X    {
  116. X        strcat(ldflags, "-lsocket");
  117. X        strcat(cflags, " -DSOLARIS");
  118. X    }
  119. X
  120. X    fprintf(makefile,"# This Makefile has been generated from the Configure script.\n# Shareware copyright 1993, by Sam Lantinga\n\n");
  121. X    fprintf(makefile, "# The Configure script should have configured newing correctly for\n# your system, but you may want to manually adjust the compiler\n# flags to make sure they conform to your system.\n# Or you can just type 'make' and see if anything breaks.\n\n");
  122. X    fprintf(makefile, "# 'newing' has been extensively tested on Sun/OS 4.1\n\n");
  123. X    fprintf(makefile, "# Current possible definitions:\n#\n#\t-DIRIX\t\t\tConfigure for IRIX System V UNIX\n#\t-DSOLARIS\t\tConfigure for Solaris 2.1 UNIX\n#\t-DHAVE_UTHOST\t\tYou have the ut_host field in your\n#\t\t\t\tutmp structure.  (check <utmp.h>)\n");
  124. X    fprintf(makefile, "#\t-DHAVE_TERMIO_H\t\tYou have /usr/include/termio.h\n#\t-DHAVE_BSDTTY_H\t\tYou have /usr/include/bsdtty.h\n#\t\t\t\t(Usually HP-UX systems)\n");
  125. X    fprintf(makefile, "#\t-DNEED_INET_H\t\tYou need /usr/include/sys/inet.h\n#\t\t\t\t(For AT&T 3b2 System V.3 UNIX)\n#\t-DNEED_SELECT_H\t\tYou need /usr/include/sys/select.h\n#\t\t\t\t(For AIX and Solaris systems)\n");
  126. X    fprintf(makefile, "#\t-DHAVE_TERMCAP\t\tYou have /etc/termcap and the\n#\t\t\t\ttermcap library functions.\n\n");
  127. X
  128. X    sprintf(line, "\nCFLAGS = %s\nLIBS = %s\n\n", cflags, ldflags);
  129. X    fprintf(makefile, "%s", line);
  130. X    fprintf(makefile, "CC = cc\nOBJECTS = newing.o tty.o misc.o cmds.o history.o ile.o alias.o \\\n          trigger.o startup.o utmp.o mem.o help-err.o\n\nnewing: $(OBJECTS)\n\t$(CC) -o $@ $(OBJECTS) $(LIBS)\n\nclean:\n\trm -f Makefile config core *.o newing tmp*\n");
  131. X
  132. X    fclose(makefile);
  133. X    exit(0);
  134. X}
  135. X
  136. X
  137. X/* Yeesh.  I have to write a word grep function.... */
  138. X
  139. Xint grep(file, word)
  140. Xchar *file;
  141. Xchar *word;
  142. X{
  143. X    FILE *fp;
  144. X    char *wptr, *ptr, buffer[BUFSIZ];
  145. X
  146. X    if ( (fp=fopen(file, "r")) == NULL )
  147. X        return(0);
  148. X    ptr=word;
  149. X
  150. X    while ( fgets(buffer, BUFSIZ-1, fp) != NULL )
  151. X    {
  152. X        for ( wptr=buffer; *wptr; ++wptr)
  153. X        {
  154. X            if ( *wptr == *ptr )
  155. X            {
  156. X                ++ptr;
  157. X                if ( *ptr == '\0' )
  158. X                {
  159. X                    (void) fclose(fp);
  160. X                    return(1);
  161. X                }
  162. X            }
  163. X            else
  164. X                ptr=word;
  165. X        }
  166. X    }
  167. X    (void) fclose(fp);
  168. X    return(0);
  169. X}
  170. END_OF_FILE
  171.   if test 3944 -ne `wc -c <'config.c'`; then
  172.     echo shar: \"'config.c'\" unpacked with wrong size!
  173.   fi
  174.   # end of 'config.c'
  175. fi
  176. if test -f 'help-err.c' -a "${1}" != "-c" ; then 
  177.   echo shar: Will not clobber existing file \"'help-err.c'\"
  178. else
  179.   echo shar: Extracting \"'help-err.c'\" \(5720 characters\)
  180.   sed "s/^X//" >'help-err.c' <<'END_OF_FILE'
  181. X
  182. X/* help-err.c   Shareware Copyright by Sam Lantinga    5/6/93    */
  183. X
  184. X#include     "newing.h"
  185. X
  186. Xchar *Usage=
  187. X"Usage: newing [-h] [-v] [-u] [-i] [-e escape_char] [-s label]\r\n              [-l logfile] [program [arguments]]\r\n";
  188. X
  189. Xstatic char *topics[] = { "usage", "editing", "escapes", "aliases", "triggers", NULL };
  190. X
  191. Xvoid print_help(topic)
  192. Xchar *topic;
  193. X{
  194. X    int i;
  195. X
  196. X    if ( topic == NULL )
  197. X    {
  198. X        printf("Current topics:\r\n\t");
  199. X        for ( i=0; topics[i]; ++i )
  200. X            printf("%s ", topics[i]);
  201. X        printf("\r\n");
  202. X        return;
  203. X    }
  204. X
  205. X    /* Print out the help for "usage" */
  206. X    if ( strcmp(topic, topics[0]) == 0 )
  207. X    {
  208. X        fprintf(stderr, "%s", Usage);
  209. X        fprintf(stderr, 
  210. X"\r\nOptions:\r\n");
  211. X        fprintf(stderr,
  212. X"\t-h\t\tPrint this help message\r\n");
  213. X        fprintf(stderr,
  214. X"\t-v\t\tRun newing in verbose mode\r\n");
  215. X        fprintf(stderr,
  216. X"\t-u\t\tCreate a utmp entry for newing\r\n");
  217. X        fprintf(stderr, 
  218. X"\t-i\t\tStart newing in line edit mode\r\n");
  219. X        fprintf(stderr,
  220. X"\t-e escape_char\tSet the escape character to 'escape_char'\r\n");
  221. X        fprintf(stderr, 
  222. X"\t-s label\tInitialize newing from 'label'\r\n");
  223. X        fprintf(stderr,
  224. X"\t-l logfile\tLog the output to 'logfile'\r\n");
  225. X        fprintf(stderr,
  226. X"\tprogram\t\tRun 'program' instead of %s\r\n", SHELL);
  227. X        return;
  228. X    }
  229. X
  230. X    /* Print out the help for "editing" */
  231. X    if ( strcmp(topic, topics[1]) == 0 )
  232. X    {
  233. X        printf(
  234. X"Editing keys:\r\n");
  235. X        printf(
  236. X"\tKey\t\tFunction\r\n");
  237. X        printf(
  238. X"\t------\t\t-----------------------------\r\n");
  239. X        printf(
  240. X"\t<left-arrow>\tMove left one space\r\n");
  241. X        printf(
  242. X"\t<right-arrow>\tMove right one space\r\n");
  243. X        printf(
  244. X"\tCtrl-B\t\tMove backward one word\r\n");
  245. X        printf(
  246. X"\tCtrl-F\t\tMove forward one word\r\n");
  247. X        printf(
  248. X"\tCtrl-A\t\tMove to the beginning of the line\r\n");
  249. X        printf(
  250. X"\tCtrl-E\t\tMove to the end of the line\r\n");
  251. X        printf("\r\n");
  252. X        printf(
  253. X"\t<backspace>\tDelete the character behind the \r\n");
  254. X        printf(
  255. X"\t\t\tcursor\r\n");
  256. X        printf(
  257. X"\tCtrl-W\t\tDelete the previous word\r\n");
  258. X        printf(
  259. X"\tCtrl-K\t\tDelete to the end of the line\r\n");
  260. X        printf(
  261. X"\tCtrl-U\t\tDelete the whole line\r\n");
  262. X        printf("\r\n");
  263. X        printf(
  264. X"\tCtrl-L\t\tRedraw the line on the next line\r\n");
  265. X        printf(
  266. X"\t<up-arrow>\tEdit the previous history buffer\r\n");
  267. X        printf(
  268. X"\t<down-arrow>\tEdit the next history buffer\r\n");
  269. X        printf(
  270. X"\tCtrl-Vx\t\tQuote character x into the line\r\n");
  271. X        return;
  272. X    }
  273. X
  274. X    /* Print out the help for "escapes" */
  275. X    if ( strcmp(topic, topics[2]) == 0 )
  276. X    {
  277. X        printf(
  278. X"Currently implemented escapes:\r\n\r\n");
  279. X        printf(
  280. X"\tEscape\t\t\tAction\r\n\t-----------\t\t------------------------\r\n");
  281. X        printf(
  282. X"\tverbose\t\t\tToggles verbose mode on and off\r\n");
  283. X        printf(
  284. X"\tedit\t\t\tToggles edit mode on and off.\r\n");
  285. X        printf(
  286. X"\tescape <escape_char>\tSets the escape character\r\n");
  287. X        printf(
  288. X"\thistchar <hist_char>\tSets the history character\r\n");
  289. X        printf(
  290. X"\thistory\t\t\tDisplays the current history list\r\n");
  291. X        printf(
  292. X"\talias <name> <def>\tDefine alias 'name' as 'def'\r\n");
  293. X        printf(
  294. X"\tunalias <name>\t\tRemove the alias 'name'\r\n");
  295. X        printf(
  296. X"\tlistalias\t\tList the current aliases\r\n");
  297. X        printf(
  298. X"\taddtrig <name> <trig> <resp>\tDefine a trigger: 'name'\r\n");
  299. X        printf(
  300. X"\tdeltrig <name>\t\tRemove the trigger 'name'\r\n");
  301. X        printf(
  302. X"\tshowtrigs\t\tList the current triggers\r\n");
  303. X        printf(
  304. X"\tcat <file>\t\tCat 'file' to the program\r\n");
  305. X        printf(
  306. X"\tstatus\t\t\tPrints out the current status\r\n");
  307. X        printf(
  308. X"\tsuspend\t\t\tSuspends newing or runs a subshell\r\n");
  309. X        printf(
  310. X"\tsubsh [command]\t\tRun a subshell, or 'command'\r\n");
  311. X        printf(
  312. X"\thelp <topic>\t\tPrints out help for 'topic'\r\n");
  313. X        printf(
  314. X"\tdie\t\t\tKills newing and the program\r\n");
  315. X        return;
  316. X    }
  317. X
  318. X    if ( strcmp(topic, topics[3]) == 0 )
  319. X    {
  320. X        printf(
  321. X"\tTo define an alias, use the escape 'alias'.  For example,\r\n");
  322. X        printf(
  323. X"to define an alias 'w' that will expand to 'who', you would type:\r\n");
  324. X        printf(
  325. X"\talias w who\r\n");
  326. X        printf(
  327. X"at the escape prompt.  To define a multiword alias, you must quote\r\n");
  328. X        printf(
  329. X"the definition with double quotes.\r\n");
  330. X        printf(
  331. X"\tTo expand an alias, type its name as though it were\r\n");
  332. X        printf(
  333. X"a regular escape.  Its definition will be placed on a line for\r\n");
  334. X        printf(
  335. X"you to edit, and then to be sent to the program by the press\r\n");
  336. X        printf(
  337. X"of a carriage return.\r\n");
  338. X        return;
  339. X    }
  340. X
  341. X    /* Print out the help for triggers */
  342. X    if ( strcmp(topic, topics[4]) == 0 )
  343. X    {
  344. X        printf(
  345. X"\tTriggers are bits of text that are searched for in the\r\n");
  346. X        printf(
  347. X"porogram output.  If they are found, then the response associated\r\n");
  348. X        printf(
  349. X"with the trigger is sent to the program, followed by a newline.\r\n");
  350. X        printf(
  351. X"Triggers are useful for automatically performing certain tasks.\r\n");
  352. X        printf(
  353. X"For instance, if I wanted to set my terminal type to vt100 when\r\n");
  354. X        printf(
  355. X"ever I was prompted, I would type the escape character, and\r\n");
  356. X        printf(
  357. X"type:\r\n");
  358. X        printf(
  359. X"\taddtrig vtadd \"erminal type:\" vt100\r\n");
  360. X        printf("\r\n");
  361. X        printf(
  362. X"Then, whenever the shell prompted me with:\r\n");
  363. X        printf(
  364. X"Enter terminal type: \r\n");
  365. X        printf(
  366. X"newing would respond by sending vt100 and a carriage return.\r\n");
  367. X        printf(
  368. X"\"vtadd\" is the label I associated with the trigger, and I\r\n");
  369. X        printf(
  370. X"can delete the trigger by pressing the escape character and\r\n");
  371. X        printf(
  372. X"then typing:\r\n");
  373. X        printf(
  374. X"\tdeltrig vtadd\r\n");
  375. X        return;
  376. X    }
  377. X
  378. X    printf("No help for \"%s\"\r\n", topic);
  379. X}
  380. X
  381. Xvoid print_status()
  382. X{
  383. X    printf("Newing Status:\r\n");
  384. X    printf("\tVerbose mode: %s\r\n", 
  385. X                (flag.verbose ? "on" : "off"));
  386. X    printf("\tLine editing: %s\r\n", 
  387. X                (flag.edit ? "on" : "off"));
  388. X    printf("\tLogging is %s.\r\n", 
  389. X                (flag.logstream ? "enabled" : "disabled"));
  390. X}
  391. END_OF_FILE
  392.   if test 5720 -ne `wc -c <'help-err.c'`; then
  393.     echo shar: \"'help-err.c'\" unpacked with wrong size!
  394.   fi
  395.   # end of 'help-err.c'
  396. fi
  397. if test -f 'history.c' -a "${1}" != "-c" ; then 
  398.   echo shar: Will not clobber existing file \"'history.c'\"
  399. else
  400.   echo shar: Extracting \"'history.c'\" \(4403 characters\)
  401.   sed "s/^X//" >'history.c' <<'END_OF_FILE'
  402. X
  403. X/* history.c   Shareware Copyright by Sam Lantinga    5/6/93    */
  404. X
  405. X#include    <sys/types.h>
  406. X#ifdef HAVE_TERMIO_H
  407. X#include    <termio.h>        /* Just for VWERASE definition */
  408. X#endif
  409. X#include    <ctype.h>
  410. X#include    "newing.h"
  411. X
  412. X#define MAXHIST        10        /* The maximum of history buffers */
  413. X
  414. X#define ERASE_A        toctrl('H')    /* Erase character */
  415. X#define ERASE_B        '\177'        /* Alternate erase character (Del) */
  416. X#define ERASE_W        toctrl('W')    /* Word erase character */
  417. X#define ERASE_L        toctrl('U')    /* Line kill character */
  418. X
  419. Xint histchar=toctrl('P');        /* Default history character */
  420. X
  421. Xstatic struct history *temphist;
  422. Xstatic struct history *firsthist;
  423. Xstruct history *currhist;
  424. X
  425. X/* The routine to allocate and initialize the history buffers */
  426. X
  427. Xint init_history()
  428. X{
  429. X    if ( (firsthist=(struct history *)myalloc(sizeof(struct history)))
  430. X                         == (struct history *)NULL )
  431. X        return(-1);
  432. X    else
  433. X    {
  434. X        firsthist->prev=firsthist;
  435. X        firsthist->next=firsthist;
  436. X        firsthist->buf[0]='\0';
  437. X        currhist=firsthist;
  438. X        temphist=currhist;
  439. X    }
  440. X
  441. X    if ( init_ile() < 0 )
  442. X        fprintf(stderr, "Can't initialize ile: %s\n", ile_errmesg);
  443. X
  444. X    return(0);
  445. X}
  446. X
  447. X
  448. X/* Print out the history buffers on standard output */
  449. X
  450. Xvoid showhistory()
  451. X{
  452. X    struct history *temp;
  453. X
  454. X    printf("History:\r\n");
  455. X    for ( temp=currhist->next; ; temp=temp->next )
  456. X    {
  457. X        if ( temp == currhist )
  458. X            break;
  459. X        printf("\t%s\r\n", temp->buf);
  460. X    }
  461. X}
  462. X
  463. X
  464. X/* Add a new history buffer to the linked list.  */
  465. X
  466. Xstruct history *add_hist(buf)
  467. Xchar *buf;
  468. X{
  469. X    struct history *temp, *holder;
  470. X    int numhists=0;
  471. X
  472. X    /* Don't do anything with an empty buffer */
  473. X    if ( *buf == '\0' )
  474. X        return(NULL);
  475. X
  476. X    for ( temp=firsthist; ; temp=temp->next )
  477. X    {
  478. X        if ( numhists && (temp == firsthist) )
  479. X            break;
  480. X#ifdef BIGDEBUG
  481. X        fprintf(stderr, "temp->buf: %s\r\n", temp->buf);
  482. X#endif
  483. X        ++numhists;
  484. X    }
  485. X
  486. X#ifdef BIGDEBUG
  487. X    fprintf(stderr, "numhists: %d\n", numhists);
  488. X#endif
  489. X    if ( numhists >= MAXHIST )
  490. X    {
  491. X        currhist=currhist->next;
  492. X        strcpy(currhist->buf, buf);
  493. X        return(currhist);
  494. X    }
  495. X
  496. X    holder=temp->prev;
  497. X
  498. X    if ((temp=(struct history *)myalloc(sizeof(struct history))) != NULL)
  499. X    {
  500. X        temp->next=firsthist;
  501. X        holder->next=temp;
  502. X        temp->prev=holder;
  503. X        firsthist->prev=temp;
  504. X        strcpy(temp->buf, buf);
  505. X        currhist=temp;
  506. X    }
  507. X    return(temp);
  508. X}
  509. X
  510. X
  511. X/* Process tty input, checking for escapes and history substitution */
  512. X
  513. X#define NORMAL    0
  514. X#define AT_NL    1
  515. X
  516. Xint state=AT_NL;
  517. Xint histind=0;
  518. Xchar histbuf[MAXLINE];
  519. X
  520. Xint hist_write(fd, buf, len)
  521. Xint fd;
  522. Xchar buf[];
  523. Xint len;
  524. X{
  525. X    char *ptr, runbuf[MAXLINE];
  526. X    int i, l=0;
  527. X    
  528. X    if ( flag.edit )
  529. X    {
  530. X        if ( len == 1 )
  531. X        {
  532. X            if ( *buf == histchar )
  533. X            {
  534. X                temphist=currhist;
  535. X                (void) add_hist(ile(fd, temphist->buf));
  536. X                return(len);
  537. X            }
  538. X            else if ( *buf == escape )
  539. X            {
  540. X                read_escape(NULL, fd);
  541. X                return(len);
  542. X            }
  543. X            else if ( *buf == '\r' || issignal(*buf) || 
  544. X                  *buf == toctrl('D') || *buf == '\n' )
  545. X            {
  546. X                write(fd, buf, 1);
  547. X                histind=0;
  548. X                return(len);
  549. X            }
  550. X        }
  551. X        *(buf+len)='\0';
  552. X        (void) add_hist(ile(fd, buf));
  553. X        return(len);
  554. X    }
  555. X
  556. X    for ( i=0; i<len; ++i )
  557. X    {
  558. X        /* Catch backspacing to the beginning of the line */
  559. X        if ( histind == 0 )
  560. X            state=AT_NL;
  561. X
  562. X        if ( state == AT_NL )
  563. X        {
  564. X            if ( buf[i] == histchar )
  565. X            {
  566. X                temphist=currhist;
  567. X                (void) add_hist(ile(fd, temphist->buf));
  568. X                state=AT_NL;
  569. X            }
  570. X            else if ( buf[i] == escape )
  571. X            {
  572. X                read_escape(NULL, fd);
  573. X                histind=0;
  574. X                state=AT_NL;
  575. X            }
  576. X            else
  577. X                state=NORMAL;
  578. X        }
  579. X
  580. X        if ( state == NORMAL )
  581. X        {
  582. X            if ( buf[i] == '\r' || buf[i] == '\n' )
  583. X            {
  584. X                state=AT_NL;
  585. X
  586. X                histbuf[histind++]='\0';
  587. X#ifdef BIGDEBUG
  588. X                fprintf(stderr, "histbuf: %s\r\n", histbuf);
  589. X#endif
  590. X                (void) add_hist(histbuf);
  591. X                histind=0;
  592. X
  593. X                runbuf[l++]='\r';
  594. X                writen(fd, runbuf, l);
  595. X                l=0;
  596. X            }
  597. X            else if ( buf[i] == ERASE_A || buf[i] == ERASE_B )
  598. X            {
  599. X                runbuf[l++]=buf[i];
  600. X                histind-=(histind ? 1 : 0);
  601. X            }
  602. X#ifdef VWERASE
  603. X            else if ( buf[i] == ERASE_W )
  604. X            {
  605. X                runbuf[l++]=buf[i];
  606. X                /* Skip whitespace */
  607. X                while ( histind > 0 )
  608. X                {
  609. X                    if ( ! isspace(histbuf[histind-1]) )
  610. X                        break;
  611. X                    --histind;
  612. X                }
  613. X                /* Now skip word */
  614. X                while ( histind > 0 )
  615. X                {
  616. X                    if ( isspace(histbuf[histind-1]) )
  617. X                        break;
  618. X                    --histind;
  619. X                }
  620. X            }
  621. X#endif
  622. X            else if ( buf[i] == toctrl('D') || 
  623. X                      buf[i] == ERASE_L || issignal(buf[i]) )
  624. X            {
  625. X                runbuf[l++]=buf[i];
  626. X                histind=0;
  627. X                state=AT_NL;
  628. X            }
  629. X            else
  630. X            {
  631. X                histbuf[histind++]=buf[i];
  632. X                runbuf[l++]=buf[i];
  633. X            }
  634. X        }
  635. X    }
  636. X    return(writen(fd, runbuf, l));
  637. X}
  638. X
  639. END_OF_FILE
  640.   if test 4403 -ne `wc -c <'history.c'`; then
  641.     echo shar: \"'history.c'\" unpacked with wrong size!
  642.   fi
  643.   # end of 'history.c'
  644. fi
  645. if test -f 'mem.c' -a "${1}" != "-c" ; then 
  646.   echo shar: Will not clobber existing file \"'mem.c'\"
  647. else
  648.   echo shar: Extracting \"'mem.c'\" \(5693 characters\)
  649.   sed "s/^X//" >'mem.c' <<'END_OF_FILE'
  650. X
  651. X
  652. X/*  I have been having real problems with malloc() on an AT&T 3b2, so
  653. X    here is a customized memory handler specialized for many small
  654. X    requests for memory.  It allocates a large chunk with malloc, and
  655. X    then lops hunks off for the user routines.  Hopefully it is more
  656. X    efficient.  
  657. X
  658. X    mem.c    Shareware Copyright by Sam Lantinga    5/6/93    
  659. X*/
  660. X
  661. X#include    <stdio.h>
  662. X
  663. X#define MEMSIZ    BUFSIZ    /* The size of each block allocated */
  664. X#define MAXMEM    12    /* The most blocks that can be allocated at once */
  665. X#define GRAIN    16    /* This should be an optimum size for the requests */
  666. X#define GRAINS    (MEMSIZ/GRAIN)    /* The number of grains in a block */
  667. X
  668. Xstruct grain {
  669. X    int   size;        /* The request size in grains */
  670. X    int   used;        /* Have we been allocated?    */
  671. X    char *bit;        /* The grain of memory we are */
  672. X    };
  673. X
  674. Xstruct memblock {
  675. X    int   numfree;        /* The number of free grains  */
  676. X    char  *head;
  677. X    struct grain grains[GRAINS];
  678. X    struct memblock *next;
  679. X    } memstart;
  680. X
  681. Xstruct bigblock {
  682. X    char *data;
  683. X    struct bigblock *next;
  684. X    } Memstart;
  685. X
  686. Xstatic int havealloct=0;    /* Have we malloc'ed yet?  */
  687. Xvoid d_zero(), d_copy();    /* Replacements for bzero() and bcopy() */
  688. X
  689. X
  690. Xint meminit(blkptr)
  691. Xstruct memblock *blkptr;
  692. X{
  693. X    int   i;
  694. X    char *newarea;
  695. X
  696. X    if ( (blkptr->head=(char *)malloc(MEMSIZ)) == NULL )
  697. X        return(-1);
  698. X    blkptr->numfree=GRAINS;
  699. X
  700. X    for ( i=0, newarea=blkptr->head; i<GRAINS; ++i )
  701. X    {
  702. X        blkptr->grains[i].bit=newarea;
  703. X        blkptr->grains[i].used=0;
  704. X        newarea+=GRAIN;
  705. X    }
  706. X    blkptr->next=NULL;
  707. X    d_zero(blkptr->head, MEMSIZ);
  708. X    return(0);
  709. X}
  710. X
  711. X
  712. Xchar *myalloc(size)
  713. Xint size;
  714. X{
  715. X    int i=0;
  716. X    int needed=0;        /* The number of grains needed to fulfill */
  717. X    int need=0;        /* The size of request unfulfilled */
  718. X    int freestart=(-1);    /* The first free grain */
  719. X
  720. X    struct memblock *blk, *temp;
  721. X    struct bigblock *Blk, *Temp;
  722. X
  723. X    if ( ! havealloct )
  724. X    {  /* We need to initialize some memory */
  725. X        if ( meminit(&memstart) < 0 )
  726. X            return(NULL);
  727. X
  728. X        Memstart.data=NULL;
  729. X        Memstart.next=NULL;
  730. X
  731. X        havealloct=1;
  732. X    }
  733. X
  734. X    /* If no need, no problem! */
  735. X    if ( size == 0 )
  736. X        return(NULL);
  737. X
  738. X    /* Call malloc() directly if the request is larger than MEMSIZ */
  739. X    /* Create a big block, and attatch it to the linked list */
  740. X    if ( size > MEMSIZ )
  741. X    {
  742. X        for ( Blk=Memstart.next, Temp=(&Memstart);
  743. X                     Blk; Temp=Blk, Blk=Blk->next );
  744. X        
  745. X        if ( (Blk=(struct bigblock *)malloc(sizeof(struct bigblock)))
  746. X                                == NULL )
  747. X            return(NULL);
  748. X        if ( (Blk->data=(char *)malloc(size)) == NULL )
  749. X        {
  750. X            free(Blk);
  751. X            return(NULL);
  752. X        }
  753. X        Temp=Blk;
  754. X        Blk->next=NULL;
  755. X        return(Blk->data);
  756. X    }
  757. X
  758. X    needed=((size/GRAIN)+(size%GRAIN ? 1 : 0));
  759. X
  760. X    for (blk=(&memstart),temp=blk; (blk != NULL); temp=blk,blk=blk->next )
  761. X    {
  762. X        if ( needed <= blk->numfree )
  763. X        {
  764. X            need=needed;
  765. X            for ( i=0; i<GRAINS; ++i )
  766. X            {
  767. X                if ( blk->grains[i].used )
  768. X                {
  769. X                    freestart=(-1);
  770. X                    need=needed;
  771. X                    continue;
  772. X                }
  773. X
  774. X                if ( freestart < 0 )
  775. X                    freestart=i;
  776. X                --need;
  777. X                
  778. X                if ( need == 0 )
  779. X                {
  780. X                    for ( i=freestart;
  781. X                                i<(needed+freestart); ++i )
  782. X                        blk->grains[i].used=1;
  783. X                    blk->grains[freestart].size=needed;
  784. X                    blk->numfree-=needed;
  785. X                    d_zero(blk->grains[freestart].bit,
  786. X                                (needed*GRAIN));
  787. X                    return(blk->grains[freestart].bit);
  788. X                }
  789. X            }
  790. X        }
  791. X    }
  792. X
  793. X    /* We didn't get the memory from a pool.. allocate a new one */
  794. X
  795. X    if ( (blk=(struct memblock *)malloc(sizeof(struct memblock))) == NULL )
  796. X        return(NULL);
  797. X
  798. X    if ( meminit(blk) < 0 )
  799. X        return(NULL);
  800. X    else
  801. X        temp->next=blk;
  802. X
  803. X    for ( i=0; i<needed; ++i )
  804. X        blk->grains[i].used=1;
  805. X
  806. X    blk->grains[0].size=needed;
  807. X    blk->numfree-=needed;
  808. X    return(blk->grains[0].bit);
  809. X}
  810. X
  811. Xint myfree(ptr)
  812. Xchar *ptr;
  813. X{
  814. X    int i, cur;
  815. X    struct memblock *blk;
  816. X    struct bigblock *Blk, *Temp;
  817. X
  818. X    /* A little sanity please. :) */
  819. X    if ( ptr == NULL )
  820. X        return(0);
  821. X
  822. X    if ( ! havealloct )
  823. X        return(free(ptr));
  824. X
  825. X    for ( blk=(&memstart); (blk != NULL); blk=blk->next )
  826. X    {
  827. X        if ( (ptr >= blk->head) && (ptr < (blk->head+MEMSIZ)) )
  828. X        {   /* The area to be freed is in this block */
  829. X            for ( i=0; i<GRAINS; ++i )
  830. X            {
  831. X                if ( ptr == blk->grains[i].bit )
  832. X                {
  833. X                    if ( ! blk->grains[i].used )
  834. X                        return(-1);
  835. X
  836. X                    for( cur=i;
  837. X                        (i<(blk->grains[cur].size+cur));
  838. X                                  ++i )
  839. X                        blk->grains[i].used=0;
  840. X                    blk->numfree+=blk->grains[cur].size;
  841. X                    blk->grains[cur].size=0;
  842. X
  843. X                    return(0);
  844. X                }
  845. X            }
  846. X            return(-1);
  847. X        }
  848. X    }
  849. X
  850. X    /* Either the user passed us a bogus address, or it's from malloc() */
  851. X
  852. X    for (Blk=Memstart.next,Temp=(&Memstart); Blk; Temp=Blk,Blk=Blk->next)
  853. X    {
  854. X        if ( ptr == Blk->data )
  855. X        {
  856. X            Temp->next=Blk->next;
  857. X            free(Blk->data);
  858. X            return(0);
  859. X        }
  860. X    }
  861. X    return(-1);
  862. X}
  863. X
  864. X#ifdef DEBUG        /* Memory debugging routine */
  865. Xvoid memstat()
  866. X{
  867. X    int i=0, k;
  868. X    struct memblock *blk;
  869. X
  870. X    if ( ! havealloct )
  871. X        return;
  872. X
  873. X    for ( blk=(&memstart); (blk != NULL); blk=blk->next )
  874. X    {
  875. X        fprintf(stderr, "Memory block #%d:\n", i++);
  876. X        fprintf(stderr, "\tfree grains: %d\n", blk->numfree);
  877. X        fprintf(stderr, "\tstarting address: %d\n", blk->head);
  878. X        fprintf(stderr, "\tending address: %d\n", blk->head+MEMSIZ);
  879. X
  880. X        for ( k=0; k<GRAINS; ++k )
  881. X        {
  882. X#ifdef BIGDEBUG
  883. X            if ( blk->grains[k].used )
  884. X                fprintf(stderr, "\tgrain #%d is used.\n", k);
  885. X#endif
  886. X            if ( blk->grains[k].size > 0 )
  887. X            {
  888. X                fprintf(stderr,
  889. X         "\tgrain #%d is a Grain %d grains long at address %d\n", k, 
  890. X                blk->grains[k].size, blk->grains[k].bit);
  891. X            }
  892. X        }
  893. X    }
  894. X}
  895. X
  896. X#endif  /* DEBUG */
  897. X
  898. X
  899. X
  900. X/* These are the binary data functions that I am using instead of 
  901. X   bcopy() and bzero(), written by Richard A. O'Keefe.
  902. X     Thanks!
  903. X*/
  904. X
  905. Xvoid d_copy(src, dst, len)
  906. X    register char *src, *dst;
  907. X    register int len;
  908. X    {
  909. X    while (--len >= 0) *dst++ = *src++;
  910. X    }
  911. X
  912. Xvoid d_zero(dst, len)
  913. X    register char *dst;
  914. X    register int len;
  915. X    {
  916. X    while (--len >= 0) *dst++ = 0;
  917. X    }
  918. X
  919. END_OF_FILE
  920.   if test 5693 -ne `wc -c <'mem.c'`; then
  921.     echo shar: \"'mem.c'\" unpacked with wrong size!
  922.   fi
  923.   # end of 'mem.c'
  924. fi
  925. if test -f 'misc.c' -a "${1}" != "-c" ; then 
  926.   echo shar: Will not clobber existing file \"'misc.c'\"
  927. else
  928.   echo shar: Extracting \"'misc.c'\" \(2844 characters\)
  929.   sed "s/^X//" >'misc.c' <<'END_OF_FILE'
  930. X/*  Miscellaneous routines for the newing package  
  931. X
  932. X    misc.c    Shareware Copyright by Sam Lantinga    5/6/93    
  933. X*/
  934. X
  935. X#include    <signal.h>
  936. X
  937. X#ifdef HAVE_TERMIO_H
  938. X#include <termio.h>
  939. X#else
  940. X#include <sys/ioctl.h>
  941. X#endif  /* HAVE_TERMIO_H */
  942. X
  943. X#ifdef HAVE_BSDTTY_H
  944. X#include <sys/bsdtty.h>
  945. X#endif /* HAVE_BSDTTY_H */
  946. X
  947. X/* Include the local include file after all the system includes */
  948. X#include    "newing.h"
  949. X
  950. X/* The signal handlers and cleanup routines */
  951. X
  952. Xvoid finish(retval)
  953. Xint retval;
  954. X{
  955. X    /* Close the master fd, sending (I hope) an EOF to the 
  956. X       pty process, then kill it with SIGHUP.  */
  957. X    close(masterfd);
  958. X    if ( kill(childpid, 0) >= 0 )
  959. X        sendsig(SIGHUP);
  960. X
  961. X    /* Reset the terminal */
  962. X    if ( tty_reset(ttyfd) < 0 )
  963. X    {
  964. X        fprintf(stderr, "tty_reset() failed! Going sane....\n");
  965. X        (void) tty_sane(ttyfd);
  966. X    }
  967. X
  968. X    /* Clear the utmp entry, if needed */
  969. X    if ( flag.utlog )
  970. X        (void) utmp(utinfo.tty, utinfo.name, time(NULL), 1);
  971. X
  972. X    exit(retval);
  973. X}
  974. X
  975. Xvoid sendsig(sig)
  976. Xint sig;
  977. X{
  978. X#ifdef TIOCGPGRP
  979. X    int pgrp;
  980. X
  981. X    if ( ioctl(masterfd, TIOCGPGRP, (char *) &pgrp) == 0 )
  982. X        (void) kill(-pgrp, sig);
  983. X    else
  984. X        (void) kill(childpid, sig);
  985. X#else  /* No TIOCGPGRP */
  986. X    (void) kill(childpid, sig);
  987. X#endif /* TIOCGPGRP */
  988. X}
  989. X
  990. X
  991. X/* Run a subshell from a tty in raw mode */
  992. X
  993. Xvoid subshell(command)
  994. Xchar *command;
  995. X{
  996. X    /* Reset the terminal */
  997. X    if ( tty_reset(ttyfd) < 0 )
  998. X        (void) tty_sane(ttyfd);
  999. X
  1000. X    /* Execute a subshell */
  1001. X    system(command);
  1002. X
  1003. X    /* Re-set the terminal raw */
  1004. X    (void) tty_raw(ttyfd);
  1005. X}
  1006. X
  1007. X
  1008. X/* Cat the contents of a file to a file descriptor, returning 0
  1009. X   if everything went well, or -1 if an error occurred.  */
  1010. X
  1011. Xint cat(file, fd)
  1012. Xchar *file;
  1013. Xint fd;
  1014. X{
  1015. X    char buffer[BUFSIZ];
  1016. X    FILE *fp;
  1017. X    int len;
  1018. X
  1019. X    if ( (fp=fopen(file, "r")) == NULL )
  1020. X        return(-1);
  1021. X
  1022. X    while ( fgets(buffer, BUFSIZ-1, fp) != NULL )
  1023. X    {
  1024. X        len=strlen(buffer);
  1025. X        if ( writen(fd, buffer, len) != len )
  1026. X            return(-1);
  1027. X    }
  1028. X    return(0);
  1029. X}
  1030. X
  1031. X
  1032. X/* Write a buffer to a descriptor while stripping Ctrl-M's.
  1033. X   Useful for writing terminal i/o to a logfile.  Returns the
  1034. X   number of characters written to the descriptor   */
  1035. X
  1036. Xint writelog(fd, buf, len)
  1037. Xint fd;
  1038. Xchar *buf;
  1039. Xint len;
  1040. X{
  1041. X    int   wlen=0, i;
  1042. X    char *ptr, *bufptr;
  1043. X    char *buffer;
  1044. X
  1045. X    if ( (buffer=myalloc(len)) == NULL )
  1046. X        return(-1);
  1047. X    else
  1048. X        bufptr=buffer;
  1049. X
  1050. X    for ( ptr=buf, i=0; i<len; ++i, ++ptr )
  1051. X    {
  1052. X        if ( *ptr != ('M'^64) )
  1053. X        {
  1054. X            *bufptr=(*ptr);
  1055. X            ++bufptr;
  1056. X            ++wlen;
  1057. X        }
  1058. X    }
  1059. X    wlen=write(fd, buffer, wlen);
  1060. X
  1061. X    (void) myfree(buffer);
  1062. X    return(wlen);
  1063. X}
  1064. X
  1065. X/*
  1066. X * Write "n" bytes to a descriptor.
  1067. X * Use in place of write() when fd is a stream socket.
  1068. X */
  1069. X
  1070. Xint writen(fd, ptr, nbytes)
  1071. Xregister int    fd;
  1072. Xregister char    *ptr;
  1073. Xregister int    nbytes;
  1074. X{
  1075. X    int    nleft, nwritten;
  1076. X
  1077. X    nleft = nbytes;
  1078. X    while (nleft > 0) {
  1079. X        nwritten = write(fd, ptr, nleft);
  1080. X        if (nwritten <= 0)
  1081. X            return(nwritten);        /* error */
  1082. X
  1083. X        nleft -= nwritten;
  1084. X        ptr   += nwritten;
  1085. X    }
  1086. X    return(nbytes - nleft);
  1087. X}
  1088. END_OF_FILE
  1089.   if test 2844 -ne `wc -c <'misc.c'`; then
  1090.     echo shar: \"'misc.c'\" unpacked with wrong size!
  1091.   fi
  1092.   # end of 'misc.c'
  1093. fi
  1094. if test -f 'newing.c' -a "${1}" != "-c" ; then 
  1095.   echo shar: Will not clobber existing file \"'newing.c'\"
  1096. else
  1097.   echo shar: Extracting \"'newing.c'\" \(6176 characters\)
  1098.   sed "s/^X//" >'newing.c' <<'END_OF_FILE'
  1099. X
  1100. X/*  newing.c   Shareware Copyright by Sam Lantinga    5/6/93    */
  1101. X
  1102. X/* 
  1103. X    This is the third time I'm writing shawing.  
  1104. X    This time I'm calling it newing, and I am going to
  1105. X    avoid some of that feeping creaturism that crept into 
  1106. X    my last version.  This one will be well organized, 
  1107. X    documented, and best of all, clean. :)
  1108. X
  1109. X                -Sam Lantinga    4/23/93
  1110. X*/
  1111. X
  1112. X#ifndef lint
  1113. Xstatic char copyright[] = "@(#) Shareware Copyright (c) 1993 Sam Lantinga\n";
  1114. Xstatic char sccsid[] = "@(#) newing    Alpha release 1.0 () 5/6/93";
  1115. X#endif /* lint */
  1116. X
  1117. X#include    <sys/types.h>
  1118. X#include    <fcntl.h>
  1119. X#include    <signal.h>
  1120. X#include    <errno.h>
  1121. X#include    <sys/time.h>
  1122. X#include    "newing.h"
  1123. X
  1124. X#ifdef NEED_SELECT_H
  1125. X#include    <sys/select.h>
  1126. X#endif
  1127. X
  1128. X#ifdef NEED_INET_H
  1129. X#include    <sys/inet.h>
  1130. X#endif
  1131. X
  1132. X
  1133. Xstruct flags     flag;            /* The set of flags */
  1134. Xstruct ut_info    utinfo;            /* The utmp info structure */
  1135. Xint   escape='-';            /* the default escape character */
  1136. Xint   logfd=(-1);            /* The logfile file descriptor  */
  1137. Xchar *logfile=NULL;            /* The name of the logfile      */
  1138. Xint   childpid;                /* The pid of the child process */
  1139. Xint   masterfd;                /* The fd of the pty's master side */
  1140. Xint   ttyfd;                /* The fd of the controlling tty */
  1141. Xstruct passwd *dosuid=NULL;        /* The child suid passwd entry */
  1142. X
  1143. X
  1144. Xmain(argc, argv)
  1145. Xint argc;
  1146. Xchar *argv[];
  1147. X{
  1148. X    extern char *optarg;
  1149. X    extern int   optind;
  1150. X    extern int   errno;
  1151. X    extern char *sys_errlist[];
  1152. X
  1153. X    int maxfds, numready;
  1154. X    int c, i, len;
  1155. X    char buffer[MAXLINE], *args[MAXARGS];
  1156. X    char *startup=NULL;
  1157. X    char *goodopts, **response;
  1158. X    fd_set read_mask;
  1159. X    struct timeval tv, *tvptr;
  1160. X    struct passwd *pw, chpw;
  1161. X
  1162. X#ifdef NEED_INET_H
  1163. X    /* There is a bug in the Wallabong Group's implementation
  1164. X       of select().  It will not work properly with fd 0 */
  1165. X
  1166. X    if ( (ttyfd=dup(0)) < 0 )
  1167. X    {
  1168. X        perror("dup() error");
  1169. X        exit(2);
  1170. X    }
  1171. X#else
  1172. X    ttyfd=0;
  1173. X#endif
  1174. X
  1175. X    /* Save the terminal settings */
  1176. X    if ( tty_getmode(ttyfd) < 0 )
  1177. X    {
  1178. X        perror("Can't get the settings of your terminal");
  1179. X        exit(2);
  1180. X    }
  1181. X
  1182. X    /* Initialize some features */
  1183. X    if ( init_history() < 0 )
  1184. X    {
  1185. X        perror("Can't initialize history");
  1186. X        exit(2);
  1187. X    }
  1188. X    d_zero((char *)&utinfo, sizeof(utinfo));
  1189. X
  1190. X    /* Set default flags */
  1191. X    flag.debug=0;
  1192. X    flag.edit=0;
  1193. X    flag.logstream=0;
  1194. X    flag.restrict=0;
  1195. X    flag.utlog=0;
  1196. X    flag.verbose=0;
  1197. X
  1198. X    /* An undocumented feature:  
  1199. X        If we are running as root, we can use the '-p'
  1200. X        option to run the shell as a specific user.
  1201. X        This can be helpful for system administrators.
  1202. X     */
  1203. X
  1204. X    /* Get the run-time arguments. */
  1205. X
  1206. X    if ( geteuid() == 0 )
  1207. X        goodopts="ehil:p:rs:uvx";
  1208. X    else
  1209. X        goodopts="ehil:rs:uvx";
  1210. X
  1211. X    while ( (c=getopt(argc, argv, goodopts)) != EOF )
  1212. X    {
  1213. X        switch (c)
  1214. X        {
  1215. X            case 'e':  escape=optarg[0];
  1216. X                   break;
  1217. X            case 'h':  print_help("usage");
  1218. X                   exit(0);
  1219. X            case 'i':  flag.edit=1;
  1220. X                   break;
  1221. X            case 'l':  flag.logstream=1;
  1222. X                   logfile=optarg;
  1223. X                       break;
  1224. X            case 'p':  /* Set up the user to setuid the child to */
  1225. X                   if ( (pw=getpwnam(optarg)) == NULL )
  1226. X                   {
  1227. X                    fprintf(stderr, 
  1228. X                    "Can't find user '%s'\n", optarg);
  1229. X                    exit(1);
  1230. X                   }
  1231. X                   dosuid=(&chpw);
  1232. X                   d_copy(pw, dosuid, sizeof(struct passwd));
  1233. X                   break;
  1234. X            case 'r':  flag.restrict=1;
  1235. X                   break;
  1236. X            case 's':  startup=optarg;
  1237. X                   break;
  1238. X            case 'u':  flag.utlog=1;
  1239. X                   break;
  1240. X            case 'v':  flag.verbose=1;
  1241. X                   break;
  1242. X            case 'x':  flag.debug=1;
  1243. X                   flag.verbose=1;
  1244. X                   break;
  1245. X            default:   fprintf(stderr, "%s", Usage);
  1246. X                   exit(1);
  1247. X        }
  1248. X                    
  1249. X    }
  1250. X    /* Set argv to the program on the command line, if any */
  1251. X    argv=(&argv[optind]);
  1252. X
  1253. X    /* Open the logfile if we want */
  1254. X    if ( logfile != NULL )
  1255. X    {
  1256. X        if ((logfd=open(logfile,(O_WRONLY|O_CREAT|O_APPEND),0666)) < 0)
  1257. X        {
  1258. X            fprintf(stderr, "Can't open %s: ", logfile);
  1259. X            perror("");
  1260. X            exit(2);
  1261. X        }
  1262. X    }
  1263. X
  1264. X    /* Set the shell */
  1265. X    if ( argv[0] )
  1266. X    {
  1267. X        for ( i=0; argv[i]; ++i )
  1268. X            args[i]=argv[i];
  1269. X        args[i]=NULL;
  1270. X    }
  1271. X    else
  1272. X    {
  1273. X        args[0]=SHELL;
  1274. X        args[1]=NULL;
  1275. X    }
  1276. X
  1277. X    /* Prevent the child going <defunct> on us.  */
  1278. X    signal(SIGCLD, SIG_IGN);
  1279. X
  1280. X    if ( (masterfd=pty_open(args, &childpid)) < 0 )
  1281. X    {
  1282. X        perror("pty_open() error");
  1283. X        exit(2);
  1284. X    }
  1285. X
  1286. X    /* Set the signal handlers and go raw! */
  1287. X#ifdef SIGWINCH
  1288. X    signal(SIGWINCH, updatewin);
  1289. X#endif
  1290. X    signal(SIGTERM, finish);
  1291. X    (void) tty_raw(ttyfd);
  1292. X
  1293. X#if defined(SOLARIS) || defined(HAVE_BSDTTY_H)
  1294. X    maxfds=32;        /* Any comments?  This is a WAG */
  1295. X#else
  1296. X    maxfds=getdtablesize();
  1297. X#endif
  1298. X    /* Set select() timeout, and zero out the read mask */
  1299. X#ifdef NEED_INET_H
  1300. X    tv.tv_sec=3;
  1301. X    tv.tv_usec=0;
  1302. X    tvptr=&tv;
  1303. X#else
  1304. X    tvptr=NULL;
  1305. X#endif
  1306. X    /* Initialize from the .newingrc, and Jam!!  */
  1307. X    if ( startup )
  1308. X        init_rc(startup, masterfd);
  1309. X    FD_ZERO(&read_mask);
  1310. X
  1311. X    for ( ; ; )
  1312. X    {
  1313. X        /* Make sure the child is still alive */
  1314. X        if ( kill(childpid, 0) < 0 )
  1315. X            finish(0);
  1316. X
  1317. X        FD_SET(ttyfd, &read_mask);
  1318. X        FD_SET(masterfd, &read_mask);
  1319. X
  1320. X        if ( (numready=select(maxfds, &read_mask, 0, 0, tvptr)) <= 0 )
  1321. X        {
  1322. X#ifndef NEED_INET_H            /* Wallabong select() is buggy */
  1323. X            switch (errno)
  1324. X            {
  1325. X                case EIO:    /* The program is finished. */
  1326. X                           break;
  1327. X                case EINTR:  /* Probably SIGWINCH */
  1328. X                        break;
  1329. X                default:       perror("select() error");
  1330. X                           fprintf(stderr, "\r");
  1331. X                           break;
  1332. X            }
  1333. X            if ( errno != EINTR )
  1334. X                finish(0);
  1335. X#endif
  1336. X        }
  1337. X
  1338. X        if ( FD_ISSET(ttyfd, &read_mask) )
  1339. X        {
  1340. X            if ( (len=read(ttyfd, buffer, MAXLINE)) < 0 )
  1341. X            {
  1342. X                perror("Read error on ttyfd");
  1343. X                exit(2);
  1344. X            }
  1345. X
  1346. X            /* Check for escapes and stuff */
  1347. X
  1348. X            /* Pass what's left to the pty */
  1349. X            if ( flag.restrict )
  1350. X                writen(masterfd, buffer, len);
  1351. X            else
  1352. X                hist_write(masterfd, buffer, len);
  1353. X        }
  1354. X
  1355. X        if  ( FD_ISSET(masterfd, &read_mask) )
  1356. X        {
  1357. X            if ( (len=read(masterfd, buffer, MAXLINE)) <= 0 )
  1358. X            {
  1359. X                switch (errno)
  1360. X                {
  1361. X                    case EIO: /* The program is finished */
  1362. X#ifdef DEBUG
  1363. X                          fprintf(stderr, 
  1364. X                        "EIO on masterfd.\r\n");
  1365. X#endif
  1366. X                    default:  finish(0);
  1367. X                }
  1368. X                continue;
  1369. X            }
  1370. X
  1371. X            /* Log the output if we want */
  1372. X            if ( flag.logstream )
  1373. X                writelog(logfd, buffer, len);
  1374. X
  1375. X            /* Check for special strings */
  1376. X            for ( (response=matchtrig(buffer, len));
  1377. X                            *response; ++response )
  1378. X            {
  1379. X                writen(masterfd,*response,strlen(*response));
  1380. X                writen(masterfd, "\r", 1);
  1381. X            }
  1382. X
  1383. X            /* Write to standard output */
  1384. X            writen(1, buffer, len);
  1385. X        }
  1386. X
  1387. X    }
  1388. X}
  1389. END_OF_FILE
  1390.   if test 6176 -ne `wc -c <'newing.c'`; then
  1391.     echo shar: \"'newing.c'\" unpacked with wrong size!
  1392.   fi
  1393.   # end of 'newing.c'
  1394. fi
  1395. if test -f 'newing.h' -a "${1}" != "-c" ; then 
  1396.   echo shar: Will not clobber existing file \"'newing.h'\"
  1397. else
  1398.   echo shar: Extracting \"'newing.h'\" \(4381 characters\)
  1399.   sed "s/^X//" >'newing.h' <<'END_OF_FILE'
  1400. X
  1401. X/* A simple header file for newing */
  1402. X
  1403. X/* I owe a great deal to W. Richard Stevens who, through his
  1404. X   books, basically taught me the inner workings of many UNIX
  1405. X   mysteries.   Thank you!!
  1406. X */
  1407. X
  1408. X/*  Shareware Copyright (c) 1993 Sam Lantinga
  1409. X
  1410. X        newing        Alpha release 1.0     5/6/93
  1411. X*/
  1412. X
  1413. X#include    <stdio.h>    /* Common include file.  Include it here. */
  1414. X#include    <pwd.h>        /* Actually here by request from a sysadm */
  1415. X
  1416. Xextern struct passwd *getpwnam();
  1417. X
  1418. X#define SHELL    "/bin/csh"    /* the default shell to run    */
  1419. X
  1420. X#ifndef MAXARGS            /* The maximum arguments for SHELL */
  1421. X#define MAXARGS        25
  1422. X#endif
  1423. X#define MAXLINE        BUFSIZ        /* A good common line length */
  1424. X
  1425. X/* Macro that makes uppercase letter X a control char */
  1426. X#undef toctrl
  1427. X#define toctrl(X)        (X-'@')    
  1428. X
  1429. X/* Flags for newing */
  1430. X
  1431. Xstruct flags {
  1432. X    int debug;        /* Are we in debug mode?       */
  1433. X    int edit;        /* Are we in line edit mode?   */
  1434. X    int logstream;        /* Do we log the pseudo tty?   */
  1435. X    int restrict;        /* Do we restrict the user?    */
  1436. X    int utlog;        /* Do we create a utmp entry?  */
  1437. X    int verbose;        /* Are we in verbose mode?     */
  1438. X    };
  1439. X
  1440. Xextern struct flags flag;    /* The actual flags            */
  1441. X
  1442. X
  1443. X/* A structure that contains info on the pty process for utmp logging */
  1444. X
  1445. Xstruct ut_info {
  1446. X    int   cpid;        /* The proccess id       */
  1447. X    int   pgrp;        /* The process group id  */
  1448. X    int   euid;        /* The effective user id */
  1449. X    char  tty[24];        /* The tty name (ttyxy)  */
  1450. X    char  name[12];        /* The user's name       */
  1451. X    };
  1452. X
  1453. Xextern struct ut_info utinfo;    /* The actual structure used */
  1454. X
  1455. X
  1456. X/* A doubly linked list of structures for the history feature. */
  1457. X
  1458. Xstruct history {
  1459. X    struct history *prev;
  1460. X    char buf[MAXLINE];
  1461. X    struct history *next;
  1462. X    };
  1463. X
  1464. Xextern struct history *currhist;
  1465. X
  1466. Xextern int   childpid;        /* The pid of the child process */
  1467. Xextern int   masterfd;        /* The fd of the pty's master side */
  1468. Xextern int   ttyfd;        /* The fd of the controlling tty */
  1469. Xextern int   escape;        /* The escape character        */
  1470. Xextern int   histchar;        /* The history character       */
  1471. Xextern int   logfd;        /* The logfile file descriptor */
  1472. Xextern char *logfile;        /* The logfile for the pty     */
  1473. Xextern char *Usage;        /* The usage message           */
  1474. Xextern char ile_errmesg[];    /* Error message from init_ile() */
  1475. Xextern char alias_error[];    /* Error message from alias.c  */
  1476. Xextern struct passwd *dosuid;    /* Suid passwd entry and flag  */
  1477. X
  1478. Xextern void  print_help();    /* Print out the help message  */
  1479. Xextern void  print_status();    /* Print out the current flags */
  1480. Xextern void  read_escape();    /* Process escape commands     */
  1481. Xextern void  finish();        /* Clean up and quit.          */
  1482. Xextern void  sendsig();        /* Send a signal to the pty    */
  1483. Xextern void  subshell();    /* Run a subshell from newing  */
  1484. Xextern void  d_zero();        /* Replacement for bzero()     */
  1485. Xextern void  d_copy();        /* Replacement for bcopy()     */
  1486. X
  1487. Xextern char *ile();        /* Internal line editor        */
  1488. Xextern char *getalias();    /* Get an alias definition     */
  1489. Xextern char *myalloc();        /* Simple malloc() wrapper     */
  1490. X
  1491. Xextern int   myfree();        /* Complement to myalloc()     */
  1492. Xextern int   init_history();    /* Initialize the history bufs */
  1493. Xextern int   hist_write();    /* Process tty input to pty    */
  1494. Xextern int   add_alias();    /* Add an alias definition     */
  1495. Xextern int   del_alias();    /* Delete an alias definition  */
  1496. Xextern int   add_trig();    /* Add a trigger to the list      */
  1497. Xextern int   del_trig();    /* Remove a trigger from the list */
  1498. Xextern char **matchtrig();    /* Return trigger match responses */
  1499. Xextern int   issignal();    /* Do we have a signal character?     */
  1500. Xextern int   writelog();    /* Write a buffer, stripping Ctrl-M's */
  1501. Xextern int   pty_open();    /* Fork a process under a pty  */
  1502. X
  1503. Xextern void  init_rc();        /* Start up from .newingrc     */
  1504. Xextern void  showhistory();    /* Show the current history list */ 
  1505. Xextern void  showaliases();    /* Show the current alias list */ 
  1506. Xextern void  showtriggers();    /* Show the current trigger list */
  1507. Xextern void  updatewin();    /* Update the pty winsize      */
  1508. Xextern int   tty_getmode();    /* Save the current tty modes  */
  1509. Xextern int   tty_reset();       /* Reset the tty modes         */
  1510. Xextern int   tty_sane();        /* Just make the tty sane      */
  1511. Xextern int   tty_raw();        /* Enable raw input processing */
  1512. Xextern int   tty_echo();        /* Set or unset tty echoing    */
  1513. Xextern int   cat();        /* Type a file to the pty      */
  1514. END_OF_FILE
  1515.   if test 4381 -ne `wc -c <'newing.h'`; then
  1516.     echo shar: \"'newing.h'\" unpacked with wrong size!
  1517.   fi
  1518.   # end of 'newing.h'
  1519. fi
  1520. if test -f 'newing.hlp.UU' -a "${1}" != "-c" ; then 
  1521.   echo shar: Will not clobber existing file \"'newing.hlp.UU'\"
  1522. else
  1523.   echo shar: Extracting \"'newing.hlp.UU'\" \(11961 characters\)
  1524.   sed "s/^X//" >'newing.hlp.UU' <<'END_OF_FILE'
  1525. Xbegin 600 newing.hlp
  1526. XM"@DG;F5W:6YG)R!I<R!D97-I9VYE9"!T;R!P<F]V:61E(&%N(&EN=&5R9F%C
  1527. XM92!L87EE<@IB971W965N('EO=2!A;F0@>6]U<B!P<F]G<F%M+B @5VET:&EN
  1528. XM('1H:7,@;&%Y97(L(&UA;GD@=&AI;F=S"F-A;B!B92!D;VYE+B *"@EO("!9
  1529. XM;W4@8V%N('5S92!A(&AI<W1O<GD@9F5A='5R92!T;R!P<F5V96YT('EO=2!F
  1530. XM<F]M( H)(" @:&%V:6YG('1O(')E='EP92!T:&4@<V%M92!T:&EN9R!O=F5R
  1531. XM(&%N9"!O=F5R(&%G86EN+@H);R @66]U(&-A;B!L;V<@=&AE(&]U='!U="!O
  1532. XM9B!Y;W5R('!R;V=R86T@:6X@82!S:6UI;&%R( H)(" @;6%N;F5R(&%S('1H
  1533. XM92!P<F]G<F%M("=S8W)I<'0G+@H);R @66]U(&-A;B!S96YD('1H92!C;VYT
  1534. XM96YT<R!O9B!A(&9I;&4@=&\@=&AE('!R;V=R86T@"@D@("!Y;W4@87)E(')U
  1535. XM;FYI;F<L(&%S('1H;W5G:"!Y;W4@:&%D('1Y<&5D(&EN('1H90H)(" @=VAO
  1536. XM;&4@9FEL92!B>2!Y;W5R<V5L9BX*"6\@(%EO=2!C86X@9&5T871C:"!P86EN
  1537. XM;&5S<VQY(&9R;VT@82!P<F]G<F%M('1H870@:&%S( H)(" @9G)O>F5N('EO
  1538. XM=7(@=&5R;6EN86P@;W(@;W1H97)W:7-E(&AU;F<N"@EO("!9;W4@8V%N(&5N
  1539. XM86)L92!L:6YE(&5D:71I;F<@;VX@82!P<F]G<F%M('1H870@;F]R;6%L;'D@
  1540. XM"@D@("!D;V5S;B=T(&AA=F4@:70L('-U8V@@87,@8W-H(&]R('1E;&YE="X*
  1541. XM"6\@(%EO=2!C86X@:&%V92!N97=I;F<@<V5N9"!A=71O;6%T:6,@<F5S<&]N
  1542. XM<V5S('1O('1H90H@(" @(" @(" @(&]U='!U="!O9B!T:&4@<')O9W)A;2X*
  1543. XM"DEF('EO=2!A<F4@82!H86-K97(L(&]N92!O9B!T:&4@861V86YT86=E<R!O
  1544. XM9B!T:&ES('!R;V=R86T@:7,@"G1H870@>6]U(&AA=F4@9G5L;"!S;W5R8V4L
  1545. XM(&%N9"!C86X@:6UP;&5M96YT('1H92!F96%T=7)E<R!Y;W4@"FAA=F4@86QW
  1546. XM87ES('=A;G1E9"P@8G5T(&YE=F5R(&AA9"!T:&4@=&EM92!T;R!W<FET92!F
  1547. XM<F]M('-C<F%T8V@N"@H)16YJ;WDA"@D)+5-A;2!,86YT:6YG82 @(" @(" @
  1548. XM(" @(#4O-B\Y,PH@(" @(" @(" @(" @(" @(" @(" @(" @(" @(" @(" @
  1549. XM(" @(" @('-L;W5K96Y 8W,N=6-D879I<RYE9'4*"@I5<V%G93H@;F5W:6YG
  1550. XM(%LM:%T@6RUV72!;+75=(%LM:5T@6RUE(&5S8V%P95]C:&%R72!;+7,@;&%B
  1551. XM96Q="B @(" @(" @(" @(" @6RUL(&QO9V9I;&5=(%MP<F]G<F%M(%MA<F=U
  1552. XM;65N='-=70H*3W!T:6]N<SH*"2UH"0E0<FEN="!A('-I;7!L92!H96QP(&UE
  1553. XM<W-A9V4@86YD(&5X:70*"2UV"0E2=6X@;F5W:6YG(&EN('9E<F)O<V4@;6]D
  1554. XM90H)+74)"4-R96%T92!A('5T;7 @96YT<GD@9F]R(&YE=VEN9PH)+6D)"5-T
  1555. XM87)T(&YE=VEN9R!I;B!L:6YE(&5D:70@;6]D90H)+64@97-C87!E7V-H87()
  1556. XM4V5T('1H92!E<V-A<&4@8VAA<F%C=&5R('1O("=E<V-A<&5?8VAA<B<*"2UL
  1557. XM(&QO9V9I;&4)3&]G('1H92!O=71P=70@=&\@)VQO9V9I;&4G"@DM<R!L86)E
  1558. XM; E);FET:6%L:7IE(&YE=VEN9R!F<F]M("=L86)E;"<@:6X@+FYE=VEN9W)C
  1559. XM"@EP<F]G<F%M"0E2=6X@)W!R;V=R86TG(&EN<W1E860@;V8@=&AE(&1E9F%U
  1560. XM;'0@<VAE;&PN"@H)3F]R;6%L;'DL(&5A8V@@8VAA<F%C=&5R(&ES('!A<W-E
  1561. XM9"!D:7)E8W1L>2!T;R!T:&4@<')O9W)A;2P*8G5T(&EF('EO=2!S970@;&EN
  1562. XM92!E9&ET(&UO9&4L(&5I=&AE<B!W:71H(&$@8V]M;6%N9"!L:6YE(&]P=&EO
  1563. XM;BP*;W(@=VET:"!A;B!E<V-A<&4L(&YE=VEN9R!W:6QL(')E860@:6X@82!L
  1564. XM:6YE(&]F('1E>'0L(&%L;&]W:6YG"GEO=2!T;R!E9&ET(&ET+"!A;F0@=&AE
  1565. XM;B!I="!W:6QL('-E;F0@=&AE(&QI;F4@=&\@=&AE('!R;V=R86T@=&AA= IY
  1566. XM;W4@87)E(')U;FYI;F<N(" *"45A8V@@;&EN92!T:&%T(&ES(&5N=&5R960@
  1567. XM:7,@<V%V960@:6X@=&AE(&AI<W1O<GD@9F5A='5R90IO9B!N97=I;F<N("!%
  1568. XM;G1E<FEN9R!T:&4@:&ES=&]R>2!C:&%R86-T97(@*&1E9F%U;'0Z($-T<FPM
  1569. XM4"D@;VX@82 *;F5W(&QI;F4@9&ES<&QA>7,@=&AE(&QA<W0@;&EN92!T:&%T
  1570. XM('=A<R!T>7!E9"!O;G1O('1H92!S8W)E96XL(&%N9" *86QL;W=S('EO=2!T
  1571. XM;R!E9&ET(&ET+B @5&\@96YT97(@=&5X="P@:G5S="!T>7!E+"!A;F0@=VAE
  1572. XM;B!Y;W4@<')E<W,@"G)E='5R;BP@=&AE(&QI;F4@=VEL;"!B92!S96YT('1O
  1573. XM('1H92!R=6YN:6YG('!R;V=R86TN("!4:&4@961I=&EN9PIF96%T=7)E(&ES
  1574. XM(&QO;W-E;'D@8F%S960@;VX@=&AE($MO<FX@4VAE;&P@96UA8W,@961I=&EN
  1575. XM9R!M;V1E+B @20IQ=6]T92!T:&4@:6YT<F]D=6-T:6]N('1O('1H92!+;W)N
  1576. XM(%-H96QL(&5D:71I;F<@9F5A='5R93H*"2)!;&P@961I=&EN9R!C;VUM86YD
  1577. XM<R!C;VYS:7-T(&5I=&AE<B!O9B!C;VYT<F]L(&-H87)A8W1E<G,*;W(@97-C
  1578. XM87!E('-E<75E;F-E<RX@($-O;G1R;VP@8VAA<F%C=&5R<R!A<F4@;F]T871E
  1579. XM9"!B>2!#=')L+2!F;VQL;W=E9 IB>2!A(&-H87)A8W1E<BX@($9O<B!E>&%M
  1580. XM<&QE+"!#=')L+5@@:7,@=&AE(&YO=&%T:6]N(&9O<B!P<F5S<VEN9PIT:&4@
  1581. XM0W1R;"!K97D@86YD('1H92!X(&-H87)A8W1E<B!K97D@870@=&AE('-A;64@
  1582. XM=&EM92X@($1O(&YO="!P<F5S<PIT:&4@<VAI9G0@:V5Y("AA;'1H;W5G:"!C
  1583. XM;VYT<F]L('-E<75E;F-E<R!A<F4@:6YD:6-A=&5D('=I=&@@8V%P:71A; IL
  1584. XM971T97)S*2X*"@E$96P@:6YD:6-A=&5S('1H870@=&AE(&1E;&5T92!K97D@
  1585. XM<VAO=6QD(&)E('!R97-S960N"@H)17-C87!E('-E<75E;F-E<R!A<F4@<VAO
  1586. XM=VX@87,@17-C+2!F;VQL;W=E9"!B>2!A( IC:&%R86-T97(N("!&;W(@97AA
  1587. XM;7!L92P@>6]U(&5N=&5R($5S8RUD(&)Y('!R97-S:6YG('1H92!%<V,@:V5Y
  1588. XM+ IR96QE87-I;F<@:70L(&%N9"!T:&5N('!R97-S:6YG('1H92!D(&ME>2XB
  1589. XM"@H)22!H879E(&%T=&5M<'1E9"!T;R!K965P($5S8RT@<V5Q=65N8V5S(&%T
  1590. XM(&$@;6EN:6UU;2P*8F5C875S92!)(&9I;F0@:70@8W5M8F5R<V]M92!T;R!K
  1591. XM965P(')E86-H:6YG(&9O<B!T:&4@17-C(&ME>2P*86YD(&%L<V\@8F5C875S
  1592. XM92!T:&4@87)R;W<@:V5Y<R!A<F4@=7-E9"X@(%1H92!A<G)O=R!K97ES(&%R
  1593. XM90IA8W1U86QL>2!B;W5N9"!T;R!%<V,M6T$@=VAE<F4@02!I<R!O;F4@;V8@
  1594. XM=&AE(&QE='1E<G,@02P@0BP@0RP@"F%N9"!$+"!F;W(@96%C:"!O9B!T:&4@
  1595. XM87)R;W<@:V5Y<RX@(&%R<F]W+75P(&ES(&QE='1E<B!!+" *87)R;W<M9&]W
  1596. XM;B!I<R!L971T97(@0BP@87)R;W<M<FEG:'0@:7,@0RP@86YD(&%R<F]W+6QE
  1597. XM9G0@:7,@1"X*2&5R92!A<F4@=&AE(&5D:71I;F<@:V5Y<SH*"D-U<G-O<B!M
  1598. XM;W9E;65N=#H*"4ME>0D)1G5N8W1I;VX*"2TM+2TM+0D)+2TM+2TM+2TM+2TM
  1599. XM+2TM+2TM+2TM+2TM+2TM+2T*"3QL969T+6%R<F]W/@E-;W9E(&QE9G0@;VYE
  1600. XM('-P86-E"@D\<FEG:'0M87)R;W<^"4UO=F4@<FEG:'0@;VYE('-P86-E"@E#
  1601. XM=')L+4()"4UO=F4@8F%C:W=A<F0@;VYE('=O<F0*"4-T<FPM1@D)36]V92!F
  1602. XM;W)W87)D(&]N92!W;W)D"@E#=')L+4$)"4UO=F4@=&\@=&AE(&)E9VEN;FEN
  1603. XM9R!O9B!T:&4@;&EN90H)0W1R;"U%"0E-;W9E('1O('1H92!E;F0@;V8@=&AE
  1604. XM(&QI;F4*"4-T<FPM77@)"4UO=F4@=&\@=&AE(&YE>'0@8VAA<F%C=&5R('@@
  1605. XM;VX@"@D)"71H92!L:6YE"@I%9&ET:6YG.@H)2V5Y"0E&=6YC=&EO;@H)+2TM
  1606. XM+2TM"0DM+2TM+2TM+2TM+2TM+2TM+2TM+2TM+2TM+2TM+0H)/&)A8VMS<&%C
  1607. XM93X)1&5L971E('1H92!C:&%R86-T97(@8F5H:6YD('1H92 *"0D)8W5R<V]R
  1608. XM"@E$96P)"5-A;64@87,@8F%C:W-P86-E"@E#=')L+40)"41E;&5T92!T:&4@
  1609. XM8VAA<F%C=&5R('5N9&5R('1H92 *"0D)8W5R<V]R"@E#=')L+5<)"41E;&5T
  1610. XM92!U<"!T;R!W:&ET92US<&%C92!T;R!T:&4*"0D);&5F="!O9B!T:&4@8W5R
  1611. XM<V]R("AD96QE=&4@=V]R9"D*"4-T<FPM2PD)1&5L971E(&9R;VT@=&AE(&-U
  1612. XM<G-O<B!T;R!T:&4*"0D)96YD(&]F('1H92!L:6YE"@E#=')L+54)"41E;&5T
  1613. XM92!T:&4@=VAO;&4@;&EN90H)0W1R;"U9"0E);G-E<G0@=&AE(&QA<W0@=&5X
  1614. XM="!T:&%T('=A<PH)"0ED96QE=&5D+"!F<F]M('1H92!D96QE=&EO;B!B=69F
  1615. XM97(*"0D):6YT;R!W:&5R92!T:&4@8W5R<V]R(&ES(&YO=PH)0W1R;"U4"0E4
  1616. XM<F%N<W!O<V4@=&AE(&-H87)A8W1E<B!U;F1E<B!T:&4*"0D)8W5R<V]R('=I
  1617. XM=&@@=&AE(&]N92!T;R!T:&4@<FEG:'0N( H)17-C+70)"51R86YS<&]S92!T
  1618. XM:&4@;6%R:V5D(&-H87)A8W1E<B *"0D)=VET:"!T:&4@;VYE('5N9&5R('1H
  1619. XM92!C=7)S;W(*"45S8RUC"0E#87!I=&%L:7IE('1H92!C:&%R86-T97(@=6YD
  1620. XM97(@=&AE"@D)"6-U<G-O<BP@:68@:70@:7,@;&]W97)C87-E+"!O<B!M86ME
  1621. XM"@D)"6ET(&QO=V5R8V%S92!I9B!I="!I<R!C87!I=&%L:7IE9 H)17-C+3QS
  1622. XM<&%C93X)4V5T('1H92!M87)K(&%T('1H92!C=7)R96YT(&-U<G-O<@H)"0EP
  1623. XM;W-I=&EO;@H)17-C+7 )"4-O<'D@=&AE(&QI;F4@9G)O;2!T:&4@;6%R:R!T
  1624. XM;R!T:&4*"0D)8W5R<F5N="!C=7)S;W(@<&]S:71I;VX@:6YT;R!T:&4*"0D)
  1625. XM9&5L971I;VX@8G5F9F5R"@HH06QL('-I9VYA;',@:VEL;"!T:&4@8W5R<F5N
  1626. XM="!L:6YE(&%N9"!A<F4@<V5N="!I;6UE9&EA=&5L>2!T;R!T:&4@<')O9W)A
  1627. XM;2D*4VEG;F%L<SH*"4-T<FPM0PD)4V5N9"!#=')L+4,@=&\@=&AE(')U;FYI
  1628. XM;F<@<')O9W)A;2P*"0D)=VAI8V@@:7,@;F]R;6%L;'D@:6YT97)P<F5T960@
  1629. XM87,@86X*"0D):6YT97)R=7!T(&-H87)A8W1E<BX*"4-T<FPM7 D)4V5N9"!#
  1630. XM=')L+5P@=&\@=&AE(')U;FYI;F<@<')O9W)A;2P*"0D)=VAI8V@@:7,@;F]R
  1631. XM;6%L;'D@:6YT97)P<F5T960@87,@80H)"0EQ=6ET(&-H87)A8W1E<BX*"4-T
  1632. XM<FPM6@D)4V5N9"!#=')L+5H@=&\@=&AE(')U;FYI;F<@<')O9W)A;2P*"0D)
  1633. XM=VAI8V@@8V%N(&)E(&EN=&5R<')E=&5D(&%S(&$@<W1O< H)"0ES:6=N86P@
  1634. XM:68@=&AE('!R;V=R86T@<F5C;V=N:7IE<PH)"0EJ;V(@8V]N=')O;"X@($EF
  1635. XM(&IO8B!C;VYT<F]L(&ES(&YO= H)"0ES=7!P;W)T960@8GD@=&AE('-Y<W1E
  1636. XM;2P@0W1R;"U:(&ES( H)"0EN;W0@=')E871E9"!A<R!S<&5C:6%L+@H*36ES
  1637. XM8V5L;&%N96]U<SH*"4ME>0D)1G5N8W1I;VX*"2TM+2TM+0D)+2TM+2TM+2TM
  1638. XM+2TM+2TM+2TM+2TM+2TM+2TM+2T*"4-T<FPM3 D)4F5D<F%W('1H92!L:6YE
  1639. XM(&]N('1H92!N97AT(&QI;F4*"3QU<"UA<G)O=SX)17)A<V4@=&AE(&-U<G)E
  1640. XM;G0@;&EN92!A;F0@961I= H)"0ET:&4@;F5X="!P<F5V:6]U<R!H:7-T;W)Y
  1641. XM(&)U9F9E<@H)0W1R;"U0"0E386UE(&%S('5P+6%R<F]W"@D\9&]W;BUA<G)O
  1642. XM=SX)17)A<V4@=&AE(&-U<G)E;G0@;&EN92!A;F0@961I= H)"0ET:&4@;F5X
  1643. XM="!H:7-T;W)Y(&)U9F9E<@H)0W1R;"U."0E386UE(&%S(&1O=VXM87)R;W<*
  1644. XM"4-T<FPM5G@)"5%U;W1E('1H92!C:&%R86-T97(@>"!I;G1O('1H92 *"0D)
  1645. XM;&EN92!A="!T:&4@8W5R<F5N="!P;W-I=&EO;@H)/')E='5R;CX)17AI="!E
  1646. XM9&ET(&UO9&4@86YD('-E;F0@=&AE(&QI;F4*"0D)=&\@=&AE(')U;FYI;F<@
  1647. XM<')O9W)A;0H)/&QI;F5F965D/@E386UE(&%S(')E='5R;@H*+2TM+2TM+2TM
  1648. XM+2TM"@H)5VAE;B!T:&4@97-C87!E(&-H87)A8W1E<B H9&5F875L=#H@)RTG
  1649. XM*2!I<R!I;G!U="!A= IT:&4@8F5G:6YN:6YG(&]F(&$@;&EN92P@)VYE=VEN
  1650. XM9R<@=VEL;"!R96%D(&$@;&EN92!O9B!T97AT+@I4:&4@;&EN92!I<R!I;G1E
  1651. XM<G!R971E9"!A<R!A('-P96-I86P@(F5S8V%P92!C;VUM86YD(BP@86YD"F%N
  1652. XM>2!C;W)R97-P;VYD:6YG(&%C=&EO;B!I<R!T86ME;BX@(%1H97)E(&%R92!S
  1653. XM979E<F%L( IC=7)R96YT;'D@:6UP;&5M96YT960@97-C87!E<SH*"@E%<V-A
  1654. XM<&4)"0E!8W1I;VX*"2TM+2TM+2TM+2TM"0DM+2TM+2TM+2TM+2TM+2TM+2TM
  1655. XM+2TM+2T*"79E<F)O<V4)"0E4;V=G;&5S('9E<F)O<V4@;6]D92!O;B!A;F0@
  1656. XM;V9F"@H)97-C87!E(#QE<V-A<&5?8VAA<CX)4V5T<R G97-C87!E7V-H87(G
  1657. XM(&%S('1H92!N97<*"0D)"65S8V%P92!C:&%R86-T97(N"@H):&ES=&-H87(@
  1658. XM/&AI<W1O<GE?8VAA<CX)4V5T<R G:&ES=&]R>5]C:&%R)R!A<R!T:&4@;F5W
  1659. XM"@D)"0EH:7-T;W)Y(&-H87)A8W1E<BX*"@EH:7-T;W)Y"0D)1&ES<&QA>7,@
  1660. XM=&AE(&-U<G)E;G0@:&ES=&]R>2!L:7-T:6YG"@H)961I= D)"51O9V=L97,@
  1661. XM;&EN92!E9&ET(&UO9&4@;VX@86YD(&]F9BX*"@ES=&%T=7,)"0E0<FEN=',@
  1662. XM;W5T('1H92!C=7)R96YT('-T871U<R!O9@H)"0D);F5W:6YG"@H)8V%T(#QF
  1663. XM:6QE/@D)3W!E;G,@=&AE('-P96-I9FEE9"!F:6QE(&%N9"!S96YD<PH)"0D)
  1664. XM:71S(&-O;G1E;G1S('1O('1H92!P<F]G<F%M(&%S"@D)"0ET:&]U9V@@>6]U
  1665. XM(&AA9"!T>7!E9"!T:&5M(&EN+@H*"6%L:6%S(#QN86UE/B \9&5F:6YI=&EO
  1666. XM;CX*"0D)"41E9FEN92!A;B!A;&EA<R!O9B!T:&4@;F%M92 G;F%M92<L"@D)
  1667. XM"0EW:71H('1H92!D969I;FET:6]N("=D969I;FET:6]N)RX*"0D)"4EF('1H
  1668. XM92!D969I;FET:6]N(&ES(&UO<F4@=&AA;@H)"0D);VYE('=O<F0L(&ET(&UU
  1669. XM<W0@8F4@(G%U;W1E9"(N"@H)=6YA;&EA<R \;F%M93X)"5)E;6]V92!T:&4@
  1670. XM86QI87,@)VYA;64G+@H*"7-H;W=A;&EA<PD)3&ES="!T:&4@8W5R<F5N="!A
  1671. XM;&EA<V5S+@H*"6%D9'1R:6<@/&YA;64^(#QT<FEG9V5R/B \<F5S<&]N<V4^
  1672. XM"@D)"0E$969I;F4@82!T<FEG9V5R(&YA;65D("=N86UE)R *"0D)"71H870@
  1673. XM=VEL;"!S96YD("=R97-P;VYS92<@=VAE;@H)"0D)=&AE('!R;V=R86T@;W5T
  1674. XM<'5T<R G=')I9V=E<B<N"@H)9&5L=')I9R \;F%M93X)"5)E;6]V92!T:&4@
  1675. XM=')I9V=E<B G;F%M92<N"@H)<VAO=W1R:6=S"0E,:7-T('1H92!C=7)R96YT
  1676. XM('1R:6=G97)S+@H*"7-U8G-H(%MC;VUM86YD70D)4G5N<R!A('-U8G-H96QL
  1677. XM+"!O<B G8V]M;6%N9"<*"0D)"6EF(&ET(&ES(&=I=F5N+@H*"6AE;' @6W1O
  1678. XM<&EC70D)4')I;G1S(&]U="!H96QP(&9O<B!T:&4@;&ES=&5D"@D)"0ET;W!I
  1679. XM8RX@($-O;6UO;B!T;W!I8W,@87)E(")U<V%G92(L"@D)"0DB961I=&EN9R(L
  1680. XM(&%N9" B97-C87!E<R(N"@H)9&EE"0D)2VEL;',@;F5W:6YG(&%N9"!T:&4@
  1681. XM<')O9W)A;2!I="!I<PH)"0D)<G5N;FEN9RX*"@ES=7-P96YD"0D)4W5S<&5N
  1682. XM9',@;F5W:6YG('5S:6YG(&IO8B!C;VYT<F]L+ H)"0D);W(@<G5N<R!A('-U
  1683. XM8G-H96QL(&EF(&IO8B!C;VYT<F]L"@D)"0EI<R!N;W0@<W5P<&]R=&5D+@H*
  1684. XM"D%L:6%S97,@87)E(&)A<VEC86QL>2!E<V-A<&5S('1H870@97AP86YD('1O
  1685. XM('1E>'0@=&AA="!I<R!S96YT"G1O('1H92!P<F]G<F%M+B @1F]R(&UO<F4@
  1686. XM:&5L<"!O;B!A;&EA<V5S+"!U<V4@=&AE(&5S8V%P93H*"@EH96QP(&%L:6%S
  1687. XM97,*"E1R:6=G97)S(&%R92!B:71S(&]F('1E>'0@=&AA="!A<F4@<V5A<F-H
  1688. XM960@9F]R(&EN('1H92!P<F]G<F%M)W,*;W5T<'5T+B @268@;VYE(&ES(&9O
  1689. XM=6YD+"!T:&4@=&5X="!R97-P;VYS92!I<R!S96YT(&%U=&]M871I8V%L;'D*
  1690. XM=&\@=&AE('!R;V=R86TN("!&;W(@;6]R92!H96QP(&]N('1R:6=G97)S+"!U
  1691. XM<V4@=&AE(&5S8V%P93H*"@EH96QP('1R:6=G97)S"@H*26YI=&EA;&EZ:6YG
  1692. XM.@I)9B!T:&4@)RUS)R!O<'1I;VX@:7,@9VEV96XL(&YE=VEN9R!W:6QL(&EN
  1693. XM:71I86QI>F4@9G)O;2!A( IS=&%R='5P(&9I;&4@*"1(3TU%+RYN97=I;F=R
  1694. XM8RD@870@=&AE('-P96-I9FEE9"!L86)E;"X*02!L86)E;"!I;B!T:&4@<W1A
  1695. XM<G1U<"!F:6QE('-T87)T<R!A="!T:&4@8F5G:6YN:6YG(&]F(&$@;&EN92P@
  1696. XM"G=H:6QE(&5V97)Y=&AI;F<@8F5T=V5E;B!L86)E;',@:7,@8V]N<VED97)E
  1697. XM9"!A('-T87)T=7 @;&EN92X@( I3=&%R='5P(&QI;F5S(&)E9VEN('=I=&@@
  1698. XM=&%B<RP@86YD(&AA=F4@;W!T:6]N86P@=&EM:6YG(&EN9F\N(" *02!L:6YE
  1699. XM(&)E9VEN;FEN9R!W:71H("<C)R!I<R!A(&-O;6UE;G0N("!)9B!T:&4@<W1A
  1700. XM<G1U<"!L:6YE( IS=&%R=',@=VET:"!T:&4@8VAA<F%C=&5R("<J)RP@:70@
  1701. XM:7,@8V]N<VED97)E9"!A;B!E<V-A<&4@86YD( II<R!P<F]C8V5S<V5D+B @
  1702. XM3W1H97)W:7-E('1H92!L:6YE(&ES('-E;G0@=&\@=&AE('!R;V=R86TN"D]U
  1703. XM='!U="!F<F]M('1H92!P<F]G<F%M(&ES('-A=F5D+"!A;F0@=&AE;B!S96YT
  1704. XM('1O('1H92!S8W)E96X@"F%F=&5R(&YE=VEN9R!H87,@9FEN:7-H960@=VET
  1705. XM:"!T:&4@<W1A<G1U<"!F:6QE+@H*17AA;7!L92!S=&%R='5P(&9I;&4Z"BTM
  1706. XM+2TM+2TM+2TM+2TM+2TM+2TM+2TM+2TM+2TM+2TM+2TM+2TM+2TM+2TM+2TM
  1707. XM+2TM+2TM+2TM+2TM+2T*(R!.;W1E.B @5&EM:6YG(&EN9F\@8V%N;F]T(&)E
  1708. XM('5S960@=VET:"!E<V-A<&5S+@H*(R!4:&ES(&QA8F5L('-H;W5L9"!O;FQY
  1709. XM(&)E('5S960@=VET:" O8FEN+W-H"D)O=7)N92!,;V=I;CH*"2X@)$A/344O
  1710. XM+G!R;V9I;&4*"65C:&\@(E=E;&-O;64@=&\@=&AE($)O=7)N92!,;V=I;B$B
  1711. XM"@IS>7-C:&5C:SH*"2IV97)B;W-E"@ER=VAO"B,@5V%I=" W('-E8V]N9',@
  1712. XM869T97(@<G=H;R!B969O<F4@<V5N9&EN9R!T:&4@9FEN9V5R(&QI;F4@=&\@
  1713. XM=&AE('-H96QL"@DW(&9I;F=E<B!M>69R:65N9$!U;FEX+G-Y<W1E;2YE9'4*
  1714. XM"FYO=&AI;CH*"65C:&\[96-H;SME8VAO"@IV:3H*"2IA;&EA<R!A9&0@(D=O
  1715. XM5&AI<R!I<R!A;B!A9&1E9"!L:6YE+AL5:51H:7,@:7,@86X@:6YS97)T960@
  1716. XM;&EN92X;,4<B"@DJ<W1A='5S"@H)(R!786ET(#,@<V5C;VYD<R!A;F0@97AE
  1717. XM8W5T92!V:2X*"3,@=FD*+2TM+2TM+2TM+2TM+2TM+2TM+2TM+2TM+2TM+2TM
  1718. X5+2TM+2TM+2TM+2TM+2TM+2U%3T8*
  1719. Xend
  1720. END_OF_FILE
  1721.   if test 11961 -ne `wc -c <'newing.hlp.UU'`; then
  1722.     echo shar: \"'newing.hlp.UU'\" unpacked with wrong size!
  1723.   else
  1724.     echo shar: Uudecoding \"'newing.hlp'\" \(8661 characters\)
  1725.     cat newing.hlp.UU | uudecode
  1726.     if test 8661 -ne `wc -c <'newing.hlp'`; then
  1727.       echo shar: \"'newing.hlp'\" uudecoded with wrong size!
  1728.     else
  1729.       rm newing.hlp.UU
  1730.     fi
  1731.   fi
  1732.   # end of 'newing.hlp.UU'
  1733. fi
  1734. if test -f 'trigger.c' -a "${1}" != "-c" ; then 
  1735.   echo shar: Will not clobber existing file \"'trigger.c'\"
  1736. else
  1737.   echo shar: Extracting \"'trigger.c'\" \(3301 characters\)
  1738.   sed "s/^X//" >'trigger.c' <<'END_OF_FILE'
  1739. X/*  Trigger matching on stream input text
  1740. X    trigger.c    Shareware Copyright by Sam Lantinga    5/6/93    
  1741. X*/
  1742. X
  1743. X#include    "newing.h"
  1744. X
  1745. X/* Here are the functions:                                         */
  1746. X
  1747. X    void   showtriggers();    /* Prints the trigger list         */
  1748. X    int    add_trig();    /* Adds a trigger to the list      */
  1749. X    int    del_trig();    /* Removes a trigger from the list */
  1750. X    char **matchtrig();    /* Returns match responses         */
  1751. X
  1752. X/* The maximum number of matching triggers allowed */
  1753. X#define MAXTRIGS    8
  1754. X
  1755. X/* The array returned by matchtrig() */
  1756. Xstatic char *keys[MAXTRIGS];
  1757. X
  1758. X/* The actual trigger structure */
  1759. Xstatic struct trigger {
  1760. X    char *label;
  1761. X    char *trig;
  1762. X    char *tptr;
  1763. X    char *response;
  1764. X    struct trigger *next;
  1765. X    } basetrig = { NULL, NULL, NULL, NULL };
  1766. X
  1767. X
  1768. X/* Print out the current trigger listing */
  1769. X
  1770. Xvoid showtriggers()
  1771. X{
  1772. X    struct trigger *here;
  1773. X
  1774. X    printf("Triggers:\r\n");
  1775. X    for ( here=basetrig.next; here; here=here->next )
  1776. X    {
  1777. X        printf("\t%s\t%s\t%s\r\n", here->label, 
  1778. X                    here->trig, here->response);
  1779. X    }
  1780. X}
  1781. X
  1782. X
  1783. X/* Add a trigger to the list of triggers.  Return 0, or (-1) if
  1784. X   all the trigger slots are filled.  */
  1785. X
  1786. Xint add_trig(label, trig, response)
  1787. Xchar *label;
  1788. Xchar *trig;
  1789. Xchar *response;
  1790. X{
  1791. X    struct trigger *prev, *here, *new;
  1792. X
  1793. X    for ( prev=(&basetrig), here=basetrig.next; 
  1794. X            here; prev=here, here=here->next )
  1795. X    {
  1796. X        if ( strcmp(here->label, label) == 0 )
  1797. X            goto create;
  1798. X    }
  1799. X
  1800. X    /* Allocate memory for the new trigger */
  1801. Xcreate:
  1802. X    if ((new=(struct trigger *)myalloc(sizeof(struct trigger)))
  1803. X                                == NULL )
  1804. X        return(-1);
  1805. X    if ( (new->label=myalloc(strlen(label+1))) == NULL )
  1806. X    {
  1807. X        (void) myfree(new);
  1808. X        return(-1);
  1809. X    }
  1810. X    if ( (new->trig=myalloc(strlen(trig+1))) == NULL )
  1811. X    {
  1812. X        (void) myfree(new->label);
  1813. X        (void) myfree(new);
  1814. X        return(-1);
  1815. X    }
  1816. X    if ( (new->response=myalloc(strlen(response+1))) == NULL )
  1817. X    {
  1818. X        (void) myfree(new->label);
  1819. X        (void) myfree(new->trig);
  1820. X        (void) myfree(new);
  1821. X        return(-1);
  1822. X    }
  1823. X
  1824. X    /* Initialize the new trigger */
  1825. X    prev->next=new;
  1826. X    strcpy(new->label, label);
  1827. X    strcpy(new->trig, trig);
  1828. X    strcpy(new->response, response);
  1829. X    new->tptr=new->trig;
  1830. X
  1831. X    if ( here != NULL )
  1832. X    {
  1833. X        new->next=here->next;
  1834. X        (void) myfree(here->label);
  1835. X        (void) myfree(here->label);
  1836. X        (void) myfree(here->label);
  1837. X        (void) myfree(here);
  1838. X    }
  1839. X    else
  1840. X        new->next=NULL;
  1841. X    return(0);
  1842. X}
  1843. X
  1844. X
  1845. X/* Remove a trigger from the list of triggers.  Return (-1) if
  1846. X   the trigger wasn't there, or 0 if everything went well.  */
  1847. X
  1848. Xint del_trig(label)
  1849. Xchar *label;
  1850. X{
  1851. X    struct trigger *prev, *here, *new;
  1852. X
  1853. X    for ( prev=(&basetrig), here=basetrig.next; 
  1854. X            here; prev=here, here=here->next )
  1855. X    {
  1856. X        if ( strcmp(here->label, label) == 0 )
  1857. X        {
  1858. X            prev->next=here->next;
  1859. X            (void) myfree(here->label);
  1860. X            (void) myfree(here->label);
  1861. X            (void) myfree(here->label);
  1862. X            (void) myfree(here);
  1863. X            return(0);
  1864. X        }
  1865. X    }
  1866. X    return(-1);
  1867. X}
  1868. X
  1869. X
  1870. X/* Match each trigger with the given text  */
  1871. X
  1872. Xchar **matchtrig(line, len)
  1873. Xchar *line; 
  1874. Xint len;
  1875. X{
  1876. X    struct trigger *here;
  1877. X    char *ptr;
  1878. X    int k=0, i;
  1879. X
  1880. X    for ( ptr=line, i=0; (i<len); ++i, ++ptr )
  1881. X    {
  1882. X        for (here=basetrig.next; here&&(k<MAXTRIGS); here=here->next)
  1883. X        {
  1884. X            if ( *(here->tptr) == *ptr )
  1885. X            {
  1886. X                /* Do we have a match? */
  1887. X                if ( ! *(++here->tptr) )
  1888. X                {
  1889. X                    keys[k++]=here->response;
  1890. X                    here->tptr=here->trig;
  1891. X                }
  1892. X            }
  1893. X            else
  1894. X                here->tptr=here->trig;
  1895. X        }
  1896. X    }
  1897. X    keys[k]=NULL;
  1898. X    return(keys);
  1899. X}
  1900. END_OF_FILE
  1901.   if test 3301 -ne `wc -c <'trigger.c'`; then
  1902.     echo shar: \"'trigger.c'\" unpacked with wrong size!
  1903.   fi
  1904.   # end of 'trigger.c'
  1905. fi
  1906. echo shar: End of archive 2 \(of 3\).
  1907. cp /dev/null ark2isdone
  1908. MISSING=""
  1909. for I in 1 2 3 ; do
  1910.     if test ! -f ark${I}isdone ; then
  1911.     MISSING="${MISSING} ${I}"
  1912.     fi
  1913. done
  1914. if test "${MISSING}" = "" ; then
  1915.     echo You have unpacked all 3 archives.
  1916.     rm -f ark[1-9]isdone
  1917. else
  1918.     echo You still must unpack the following archives:
  1919.     echo "        " ${MISSING}
  1920. fi
  1921. exit 0
  1922. exit 0 # Just in case...
  1923.