home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1994 March / Source_Code_CD-ROM_Walnut_Creek_March_1994.iso / compsrcs / misc / volume32 / ecu / part07 < prev    next >
Encoding:
Text File  |  1992-09-10  |  57.0 KB  |  2,337 lines

  1. Newsgroups: comp.sources.misc
  2. From: wht@n4hgf.mt-park.ga.us (Warren Tucker)
  3. Subject:  v32i042:  ecu - ECU Asynchronous Communications v3.20, Part07/40
  4. Message-ID: <1992Sep11.192654.7262@sparky.imd.sterling.com>
  5. X-Md4-Signature: 0d7fbd07d4f42b73dd1b7e3d67c52050
  6. Date: Fri, 11 Sep 1992 19:26:54 GMT
  7. Approved: kent@sparky.imd.sterling.com
  8.  
  9. Submitted-by: wht@n4hgf.mt-park.ga.us (Warren Tucker)
  10. Posting-number: Volume 32, Issue 42
  11. Archive-name: ecu/part07
  12. Environment: SCO,XENIX,ISC,SUNOS,SYSVR4,HDB,Curses
  13. Supersedes: ecu: Volume 21, Issue 53-89
  14.  
  15. ---- Cut Here and feed the following to sh ----
  16. #!/bin/sh
  17. # this is ecu320.07 (part 7 of ecu320)
  18. # do not concatenate these parts, unpack them in order with /bin/sh
  19. # file ecufinsert.c continued
  20. #
  21. if test ! -r _shar_seq_.tmp; then
  22.     echo 'Please unpack part 1 first!'
  23.     exit 1
  24. fi
  25. (read Scheck
  26.  if test "$Scheck" != 7; then
  27.     echo Please unpack part "$Scheck" next!
  28.     exit 1
  29.  else
  30.     exit 0
  31.  fi
  32. ) < _shar_seq_.tmp || exit 1
  33. if test ! -f _shar_wnt_.tmp; then
  34.     echo 'x - still skipping ecufinsert.c'
  35. else
  36. echo 'x - continuing file ecufinsert.c'
  37. sed 's/^X//' << 'SHAR_EOF' >> 'ecufinsert.c' &&
  38. X{
  39. Xint itmp;
  40. Xregister rchar;
  41. Xint old_ttymode = get_ttymode();
  42. Xlong total_chars = 0L;
  43. Xlong total_lines = 0L;
  44. Xulong colors_at_entry = colors_current;
  45. Xlong timeout_msecs;
  46. XFILE *fp;
  47. Xchar file_string[256];
  48. Xchar s256[256];
  49. Xchar xmit_mode;
  50. Xuchar delim;
  51. X#ifdef USE_XON_XOFF
  52. Xint ixon;
  53. Xint ixoff;
  54. X#endif
  55. Xchar *make_char_graphic();
  56. X
  57. X    sigint = 0;
  58. X
  59. X    if(narg > 1)
  60. X    {
  61. X        strncpy(s256,arg[1],sizeof(s256));    
  62. X        s256[sizeof(s256) - 1] = 0;
  63. X    }
  64. X    else
  65. X    {
  66. X        ff(se,"\r\n--> File to insert on comm line: ");
  67. X        ttygets(s256,sizeof(s256),TG_CRLF,&delim,(int *)0);
  68. X        if((delim == ESC) || !strlen(s256)) 
  69. X        {
  70. X            ff(se," --> transmission aborted\r\n");
  71. X            return(0);
  72. X        }
  73. X    }
  74. X    if((itmp = expand_filename(s256,sizeof(s256))) < 0)
  75. X        return(-1);
  76. X    else if(itmp)
  77. X        ff(se,"\r\n--> wild card match: %s",s256);
  78. X
  79. X    if((fp = fopen(s256,"r")) == (FILE *)0)
  80. X    {
  81. X        ff(se,"\r\n--> ");
  82. X        pperror(s256);            /* print error if we get one */
  83. X        return(-1);
  84. X    }
  85. X
  86. X    if(narg > 1)
  87. X        ff(se,"\r\n");
  88. X
  89. X    if(narg > 2)
  90. X        xmit_mode = *arg[2];
  91. X    else
  92. X    {
  93. XASK_OPTION:
  94. X        ff(se,"(S)ingle line at a time\r\n");
  95. X        ff(se,"(E)cho pacing\r\n");
  96. X        ff(se,"(F)ull speed transmission\r\n");
  97. X        ff(se,"(P)aced transmission (20 msec/char)\r\n");
  98. X        ff(se,"(Q)uit (or ESC)          press a key:   ");
  99. X        xmit_mode = ttygetc(0) & 0x7F;
  100. X        if(xmit_mode > 0x20)
  101. X            fputs(make_char_graphic(xmit_mode,0),se);
  102. X        fputs("\r\n",se);
  103. X    }
  104. X
  105. X    kill_rcvr_process(SIGUSR1);
  106. X
  107. X    switch(xmit_mode = to_lower(xmit_mode))
  108. X    {
  109. X        case 's':
  110. X            setcolor(colors_alert);
  111. X            fputs("--> press SPACE to continue or ESC/'s' to stop\r\n",se);
  112. X            setcolor(colors_at_entry);
  113. X            break;
  114. X
  115. X        case 'e':
  116. X            /* fall through */
  117. X
  118. X        case 'f':
  119. X        case 'p':
  120. X            setcolor(colors_alert);
  121. X            ff(se,"--> press %s to abort\r\n",make_char_graphic(kbdintr,0));
  122. X            setcolor(colors_at_entry);
  123. X            ttymode(2);
  124. X            break;
  125. X
  126. X        case 'q':
  127. X        case ESC:
  128. X            goto INSERT_DONE2;
  129. X
  130. X        default:
  131. X            ring_bell();
  132. X            fputs("\r\n",se);
  133. X            goto ASK_OPTION;
  134. X    }
  135. X
  136. X#ifdef USE_XON_XOFF
  137. X    lget_xon_xoff(&ixon,&ixoff);        /* get current line xon/xoff status */
  138. X    lxon_xoff(IXON);                    /* set it for us */
  139. X#endif
  140. X
  141. X    while(fgets(file_string,sizeof(file_string),fp))
  142. X    {
  143. X    int xmit_len = strlen(file_string);
  144. X    int xmit_cr = xmit_len && (file_string[xmit_len - 1] == NL);
  145. X
  146. X        if(xmit_cr)
  147. X        {
  148. X            xmit_len--;
  149. X            file_string[xmit_len] = 0;
  150. X        }
  151. X        total_chars += xmit_len;
  152. X        total_lines++;
  153. X
  154. X/* some destinations, like BBS msg entry, take a blank line to mean
  155. Xend of message, so do not send completely blank lines */
  156. X        if(!xmit_len && xmit_cr)
  157. X        {
  158. X            lputc(' ');
  159. X            xmit_len = 1;
  160. X        }
  161. X        else if(xmit_mode == 'p')
  162. X        {
  163. X        register char *cptr = file_string;
  164. X            while(*cptr)
  165. X            {
  166. X                lputc(*cptr++);
  167. X                Nap(20L);
  168. X                while(rdchk(shm->Liofd))
  169. X                {
  170. X                    rchar = lgetc_xmtr();
  171. X                    process_xmtr_rcvd_char((char)rchar,1);
  172. X                }
  173. X            }
  174. X        }
  175. X        else
  176. X            lputs(file_string);
  177. X        if(xmit_cr)
  178. X        {
  179. X            if(xmit_mode == 'p')
  180. X                Nap(20L);
  181. X            lputc('\r');
  182. X            xmit_len++;
  183. X        }
  184. X
  185. X        if(sigint)
  186. X            break;
  187. X
  188. X        switch(xmit_mode)
  189. X        {
  190. X            case 's':
  191. X                while(1)
  192. X                {
  193. X                    if(ttyrdchk())
  194. X                        break;
  195. X                    rchar = lgetc_timeout(5 * 1000L);
  196. X                    if(rchar < 0)
  197. X                        file_insert_clear_xoff();
  198. X                    else
  199. X                        process_xmtr_rcvd_char((char)rchar,1);
  200. X                    if(rchar == 0x0A)
  201. X                        break;
  202. X                }
  203. X                rchar = to_lower(ttygetc(1));
  204. X                if((rchar == 's') || (rchar == ESC))
  205. X                    goto INSERT_DONE;
  206. X                break;
  207. X
  208. X            case 'e':
  209. X                timeout_msecs = 5 * 1000L;
  210. X                while(1)
  211. X                {
  212. X                    if(sigint)
  213. X                        break;
  214. X                    rchar = lgetc_timeout(timeout_msecs);
  215. X                    if(rchar < 0)
  216. X                    {
  217. X                        if(!xmit_len)
  218. X                            break;
  219. X                        file_insert_clear_xoff();
  220. X                        timeout_msecs = 1 * 1000L;
  221. X                    }
  222. X                    else
  223. X                    {
  224. X                        process_xmtr_rcvd_char((char)rchar,1);
  225. X                        timeout_msecs = 100L;
  226. X                        if(xmit_len)
  227. X                            xmit_len--;
  228. X                    }
  229. X                    if(rchar == 0x0A)
  230. X                        break;
  231. X                }
  232. X                break;
  233. X
  234. X            case 'f':
  235. X            case 'p':
  236. X                while(rdchk(shm->Liofd))
  237. X                {
  238. X                    rchar = lgetc_xmtr();
  239. X                    process_xmtr_rcvd_char((char)rchar,1);
  240. X                }
  241. X                break;
  242. X        }
  243. X        if(sigint)
  244. X            break;
  245. X    }
  246. X
  247. XINSERT_DONE:
  248. X
  249. X    if(sigint)
  250. X    {
  251. X        sigint = 0;
  252. X        setcolor(colors_error);
  253. X        ff(se,"--> Interrupted\r\n");
  254. X        setcolor(colors_at_entry);
  255. X    }
  256. X
  257. XINSERT_DONE2:
  258. X
  259. X    fclose(fp);
  260. X
  261. X    ttymode(old_ttymode);        /* restore old console mode */
  262. X    sigint = 0;                /* reset SIGINT flag */
  263. X
  264. X    while(((rchar = lgetc_timeout(200L)) >= 0) && !sigint)
  265. X        process_xmtr_rcvd_char((char)rchar,1);
  266. X
  267. X    setcolor(colors_success);
  268. X    ff(se,"\r\n-->  done ... sent %ld lines, %ld characters\r\n",
  269. X                total_lines,total_chars);
  270. X    setcolor(colors_at_entry);
  271. X    lclear_xmtr_xoff();
  272. X#ifdef USE_XON_XOFF
  273. X    lxon_xoff(ixon | ixoff);    /* restore old line xon/xoff status */
  274. X#endif
  275. X    start_rcvr_process(1);
  276. X    return(0);
  277. X
  278. X}    /* end of file_insert_to_line */
  279. X
  280. X/* vi: set tabstop=4 shiftwidth=4: */
  281. X/* end of ecufinsert.c */
  282. SHAR_EOF
  283. echo 'File ecufinsert.c is complete' &&
  284. chmod 0644 ecufinsert.c ||
  285. echo 'restore of ecufinsert.c failed'
  286. Wc_c="`wc -c < 'ecufinsert.c'`"
  287. test 7262 -eq "$Wc_c" ||
  288.     echo 'ecufinsert.c: original size 7262, current size' "$Wc_c"
  289. rm -f _shar_wnt_.tmp
  290. fi
  291. # ============= ecufkey.c ==============
  292. if test -f 'ecufkey.c' -a X"$1" != X"-c"; then
  293.     echo 'x - skipping ecufkey.c (File already exists)'
  294.     rm -f _shar_wnt_.tmp
  295. else
  296. > _shar_wnt_.tmp
  297. echo 'x - extracting ecufkey.c (Text)'
  298. sed 's/^X//' << 'SHAR_EOF' > 'ecufkey.c' &&
  299. X/*+-----------------------------------------------------------------
  300. X    ecufkey.c -- function key definition
  301. X    wht@n4hgf.Mt-Park.GA.US
  302. X
  303. X  Defined functions:
  304. X    ffso(str)
  305. X    idke_to_xf(ikde)
  306. X    kde_fgets(buf,bufsize,fp)
  307. X    kde_name_to_ikde(keystr)
  308. X    kde_text(ikde)
  309. X    keyset_define_key(bufptr)
  310. X    keyset_display()
  311. X    keyset_idstr(ikde)
  312. X    keyset_init()
  313. X    keyset_read(name)
  314. X    xf_text(xf)
  315. X    xf_to_ikde(xf)
  316. X
  317. X------------------------------------------------------------------*/
  318. X/*+:EDITS:*/
  319. X/*:09-10-1992-13:58-wht@n4hgf-ECU release 3.20 */
  320. X/*:08-22-1992-15:38-wht@n4hgf-ECU release 3.20 BETA */
  321. X/*:04-17-1992-16:29-wht@n4hgf-initialize keyset to SCO "ANSI" send strings */
  322. X/*:09-01-1991-05:16-wht@n4hgf2-allow comments and whitespace after names */
  323. X/*:08-31-1991-13:21-wht@n4hgf2-look for keys file in ECULIBDIR */
  324. X/*:08-16-1991-00:11-wht@n4hgf-keyset_init loads default keyset if found */
  325. X/*:07-25-1991-12:55-wht@n4hgf-ECU release 3.10 */
  326. X/*:07-12-1991-13:57-wht@n4hgf-GCC140 fix update */
  327. X/*:05-21-1991-00:45-wht@n4hgf-added -3 error code to keyset_read */
  328. X/*:05-21-1991-00:37-wht@n4hgf-improve fkey load error detection */
  329. X/*:05-16-1991-15:05-wht@n4hgf-gcc binary exploded in keyset_display */
  330. X/*:08-14-1990-20:40-wht@n4hgf-ecu3.00-flush old edit history */
  331. X
  332. X#include "ecu.h"
  333. X#include "ecukey.h"
  334. X#include "ecufkey.h"
  335. X#include "ecuxkey.h"
  336. X#include "ecufork.h"
  337. X
  338. Xchar *str_token();
  339. X
  340. Xextern char kbdintr;    /* current input INTR */
  341. Xextern char curr_dir[CURR_DIRSIZ];    /* current working key defns */
  342. X
  343. XKDE keyset_table[KDE_COUNT];
  344. Xchar keyset_name[256] = "";
  345. X
  346. XKDEMAP kdemap[] = {
  347. X    { XFcurup,    IKDE_CUU,    "CUU",    "\033[A"    },
  348. X    { XFcurdn,    IKDE_CUD,    "CUD",    "\033[B"    },
  349. X    { XFcurrt,    IKDE_CUR,    "CUR",    "\033[C"    },
  350. X    { XFcurlf,    IKDE_CUL,    "CUL",    "\033[D"    },
  351. X    { XFcur5,    IKDE_CU5,    "CU5",    "\033[E"    },
  352. X    { XFend,    IKDE_END,    "End",    "\033[F"    },
  353. X    { XFpgdn,    IKDE_PGDN,    "PgDn",    "\033[G"    },
  354. X    { XFhome,    IKDE_HOME,    "Home",    "\033[H"    },
  355. X    { XFpgup,    IKDE_PGUP,    "PgUp",    "\033[I"    },
  356. X    { XFins,    IKDE_INS,    "Ins",    "\033[L"    },
  357. X    { XF1,        IKDE_F1,    "F1",    "\033[M"    },
  358. X    { XF2,        IKDE_F2,    "F2",    "\033[N"    },
  359. X    { XF3,        IKDE_F3,    "F3",    "\033[O"    },
  360. X    { XF4,        IKDE_F4,    "F4",    "\033[P"    },
  361. X    { XF5,        IKDE_F5,    "F5",    "\033[Q"    },
  362. X    { XF6,        IKDE_F6,    "F6",    "\033[R"    },
  363. X    { XF7,        IKDE_F7,    "F7",    "\033[S"    },
  364. X    { XF8,        IKDE_F8,    "F8",    "\033[T"    },
  365. X    { XF9,        IKDE_F9,    "F9",    "\033[U"    },
  366. X    { XF10,        IKDE_F10,    "F10",    "\033[V"    },
  367. X    { XF11,        IKDE_F11,    "F11",    "\033[W"    },
  368. X    { XF12,        IKDE_F12,    "F12",    "\033[X"    },
  369. X    { XFbktab,    IKDE_BKTAB,    "BkTab","\033[Z"    },
  370. X    { 255,        IKDE_InitStr,"IS",    ""            },
  371. X    { 0,0,"",""}
  372. X};
  373. X
  374. X/*+-------------------------------------------------------------------------
  375. X    keyset_init()
  376. X--------------------------------------------------------------------------*/
  377. Xvoid
  378. Xkeyset_init()
  379. X{
  380. X    register itmp;
  381. X    register KDE *tkde;
  382. X    register KDEMAP *kmap;
  383. X
  384. X    for(itmp = 0; itmp < KDE_COUNT; itmp++)
  385. X    {
  386. X        tkde = &keyset_table[itmp];
  387. X        tkde->logical[0] = 0;
  388. X        tkde->ikde = (uchar)itmp;
  389. X    }
  390. X
  391. X    kmap = kdemap;
  392. X    while(kmap->xf)
  393. X    {
  394. X        if(kmap->ikde <= IKDE_lastKey)
  395. X        {
  396. X            tkde = &keyset_table[kmap->ikde];
  397. X            sprintf(tkde->logical,"SCO %s",kmap->name);
  398. X            strcpy(tkde->str,kmap->init);
  399. X            tkde->count  = strlen(tkde->str);
  400. X        }
  401. X        kmap++;
  402. X    }
  403. X
  404. X    keyset_name[0] = 0;
  405. X
  406. X    tkde = &keyset_table[IKDE_BKTAB];
  407. X    strcpy(tkde->logical,"redisplay");
  408. X    tkde->count = KACT_REDISPLAY;
  409. X
  410. X    tkde = &keyset_table[IKDE_HOME];
  411. X    strcpy(tkde->logical,"ecu cmd");
  412. X    tkde->count = KACT_COMMAND;
  413. X
  414. X    tkde = &keyset_table[IKDE_INS];
  415. X    strcpy(tkde->logical,"local shell");
  416. X    tkde->count = KACT_LOCAL_SHELL;
  417. X
  418. X    tkde = &keyset_table[IKDE_CU5];
  419. X    strcpy(tkde->logical,"screen dump");
  420. X    tkde->str[0] = 0x7F;    /* this key is intercepted by kbd read routine */
  421. X    tkde->count = 0;
  422. X
  423. X}    /* end of keyset_init */
  424. X
  425. X/*+-------------------------------------------------------------------------
  426. X    kde_fgets(buf,bufsize,fp) - read and evaluate key file line
  427. X
  428. XReturns:
  429. X    KDETYPE_COMMENT     comment or blank line (null, all blank or "#"
  430. X                        as non-blank)
  431. X    KDETYPE_NAME        "name" (non "#\t " in column 1)
  432. X    KDETYPE_ENTRY       "entry" ("\t " in column 1)
  433. X    KDETYPE_EOF         end of file
  434. X--------------------------------------------------------------------------*/
  435. Xint
  436. Xkde_fgets(buf,bufsize,fp)
  437. Xchar *buf;
  438. Xint bufsize;
  439. XFILE *fp;
  440. X{
  441. X    register itmp;
  442. X    register char *cptr;
  443. X
  444. X    if(!fgets(buf,bufsize,fp))
  445. X    {
  446. X        return(KDETYPE_EOF);
  447. X    }
  448. X
  449. X    if(!(itmp = strlen(buf)))
  450. X        return(KDETYPE_COMMENT);
  451. X    if(buf[itmp - 1] == NL)
  452. X    {
  453. X        buf[itmp - 1] = 0;
  454. X        itmp--;
  455. X    }
  456. X    if(!itmp)
  457. X        return(KDETYPE_COMMENT);
  458. X
  459. X    cptr = buf;
  460. X    itmp = (strchr(" \t",*cptr)) ? KDETYPE_ENTRY : KDETYPE_NAME;
  461. X    while(*cptr && ((*cptr == SPACE) || (*cptr == TAB)))
  462. X        cptr++;
  463. X
  464. X    if(!*cptr || (*cptr == '#'))
  465. X        return(KDETYPE_COMMENT);
  466. X
  467. X    return(itmp);
  468. X    
  469. X}    /* end of kde_fgets */
  470. X
  471. X/*+-------------------------------------------------------------------------
  472. X    kde_name_to_ikde(keystr)
  473. X--------------------------------------------------------------------------*/
  474. Xint
  475. Xkde_name_to_ikde(keystr)
  476. Xchar *keystr;
  477. X{
  478. X    KDEMAP *kmap = kdemap;
  479. X
  480. X    while(kmap->xf != 0)
  481. X    {
  482. X        if(!strcmpi(kmap->name,keystr))
  483. X            return((int)kmap->ikde);
  484. X        kmap++;
  485. X    }
  486. X    return(-1);
  487. X}    /* end of kde_name_to_ikde */
  488. X
  489. X/*+-------------------------------------------------------------------------
  490. X    keyset_idstr(ikde)
  491. X--------------------------------------------------------------------------*/
  492. Xchar *
  493. Xkeyset_idstr(ikde)
  494. Xint ikde;
  495. X{
  496. X    KDEMAP *kmap = kdemap;
  497. X
  498. X    while(kmap->xf)
  499. X    {
  500. X        if((int)kmap->ikde == ikde)
  501. X            return(kmap->name);
  502. X        kmap++;
  503. X    }
  504. X    return((char *)0);
  505. X}    /* end of keyset_idstr */
  506. X
  507. X/*+-------------------------------------------------------------------------
  508. X    xf_to_ikde(xf)
  509. X--------------------------------------------------------------------------*/
  510. Xint
  511. Xxf_to_ikde(xf)
  512. Xuchar xf;
  513. X{
  514. X    KDEMAP *kmap = kdemap;
  515. X
  516. X    while(kmap->xf)
  517. X    {
  518. X        if(kmap->xf == xf)
  519. X            return((int)kmap->ikde & 0xFF);
  520. X        kmap++;
  521. X    }
  522. X    return(-1);
  523. X}    /* end of xf_to_ikde */
  524. X
  525. X/*+-------------------------------------------------------------------------
  526. X    ikde_to_xf(ikde)
  527. X--------------------------------------------------------------------------*/
  528. Xint
  529. Xikde_to_xf(ikde)
  530. Xuchar ikde;
  531. X{
  532. X    KDEMAP *kmap = kdemap;
  533. X
  534. X    while(kmap->xf)
  535. X    {
  536. X        if(kmap->ikde == ikde)
  537. X            return((int)kmap->xf & 0xFF);
  538. X        kmap++;
  539. X    }
  540. X    return(-1);
  541. X}    /* end of ikde_to_xf */
  542. X
  543. X/*+-------------------------------------------------------------------------
  544. X    kde_text(ikde) - ikde value to text
  545. X--------------------------------------------------------------------------*/
  546. Xchar *
  547. Xkde_text(ikde)
  548. Xint ikde;
  549. X{
  550. X    KDEMAP *kmap = kdemap;
  551. X
  552. X    while(kmap->xf)
  553. X    {
  554. X        if(kmap->ikde == (char)ikde)
  555. X            return(kmap->name);
  556. X        kmap++;
  557. X    }
  558. X    return("??");
  559. X}    /* end of xf_to_ikde */
  560. X
  561. X/*+-------------------------------------------------------------------------
  562. X    xf_text(xf) - XFkey to text
  563. X--------------------------------------------------------------------------*/
  564. Xchar *
  565. Xxf_text(xf)
  566. Xuchar xf;
  567. X{
  568. X    static char sc8[8];
  569. X
  570. X    switch(xf)
  571. X    {
  572. X        case XFcurup:    return("CUU");
  573. X        case XFcurdn:    return("CUD");
  574. X        case XFcurrt:    return("CUR");
  575. X        case XFcurlf:    return("CUL");
  576. X        case XFcur5:    return("CU5");
  577. X        case XFend:        return("End");
  578. X        case XFpgdn:    return("PgDn");
  579. X        case XFhome:    return("Home");
  580. X        case XFpgup:    return("PgUp");
  581. X        case XFins:        return("Ins");
  582. X        case XF1:        return("F1");
  583. X        case XF2:        return("F2");
  584. X        case XF3:        return("F3");
  585. X        case XF4:        return("F4");
  586. X        case XF5:        return("F5");
  587. X        case XF6:        return("F6");
  588. X        case XF7:        return("F7");
  589. X        case XF8:        return("F8");
  590. X        case XF9:        return("F9");
  591. X        case XF10:        return("F10");
  592. X        case XF11:        return("F11");
  593. X        case XF12:        return("F12");
  594. X        case XFbktab:    return("BkTab");
  595. X    }
  596. X
  597. X    if((xf >= XF_ALTA) && (xf <= XF_ALTZ))
  598. X    {
  599. X        sprintf(sc8,"Alt-%c",'a' + xf - XF_ALTA);
  600. X        return(sc8);
  601. X    }
  602. X    sprintf(sc8,"XF_%02x\n",xf);
  603. X    return(sc8);
  604. X}    /* end of xf_text */
  605. X
  606. X/*+-------------------------------------------------------------------------
  607. X    keyset_define_key(bufptr)
  608. X
  609. Xreturn 0 if no error, -1 if error
  610. X--------------------------------------------------------------------------*/
  611. Xint
  612. Xkeyset_define_key(bufptr)
  613. Xchar *bufptr;
  614. X{
  615. X    register itmp;
  616. X    register token_number;
  617. X    register KDE *tkde = (KDE *)0;
  618. X    int ikde = 0;
  619. X    char token_separator[8];
  620. X    char *token;
  621. X    char *syntax = "syntax error in key definition: %s\n";
  622. X
  623. X    if((itmp = strlen(bufptr)) && (bufptr[itmp - 1] == NL))
  624. X        bufptr[--itmp] = 0;        /* strip trailing NL */
  625. X    if(!itmp)
  626. X        return(0);
  627. X
  628. X    if((*bufptr != SPACE) && (*bufptr != TAB))    /* if no leading space */
  629. X        return(0);
  630. X
  631. X    while((*bufptr == SPACE) || (*bufptr == TAB))    /* strip lding sp/tab */
  632. X        bufptr++;
  633. X
  634. X    token_number = 0;
  635. X    strcpy(token_separator,":");
  636. X    while(token = str_token(bufptr,token_separator))
  637. X    {
  638. X        bufptr = (char *)0;    /* further calls to str_token need NULL */
  639. X        switch(token_number)
  640. X        {
  641. X            case 0:        /* first field is key identifier */
  642. X                if((ikde = kde_name_to_ikde(token)) < 0)
  643. X                {
  644. X                    pprintf(syntax,keyset_name);
  645. X                    pprintf("  %s is not a legal key identifier\n",token);
  646. X                    return(-1);
  647. X                }
  648. X                if(ikde == IKDE_HOME)
  649. X                {
  650. X                    pprintf(syntax,keyset_name);
  651. X                    pprintf("  HOME cannot be redefined!\n");
  652. X                    return(-1);
  653. X                }
  654. X                if(ikde == IKDE_CU5)
  655. X                {
  656. X                    pprintf(syntax,keyset_name);
  657. X                    pprintf("  CUR5 cannot be redefined!\n");
  658. X                    return(-1);
  659. X                }
  660. X                if(ikde == IKDE_BKTAB)
  661. X                {
  662. X                    pprintf(syntax,keyset_name);
  663. X                    pprintf("  BkTab cannot be redefined!\n");
  664. X                    return(-1);
  665. X                }
  666. X                tkde = &keyset_table[ikde];
  667. X                tkde->logical[0] = 0;
  668. X                tkde->count = 0;
  669. X                break;
  670. X
  671. X            case 1:        /* second field is logical key name */
  672. X                strncpy(tkde->logical,token,sizeof(tkde->logical));
  673. X                tkde->logical[sizeof(tkde->logical) - 1] = 0;
  674. X                strcpy(token_separator," \t"); /* whitespace is tok sep now */
  675. X                break;
  676. X
  677. X            default:    /* third and subsequent to define key */
  678. X                if(!strlen(token))
  679. X                    continue;
  680. X                if(tkde->count == sizeof(tkde->str))
  681. X                {
  682. X                    pprintf(syntax,keyset_name);
  683. X                    pprintf("  %s: output count too long",
  684. X                        keyset_idstr(ikde));
  685. X                    return(-1);
  686. X                }
  687. X                if((itmp = ascii_to_hex(token)) < 0)
  688. X                {
  689. X                    pprintf(syntax,keyset_name);
  690. X                    pprintf("  %s: '%s' invalid code\n",
  691. X                        keyset_idstr(ikde),token);
  692. X                    return(0);
  693. X                }
  694. X                tkde->str[tkde->count] = itmp;
  695. X                tkde->count++;
  696. X                break;
  697. X        }    /* end of switch(token_number) */
  698. X        token_number++;
  699. X    }        /* end while not end of record */
  700. X
  701. X    return(0);
  702. X}    /* end of keyset_define_key */
  703. X
  704. X/*+-------------------------------------------------------------------------
  705. X    keyset_read(name)
  706. Xreturns 0 on success, -1 if no .ecu/keys, -2 if no 'name', -3 if error
  707. X--------------------------------------------------------------------------*/
  708. Xint
  709. Xkeyset_read(name)
  710. Xchar *name;
  711. X{
  712. X    int itmp;
  713. X    int ikde;
  714. X    char ecukeys_name[128];
  715. X    char s128[128];
  716. X    FILE *fp_keys;
  717. X
  718. X    get_home_dir(ecukeys_name);
  719. X    strcat(ecukeys_name,"/.ecu/keys");    /* someone may core dump here one day */
  720. X
  721. X    if(!(fp_keys = fopen(ecukeys_name,"r")))
  722. X    {
  723. X        strcpy(ecukeys_name,eculibdir);
  724. X        strcat(ecukeys_name,"/keys");
  725. X        if(!(fp_keys = fopen(ecukeys_name,"r")))
  726. X            return(-1);
  727. X    }
  728. X
  729. X/* find keyset name */
  730. X    itmp = 0;
  731. X    while((ikde = kde_fgets(s128,sizeof(s128),fp_keys)) != KDETYPE_EOF)
  732. X    {
  733. X        if((ikde == KDETYPE_NAME) && !strcmp(s128,name))
  734. X        {
  735. X            itmp = 1; /* success */
  736. X            break;
  737. X        }
  738. X    }
  739. X    if(!itmp)                /* find match? */
  740. X    {
  741. X        fclose(fp_keys);    /* nope */
  742. X        return(-2);
  743. X    }
  744. X
  745. X/*
  746. X * read past any other keyset names matching this set
  747. X * process 1st line of definition when found
  748. X */
  749. X    while((ikde = kde_fgets(s128,sizeof(s128),fp_keys)) != KDETYPE_EOF)
  750. X    {
  751. X        if((ikde == KDETYPE_NAME) || (ikde == KDETYPE_COMMENT))
  752. X            continue;
  753. X        else if(ikde == KDETYPE_ENTRY)
  754. X        {
  755. X            if(keyset_define_key(s128) < 0)
  756. X            {
  757. X                fclose(fp_keys);
  758. X                keyset_init();
  759. X                return(-3);
  760. X            }
  761. X            break;
  762. X        }
  763. X    }
  764. X
  765. X/*
  766. X * read rest of definition
  767. X */
  768. X    while((ikde = kde_fgets(s128,sizeof(s128),fp_keys)) != KDETYPE_EOF)
  769. X    {
  770. X        switch(ikde)
  771. X        {
  772. X            case KDETYPE_COMMENT:
  773. X                continue;
  774. X            case KDETYPE_ENTRY:
  775. X                if(keyset_define_key(s128) < 0)
  776. X                {
  777. X                    fclose(fp_keys);
  778. X                    keyset_init();
  779. X                    return(-3);
  780. X                }
  781. X                break;
  782. X            default:
  783. X                goto DONE;
  784. X        }
  785. X    }
  786. X
  787. XDONE:
  788. X    strncpy(keyset_name,name,sizeof(keyset_name));
  789. X    keyset_name[sizeof(keyset_name) - 1] = 0;
  790. X    fclose(fp_keys);
  791. X    return(0);
  792. X}    /* end of keyset_read */
  793. X
  794. X/*+-------------------------------------------------------------------------
  795. X    ffso(str)
  796. X--------------------------------------------------------------------------*/
  797. Xvoid
  798. Xffso(str)
  799. Xchar *str;
  800. X{
  801. X    tcap_stand_out();
  802. X    fputs(str,se);
  803. X    tcap_stand_end();
  804. X}    /* end of ffso */
  805. X
  806. X/*+-------------------------------------------------------------------------
  807. X    keyset_display()
  808. X
  809. X F1  xxxxx  F2   xxxxx   HOME xxxxx  PGUP xxxxx
  810. X F3  xxxxx  F4   xxxxx   END  xxxxx  PGDN xxxxx
  811. X F5  xxxxx  F6   xxxxx   INS  xxxxx  CUR5 xxxxx
  812. X F7  xxxxx  F8   xxxxx   BkTab xxxxx
  813. X F9  xxxxx  F10  xxxxx   CUR^ xxxxx  CUR> xxxxx
  814. X F11 xxxxx  F12  xxxxx   CUR< xxxxx  CURv xxxxx
  815. X--------------------------------------------------------------------------*/
  816. Xvoid
  817. Xkeyset_display()
  818. X{
  819. X    int itmp;
  820. X    int itmp2;
  821. X    int clen1 = 0;
  822. X    char cfmt1[32];
  823. X    int clen2 = 0;
  824. X    char cfmt2[32];
  825. X    int clen3 = 0;
  826. X    char cfmt3[32];
  827. X    char cfmt4[32];
  828. X    KDE *tkde;
  829. X
  830. X    if(!keyset_name[0])
  831. X        keyset_init();
  832. X
  833. X    for(itmp = 0; itmp < KDE_COUNT; itmp++)
  834. X    {
  835. X        tkde = &keyset_table[itmp];
  836. X        itmp2 = strlen(tkde->logical);
  837. X#if defined(__GNUC__) && !defined(GCC140)
  838. X        /*
  839. X         * do absolutely nothing except defeat optimization
  840. X         * see top of source; function is in ecuutil.c
  841. X         * GCC 1.40 fixed the bug
  842. X         */
  843. X        defeat_optimize_to_work_around_bug(&itmp);
  844. X#endif /* __GNUC__ */
  845. X        switch(itmp)
  846. X        {
  847. X            case IKDE_F1: case IKDE_F3: case IKDE_F5: case IKDE_F7:
  848. X            case IKDE_F9: case IKDE_F11:
  849. X                if(clen1 < itmp2)
  850. X                    clen1 = itmp2;
  851. X                break;
  852. X
  853. X            case IKDE_F2: case IKDE_F4: case IKDE_F6: case IKDE_F8:
  854. X            case IKDE_F10: case IKDE_F12:
  855. X                if(clen2 < itmp2)
  856. X                    clen2 = itmp2;
  857. X                break;
  858. X
  859. X            case IKDE_HOME: case IKDE_END: case IKDE_INS:
  860. X            case IKDE_CUU: case IKDE_CUL:
  861. X                if(clen3 < itmp2)
  862. X                    clen3 = itmp2;
  863. X                break;
  864. X
  865. X            case IKDE_InitStr:    /* initialization string excluded */
  866. X                break;
  867. X        }
  868. X    }
  869. X    sprintf(cfmt1," %%-%d.%ds",clen1,clen1);
  870. X    sprintf(cfmt2," %%-%d.%ds",clen2,clen2);
  871. X    sprintf(cfmt3," %%-%d.%ds",clen3,clen3);
  872. X    strcpy(cfmt4," %s");
  873. X    ff(se,"   key definition: %s\r\n\r\n",keyset_name);
  874. X
  875. X    ffso(" F1  ");ff(se,cfmt1,keyset_table[IKDE_F1].logical);
  876. X    fputs("  ",se);
  877. X    ffso(" F2  ");ff(se,cfmt2,keyset_table[IKDE_F2].logical);
  878. X    fputs("  ",se);
  879. X    ffso(" Home ");ff(se,cfmt3,keyset_table[IKDE_HOME].logical);
  880. X    fputs("  ",se);
  881. X    ffso(" PgUp ");ff(se,cfmt4,keyset_table[IKDE_PGUP].logical);
  882. X    fputs("\r\n",se);
  883. X
  884. X    ffso(" F3  ");ff(se,cfmt1,keyset_table[IKDE_F3].logical);
  885. X    fputs("  ",se);
  886. X    ffso(" F4  ");ff(se,cfmt2,keyset_table[IKDE_F4].logical);
  887. X    fputs("  ",se);
  888. X    ffso(" End  ");ff(se,cfmt3,keyset_table[IKDE_END].logical);
  889. X    fputs("  ",se);
  890. X    ffso(" PgDn ");ff(se,cfmt4,keyset_table[IKDE_PGDN].logical);
  891. X    fputs("\r\n",se);
  892. X
  893. X    ffso(" F5  ");ff(se,cfmt1,keyset_table[IKDE_F5].logical);
  894. X    fputs("  ",se);
  895. X    ffso(" F6  ");ff(se,cfmt2,keyset_table[IKDE_F6].logical);
  896. X    fputs("  ",se);
  897. X    ffso(" Ins  ");ff(se,cfmt3,keyset_table[IKDE_INS].logical);
  898. X    fputs("  ",se);
  899. X    ffso(" CUR5 ");ff(se,cfmt4,keyset_table[IKDE_CU5].logical);
  900. X    fputs("\r\n",se);
  901. X
  902. X    ffso(" F7  ");ff(se,cfmt1,keyset_table[IKDE_F7].logical);
  903. X    fputs("  ",se);
  904. X    ffso(" F8  ");ff(se,cfmt2,keyset_table[IKDE_F8].logical);
  905. X    fputs("  ",se);
  906. X    ffso(" BkTab");ff(se,cfmt3,keyset_table[IKDE_BKTAB].logical);
  907. X    fputs("\r\n",se);
  908. X
  909. X    ffso(" F9  ");ff(se,cfmt1,keyset_table[IKDE_F9].logical);
  910. X    fputs("  ",se);
  911. X    ffso(" F10 ");ff(se,cfmt2,keyset_table[IKDE_F10].logical);
  912. X    fputs("  ",se);
  913. X    ffso(" CUR^ ");ff(se,cfmt3,keyset_table[IKDE_CUU].logical);
  914. X    fputs("  ",se);
  915. X    ffso(" CUR> ");ff(se,cfmt4,keyset_table[IKDE_CUR].logical);
  916. X    fputs("\r\n",se);
  917. X
  918. X    ffso(" F11 ");ff(se,cfmt1,keyset_table[IKDE_F11].logical);
  919. X    fputs("  ",se);
  920. X    ffso(" F12 ");ff(se,cfmt2,keyset_table[IKDE_F12].logical);
  921. X    fputs("  ",se);
  922. X    ffso(" CUR< ");ff(se,cfmt3,keyset_table[IKDE_CUL].logical);
  923. X    fputs("  ",se);
  924. X    ffso(" CURv ");ff(se,cfmt4,keyset_table[IKDE_CUD].logical);
  925. X    fputs("\r\n\r\n",se);
  926. X
  927. X}    /* end of keyset_display */
  928. X
  929. X/* end of ecufkey.c */
  930. X/* vi: set tabstop=4 shiftwidth=4: */
  931. SHAR_EOF
  932. chmod 0644 ecufkey.c ||
  933. echo 'restore of ecufkey.c failed'
  934. Wc_c="`wc -c < 'ecufkey.c'`"
  935. test 15916 -eq "$Wc_c" ||
  936.     echo 'ecufkey.c: original size 15916, current size' "$Wc_c"
  937. rm -f _shar_wnt_.tmp
  938. fi
  939. # ============= ecufkey.h ==============
  940. if test -f 'ecufkey.h' -a X"$1" != X"-c"; then
  941.     echo 'x - skipping ecufkey.h (File already exists)'
  942.     rm -f _shar_wnt_.tmp
  943. else
  944. > _shar_wnt_.tmp
  945. echo 'x - extracting ecufkey.h (Text)'
  946. sed 's/^X//' << 'SHAR_EOF' > 'ecufkey.h' &&
  947. X/*+-------------------------------------------------------------------------
  948. X    ecufkey.h -- AT XENIX/UNIX function key phrases
  949. X    wht@n4hgf.Mt-Park.GA.US
  950. X--------------------------------------------------------------------------*/
  951. X/*+:EDITS:*/
  952. X/*:09-10-1992-13:58-wht@n4hgf-ECU release 3.20 */
  953. X/*:08-22-1992-15:38-wht@n4hgf-ECU release 3.20 BETA */
  954. X/*:03-27-1992-16:21-wht@n4hgf-re-include protection for all .h files */
  955. X/*:07-25-1991-12:55-wht@n4hgf-ECU release 3.10 */
  956. X/*:08-14-1990-20:40-wht@n4hgf-ecu3.00-flush old edit history */
  957. X
  958. X#ifndef _ecufkey_h
  959. X#define _ecufkey_h
  960. X
  961. X/*
  962. X * indices to key mapping tables
  963. X *
  964. X * these are close to being magic numbers - don't change w/o looking
  965. X * at IKDE_to_XF in ecutty.c
  966. X */
  967. Xenum ikde_enum {
  968. X    IKDE_HOME,
  969. X    IKDE_END,
  970. X    IKDE_PGUP,
  971. X    IKDE_PGDN,
  972. X    IKDE_F1,
  973. X    IKDE_F2,
  974. X    IKDE_F3,
  975. X    IKDE_F4,
  976. X    IKDE_F5,
  977. X    IKDE_F6,
  978. X    IKDE_F7,
  979. X    IKDE_F8,
  980. X    IKDE_F9,
  981. X    IKDE_F10,
  982. X    IKDE_F11,
  983. X    IKDE_F12,
  984. X    IKDE_CUU,
  985. X    IKDE_CUD,
  986. X    IKDE_CUR,
  987. X    IKDE_CUL,
  988. X    IKDE_CU5,
  989. X    IKDE_INS,
  990. X    IKDE_BKTAB
  991. X};
  992. X#define IKDE_lastKey    IKDE_BKTAB
  993. X#define IKDE_InitStr    (IKDE_BKTAB + 1)    /* initialization string kludge */
  994. X#define KDE_COUNT        (IKDE_BKTAB + 2)
  995. X
  996. X#define KDE_LOGICAL_MAX        12    /* max length of keystroke sequence */
  997. X#define KDE_OUTSTR_MAX        32    /* max length of output sequence */
  998. X
  999. X/*
  1000. X * KDE input line types
  1001. X*/
  1002. X#define KDETYPE_NAME        1
  1003. X#define KDETYPE_ENTRY        2
  1004. X#define KDETYPE_COMMENT        3
  1005. X#define KDETYPE_EOF            4
  1006. X
  1007. Xtypedef struct kde
  1008. X{
  1009. X    int count;
  1010. X    uchar ikde;
  1011. X    char logical[KDE_LOGICAL_MAX];
  1012. X    char str[KDE_OUTSTR_MAX];
  1013. X}    KDE;
  1014. X
  1015. X/* when a count is not a count but an action: */
  1016. X#define KACT_COMMAND            -1
  1017. X#define KACT_LOCAL_SHELL        -2
  1018. X#define KACT_REDISPLAY            -3
  1019. X
  1020. Xtypedef struct kdemap
  1021. X{
  1022. X    uchar xf;            /* extended function code (0x80+ from ttygetc()) */
  1023. X    short ikde;            /* index into keyset */
  1024. X    char *name;            /* ECU "formal" name for key */
  1025. X    char *init;            /* key sends this string to port by default */
  1026. X}    KDEMAP;
  1027. X
  1028. Xchar *keyset_idstr();
  1029. X
  1030. X#endif /* _ecufkey_h */
  1031. X
  1032. X/* vi: set tabstop=4 shiftwidth=4: */
  1033. X/* end of ecufkey.h */
  1034. SHAR_EOF
  1035. chmod 0644 ecufkey.h ||
  1036. echo 'restore of ecufkey.h failed'
  1037. Wc_c="`wc -c < 'ecufkey.h'`"
  1038. test 1988 -eq "$Wc_c" ||
  1039.     echo 'ecufkey.h: original size 1988, current size' "$Wc_c"
  1040. rm -f _shar_wnt_.tmp
  1041. fi
  1042. # ============= ecufork.c ==============
  1043. if test -f 'ecufork.c' -a X"$1" != X"-c"; then
  1044.     echo 'x - skipping ecufork.c (File already exists)'
  1045.     rm -f _shar_wnt_.tmp
  1046. else
  1047. > _shar_wnt_.tmp
  1048. echo 'x - extracting ecufork.c (Text)'
  1049. sed 's/^X//' << 'SHAR_EOF' > 'ecufork.c' &&
  1050. X/*+-------------------------------------------------------------------------
  1051. X    ecufork.c -- ecu spawning ground
  1052. X    wht@n4hgf.Mt-Park.GA.US
  1053. X
  1054. X  Defined functions:
  1055. X    exec_cmd(cmdstr)
  1056. X    expand_wildcard_list(wild,expcmd)
  1057. X    find_executable(progname)
  1058. X    is_executable(progname)
  1059. X    shell(shellcmd)
  1060. X    smart_fork()
  1061. X
  1062. X--------------------------------------------------------------------------*/
  1063. X/*+:EDITS:*/
  1064. X/*:09-10-1992-13:58-wht@n4hgf-ECU release 3.20 */
  1065. X/*:08-22-1992-15:38-wht@n4hgf-ECU release 3.20 BETA */
  1066. X/*:04-29-1992-13:29-wht@n4hgf-ignore SIGQUIT when in executing a child */
  1067. X/*:09-25-1991-18:02-wht@n4hgf2-find_executable flunks directories now */
  1068. X/*:09-06-1991-04:20-wht@n4hgf2-expand_wildcard_list minor bug */
  1069. X/*:08-29-1991-01:56-wht@n4hgf2-use max esd size instead of 5120 */
  1070. X/*:07-25-1991-12:55-wht@n4hgf-ECU release 3.10 */
  1071. X/*:07-17-1991-07:04-wht@n4hgf-avoid SCO UNIX nap bug */
  1072. X/*:09-19-1990-19:36-wht@n4hgf-ecu_log_event now gets pid for log from caller */
  1073. X/*:08-14-1990-20:40-wht@n4hgf-ecu3.00-flush old edit history */
  1074. X
  1075. X#include "ecu.h"
  1076. X#include "esd.h"
  1077. X#include "ecufork.h"
  1078. X
  1079. Xextern int last_child_wait_status;
  1080. Xextern int last_child_wait_pid;
  1081. X
  1082. X#ifdef M_I286
  1083. X#define MAX_EXEC_ARG 512
  1084. X#else
  1085. X#if defined(M_UNIX) || defined(ISC)
  1086. X#define MAX_EXEC_ARG 1024
  1087. X#else
  1088. X#define MAX_EXEC_ARG 2048
  1089. X#endif    /* M_UNIX || ISC */
  1090. X#endif    /* M_I286 */
  1091. X
  1092. X/*+-------------------------------------------------------------------------
  1093. X    smart_fork()
  1094. X--------------------------------------------------------------------------*/
  1095. Xint
  1096. Xsmart_fork()
  1097. X{
  1098. X    register int count = 5;
  1099. X    register int pid;
  1100. X
  1101. X    while(count--)
  1102. X    {
  1103. X        if((pid = fork()) >= 0)
  1104. X            return(pid);
  1105. X        if(count)
  1106. X            Nap(40L);
  1107. X    }
  1108. X    return(-1);
  1109. X}    /* end of smart_fork */
  1110. X
  1111. X/*+-----------------------------------------------------------------------
  1112. X    shell(shellcmd)
  1113. X
  1114. X  param 'shellcmd' is a shell command prefixed with either
  1115. X  a '!', '$', '>' character.
  1116. X
  1117. X  '!' causes the command to run as a normal subshell of a process.
  1118. X  '$' causes the communications line to be stdin and stdout
  1119. X      for the spawned shell
  1120. X  '>' causes spawned shell to receive exactly sames files as ecu
  1121. X------------------------------------------------------------------------*/
  1122. Xvoid
  1123. Xshell(shellcmd)
  1124. Xchar *shellcmd;
  1125. X{
  1126. X    register shellpid;
  1127. X    register itmp;
  1128. X    register char *cptr;
  1129. X#if defined(FORK_DEBUG)
  1130. X    char s40[40];
  1131. X#endif
  1132. X    int wait_status;
  1133. X    int restart_rcvr = need_rcvr_restart();
  1134. X    char *getenv();
  1135. X
  1136. X    kill_rcvr_process(SIGUSR1);        /* stop receiver process gracefully */
  1137. X
  1138. X    signal(SIGINT,SIG_IGN);
  1139. X    signal(SIGQUIT,SIG_IGN);
  1140. X    signal(SIGUSR1,SIG_IGN);
  1141. X    signal(SIGUSR2,SIG_IGN);
  1142. X    signal(SIGCLD,SIG_DFL);
  1143. X
  1144. X    if((shellpid = smart_fork()) < 0)
  1145. X    {
  1146. X        ff(se,"Cannot fork\r\n");
  1147. X        if(restart_rcvr)
  1148. X            start_rcvr_process(1);
  1149. X        xmtr_signals();
  1150. X        return;
  1151. X    }
  1152. X
  1153. X    ttymode(0);                   /* set canonical tty mode */
  1154. X    if(shellpid == 0)            /* we are the spawned (going to call shell) */
  1155. X    {
  1156. X        if(*shellcmd != '>')    /* '>' prefix means leave fd's alone! */
  1157. X        {
  1158. X            /* Hook-up our "standard output" to either the tty or
  1159. X             * the line as appropriate for '!' or '$' */
  1160. X            close(TTYOUT);
  1161. X            fcntl(((*shellcmd == '$') ? shm->Liofd : TTYERR),F_DUPFD,TTYOUT);
  1162. X            if(*shellcmd == '$')
  1163. X            {
  1164. X                close(TTYIN);
  1165. X                fcntl(shm->Liofd,F_DUPFD,TTYIN);
  1166. X            }
  1167. X            close(shm->Liofd);
  1168. X        }
  1169. X
  1170. X        child_signals();        /* signals for child */
  1171. X
  1172. X        if(*shellcmd == '!')
  1173. X        {
  1174. X            cptr = getenv("SHELL");
  1175. X            if(cptr == (char *)0)
  1176. X                cptr = "/bin/csh";
  1177. X        }
  1178. X        else
  1179. X            cptr = "/bin/sh";
  1180. X
  1181. X        shellcmd++;
  1182. X        child_signals();
  1183. X        if(ulindex(cptr,"csh") > -1)
  1184. X        {
  1185. X            if(*shellcmd == '\0')
  1186. X                execl(cptr,"csh",(char *)0);
  1187. X            else
  1188. X                execl(cptr,"csh","-c",shellcmd,(char *)0);
  1189. X        }
  1190. X        else
  1191. X        {
  1192. X            if(*shellcmd == '\0')
  1193. X                execl(cptr,"sh",(char *)0);
  1194. X            else
  1195. X                execl(cptr,"sh","-c",shellcmd,(char *)0);
  1196. X        }
  1197. X
  1198. X        ff(se,"cannot execute %s\r\n",cptr);    /* should not get here */
  1199. X        _exit(255);                                /* end of spawned process */
  1200. X    }    /* end of if child process */
  1201. X
  1202. X#if defined(FORK_DEBUG)
  1203. X    sprintf(s40,"DEBUG fork shell pid %d",shellpid);
  1204. X    ecu_log_event(getpid(),s40); /* shell */
  1205. X#endif
  1206. X
  1207. X    while(((itmp = wait(&wait_status)) != shellpid) && (itmp != -1))
  1208. X        ;
  1209. X    last_child_wait_status = wait_status;
  1210. X    last_child_wait_pid = shellpid;
  1211. X
  1212. X    xmtr_signals();            /* restore standard xmtr signals */
  1213. X    ttymode(1);                /* control tty back to raw mode */
  1214. X
  1215. X/* any comm program will probably doodle with the line characteristics. */
  1216. X/* we want to make sure they are restored to normal */
  1217. X    lreset_ksr();            /* restore comm line params */
  1218. X
  1219. X    if(restart_rcvr)
  1220. X        start_rcvr_process(1);
  1221. X
  1222. X}    /* end of shell */
  1223. X
  1224. X/*+-------------------------------------------------------------------------
  1225. X    is_executable(progname)
  1226. X--------------------------------------------------------------------------*/
  1227. Xis_executable(progname)
  1228. Xchar *progname;
  1229. X{
  1230. X    struct stat ss;
  1231. X
  1232. X    if(stat(progname,&ss) < 0)            /* if cannot stat, flunk */
  1233. X        return(0);
  1234. X    if((ss.st_mode & 0111) == 0)        /* if no --x--x--x, flunk */
  1235. X        return(0);
  1236. X    if((ss.st_mode & S_IFMT) != S_IFREG)/* if no --x--x--x, flunk */
  1237. X        return(0);
  1238. X    return(1);    /* whew, this OUGHT to work */
  1239. X
  1240. X}    /* end of is_executable */
  1241. X
  1242. X/*+-------------------------------------------------------------------------
  1243. X    find_executable(progname)
  1244. XPATH=':/usr/wht/bin:/bin:/usr/bin:/usr/wht/bin:/etc/tuckerware' len=56
  1245. X--------------------------------------------------------------------------*/
  1246. Xchar *
  1247. Xfind_executable(progname)
  1248. Xchar *progname;
  1249. X{
  1250. X    register itmp;
  1251. X    static char *path_buf = (char *)0;
  1252. X#define PATHNAME_QUAN 32
  1253. X    static char *path_name[PATHNAME_QUAN + 1];
  1254. X    static char rtn_path[256];
  1255. X    static int path_count = 0;
  1256. X    char *cptr;
  1257. X    char *getenv();
  1258. X
  1259. X    if(path_buf == (char *)0)
  1260. X    {
  1261. X        if((cptr = getenv("PATH")) == (char *)0)
  1262. X            return(cptr);
  1263. X        if(!(path_buf = malloc(strlen(cptr) + 1)))
  1264. X            return((char *)0);
  1265. X        strcpy(path_buf,cptr);
  1266. X        path_name[PATHNAME_QUAN + 1] = (char *)0;
  1267. X        cptr = path_buf;
  1268. X        for(path_count = 0; path_count < PATHNAME_QUAN; path_count++)
  1269. X        {
  1270. X            if(*cptr == 0)
  1271. X                break;
  1272. X            path_name[path_count] = cptr;
  1273. X            while((*cptr != ':') && (*cptr != 0))
  1274. X                cptr++;
  1275. X            if(*cptr == ':')
  1276. X                *cptr++ = 0;
  1277. X        }
  1278. X    }    /* end of get and process path env variable */
  1279. X
  1280. X/* look for executable */
  1281. X    for(itmp = 0; itmp < path_count; itmp++)
  1282. X    {
  1283. X        if(*path_name[itmp] == 0)    /* if null path (./) */
  1284. X            strcpy(rtn_path,"./");
  1285. X        else
  1286. X            sprintf(rtn_path,"%s/",path_name[itmp]);
  1287. X        strcat(rtn_path,progname);
  1288. X        if(is_executable(rtn_path))
  1289. X            return(rtn_path);
  1290. X    }
  1291. X    return((char *)0);
  1292. X}    /* end of find_executable */
  1293. X
  1294. X/*+-------------------------------------------------------------------------
  1295. X    exec_cmd(cmdstr) - execute an arbitrary program with arguments
  1296. Xkills rcvr process if alive and restarts it when done if was alive
  1297. X--------------------------------------------------------------------------*/
  1298. Xexec_cmd(cmdstr)
  1299. Xchar *cmdstr;
  1300. X{
  1301. X    char *cmdpath;
  1302. X    char *cmdargv[MAX_EXEC_ARG];
  1303. X    int itmp;
  1304. X    int execpid;
  1305. X    int restart_rcvr = need_rcvr_restart();
  1306. X    int old_ttymode = get_ttymode();
  1307. X    int wait_status = 0;
  1308. X    char *strrchr();
  1309. X
  1310. X#if defined(FORK_DEBUG)
  1311. X    char s80[80];
  1312. X    strcpy(s80,"DEBUG exec ");
  1313. X    strncat(s80,cmdstr,sizeof(s80)-12);
  1314. X    s80[sizeof(s80)-12] = 0;
  1315. X    ecu_log_event(getpid(),s80);
  1316. X#endif
  1317. X
  1318. X    build_arg_array(cmdstr,cmdargv,MAX_EXEC_ARG,&itmp);
  1319. X    if(itmp == MAX_EXEC_ARG)
  1320. X    {
  1321. X        ff(se,"Too many arguments to command\r\n");
  1322. X        return(-1);
  1323. X    }
  1324. X    else if(!itmp)
  1325. X    {
  1326. X        ff(se,"null command\r\n");
  1327. X        return(-1);
  1328. X    }
  1329. X
  1330. X    if(*cmdargv[0] == '/')
  1331. X    {
  1332. X        cmdpath = cmdargv[0];
  1333. X        cmdargv[0] = strrchr(cmdargv[0],'/') + 1;
  1334. X    }
  1335. X    else
  1336. X    {
  1337. X        if((cmdpath = find_executable(cmdargv[0])) == (char *)0)
  1338. X        {
  1339. X            ff(se,"Cannot find %s\r\n",cmdargv[0]);
  1340. X            return(-1);
  1341. X        }
  1342. X    }
  1343. X
  1344. X    kill_rcvr_process(SIGUSR1);        /* stop receiver process gracefully */
  1345. X
  1346. X/* this code executed by the father (forking) process */
  1347. X/* wait on death of child (morbid in life, but ok here) */
  1348. X
  1349. X    signal(SIGINT,SIG_IGN);
  1350. X    signal(SIGQUIT,SIG_IGN);
  1351. X    signal(SIGUSR1,SIG_IGN);
  1352. X    signal(SIGUSR2,SIG_IGN);
  1353. X    signal(SIGCLD,SIG_DFL);
  1354. X
  1355. X    if((execpid = smart_fork()) < 0)
  1356. X    {
  1357. X        ff(se,"Cannot fork\r\n");
  1358. X        if(restart_rcvr)
  1359. X            start_rcvr_process(1);
  1360. X        xmtr_signals();
  1361. X        return(-1);
  1362. X    }
  1363. X
  1364. X    if(execpid == 0)            /* we are the spawned (going to call exec) */
  1365. X    {
  1366. X        ttymode(0);               /* set canonical tty mode */
  1367. X        child_signals();
  1368. X        execv(cmdpath,cmdargv);
  1369. X        perror(cmdpath);
  1370. X        _exit(255);                /* end of spawned process */
  1371. X    }    /* end of if child process */
  1372. X
  1373. X    wait_status = 0;
  1374. X    while(((itmp = wait(&wait_status)) != execpid) && (itmp != -1))
  1375. X        ;
  1376. X    last_child_wait_status = wait_status;
  1377. X    last_child_wait_pid = execpid;
  1378. X
  1379. X/* resume our normally scheduled program */
  1380. X    lreset_ksr();                /* restore comm line params */
  1381. X    ttymode(old_ttymode);        /* control tty back to original */
  1382. X    if(restart_rcvr)
  1383. X        start_rcvr_process(1);
  1384. X    xmtr_signals();
  1385. X    return(last_child_wait_status);
  1386. X
  1387. X}    /* end of exec_cmd */
  1388. X
  1389. X/*+-------------------------------------------------------------------------
  1390. X    expand_wildcard_list(wild,&expcmd)
  1391. X
  1392. Xcalled with 'foo <wildcardlist>' for command expansion prior to exec()
  1393. X         or '<wildcardlist>' to expand a list of files.
  1394. X
  1395. XIf called with 'foo'-style wild, anything you want to protect from csh 
  1396. Xglobbing or other interpretation must be properly protected (quoted) --
  1397. XAND quoting will be removed one level by the csh.
  1398. X
  1399. Xif return 0, wild has been expanded, expcmd must be free()'d when done
  1400. Xif return -1, error, expcmd has error message (static message: DO NOT FREE)
  1401. X--------------------------------------------------------------------------*/
  1402. Xexpand_wildcard_list(wild,expcmd)
  1403. Xchar *wild;
  1404. Xchar **expcmd;
  1405. X{
  1406. X    register char *cptr;
  1407. X#define P_READ 0
  1408. X#define P_WRITE 1
  1409. X    PID_T pipe_pid;
  1410. X    int stdout_pipe[2];
  1411. X    int stderr_pipe[2];
  1412. X    int count;
  1413. X    int expcmd_size = 0;
  1414. X    int itmp;
  1415. X    int wait_status;
  1416. X    int restart_rcvr = need_rcvr_restart();
  1417. X    FILE *fp_pipe = (FILE *)0;
  1418. X    char *echo_cmd;
  1419. X    static char s132[132];
  1420. X    char *strchr();
  1421. X    static char *pipe_err_msg = "system error: no pipe";
  1422. X    static char *mem_err_msg = "system error: no memory";
  1423. X
  1424. X    if(strchr(wild,'<') || strchr(wild,'>') || strchr(wild,'&'))
  1425. X    {
  1426. X        *expcmd = "illegal characters: '<', '>' or '&'";
  1427. X        return(-1);
  1428. X    }
  1429. X
  1430. X    if(pipe(stdout_pipe) < 0)
  1431. X    {
  1432. X        *expcmd = pipe_err_msg;
  1433. X        return(-1);
  1434. X    }
  1435. X    if(pipe(stderr_pipe) < 0)
  1436. X    {
  1437. X        close(stdout_pipe[P_READ]);
  1438. X        close(stdout_pipe[P_WRITE]);
  1439. X        *expcmd = pipe_err_msg;
  1440. X        return(-1);
  1441. X    }
  1442. X    if(!(echo_cmd = malloc(strlen(wild) + 10)))
  1443. X    {
  1444. X        close(stdout_pipe[P_READ]);
  1445. X        close(stdout_pipe[P_WRITE]);
  1446. X        close(stderr_pipe[P_READ]);
  1447. X        close(stderr_pipe[P_WRITE]);
  1448. X        *expcmd = mem_err_msg;
  1449. X        return(-1);
  1450. X    }
  1451. X
  1452. X    strcpy(echo_cmd,"echo ");
  1453. X    strcat(echo_cmd,wild);
  1454. X
  1455. X    kill_rcvr_process(SIGUSR1);        /* stop receiver process gracefully */
  1456. X
  1457. X    signal(SIGINT,SIG_IGN);
  1458. X    signal(SIGQUIT,SIG_IGN);
  1459. X    signal(SIGUSR1,SIG_IGN);
  1460. X    signal(SIGUSR2,SIG_IGN);
  1461. X    signal(SIGCLD,SIG_DFL);
  1462. X
  1463. X    if((pipe_pid = smart_fork()) == 0)
  1464. X    {
  1465. X    int null = open("/dev/null",O_WRONLY,0);
  1466. X
  1467. X        close(stdout_pipe[P_READ]);
  1468. X        close(TTYOUT);
  1469. X        dup(stdout_pipe[P_WRITE]);
  1470. X        close(stdout_pipe[P_WRITE]);
  1471. X        close(TTYERR);
  1472. X        dup(stderr_pipe[P_WRITE]);
  1473. X        close(stderr_pipe[P_WRITE]);
  1474. X        close(null);
  1475. X        child_signals();
  1476. X        execl("/bin/csh","csh","-e","-f","-c",echo_cmd,(char *)0);
  1477. X        _exit(255);
  1478. X    }
  1479. X
  1480. X#if defined(FORK_DEBUG)
  1481. X    sprintf(s132,"DEBUG expand pid %d",pipe_pid);
  1482. X    ecu_log_event(getpid(),s132);        /* expand_wildcard_list */
  1483. X#endif
  1484. X
  1485. X    free(echo_cmd);
  1486. X
  1487. X    close(stdout_pipe[P_WRITE]);
  1488. X    close(stderr_pipe[P_WRITE]);
  1489. X    if(pipe_pid == -1)
  1490. X    {
  1491. X        close(stdout_pipe[P_READ]);
  1492. X        close(stderr_pipe[P_READ]);
  1493. X        *expcmd = "could not fork";
  1494. X        if(restart_rcvr)
  1495. X            start_rcvr_process(0);
  1496. X        xmtr_signals();
  1497. X        return(-1);
  1498. X    }
  1499. X
  1500. X    if(!(*expcmd = malloc(expcmd_size = ESD_MAXSIZE)))
  1501. X    {
  1502. X        close(stdout_pipe[P_READ]);
  1503. X        close(stderr_pipe[P_READ]);
  1504. X        kill(pipe_pid,SIGKILL);
  1505. X        *expcmd = mem_err_msg;
  1506. X        if(restart_rcvr)
  1507. X            start_rcvr_process(0);
  1508. X        xmtr_signals();
  1509. X        return(-1);
  1510. X    }
  1511. X
  1512. X    if(!(fp_pipe = fdopen(stdout_pipe[P_READ],"r")) ||
  1513. X        ((count = fread(*expcmd,1,expcmd_size,fp_pipe)) < 0))
  1514. X    {
  1515. X            free(*expcmd);
  1516. X            kill(pipe_pid,SIGKILL);
  1517. X            close(stdout_pipe[P_READ]);
  1518. X            close(stderr_pipe[P_READ]);
  1519. X            *expcmd = "error reading wild list expansion";
  1520. X            if(restart_rcvr)
  1521. X                start_rcvr_process(0);
  1522. X            xmtr_signals();
  1523. X            return(-1);
  1524. X    }
  1525. X
  1526. X    /*
  1527. X     * make sure stdout is closed
  1528. X     */
  1529. X    if(fp_pipe)
  1530. X        fclose(fp_pipe);
  1531. X    close(stdout_pipe[P_READ]);
  1532. X
  1533. X    /*
  1534. X     * place trailing null
  1535. X     * kill trailing new line
  1536. X     */
  1537. X    if(count)
  1538. X    {
  1539. X        cptr = (*expcmd) + count;
  1540. X        *cptr-- = 0;
  1541. X        if(*cptr == '\n')
  1542. X        {
  1543. X            *cptr = 0;
  1544. X            count--;
  1545. X        }
  1546. X    }
  1547. X
  1548. X    /*
  1549. X     * if no expansion, read stderr to find out why
  1550. X     */
  1551. X    if(!count)
  1552. X    {
  1553. X        free(*expcmd);
  1554. X        count = read(stderr_pipe[P_READ],s132,sizeof(s132) - 1);
  1555. X        if(count < 0)
  1556. X            strcpy(s132,errno_text(errno));
  1557. X        else
  1558. X            s132[count] = 0;
  1559. X        if(s132[count - 1] == '\n')
  1560. X            s132[count - 1] = 0;
  1561. X        close(stderr_pipe[P_READ]);
  1562. X        if(strncmp(s132,"echo: ",6))
  1563. X            *expcmd = s132;
  1564. X        else
  1565. X            *expcmd = s132 + 6;
  1566. X        if(restart_rcvr)
  1567. X            start_rcvr_process(0);
  1568. X        return(-1);
  1569. X    }
  1570. X
  1571. X    /*
  1572. X     * clean up zombie
  1573. X     */
  1574. X    wait_status = 0;
  1575. X    while(((itmp = wait(&wait_status)) != pipe_pid) && (itmp != -1))
  1576. X        ;
  1577. X
  1578. X    xmtr_signals();
  1579. X
  1580. X    /*
  1581. X     * if bad termination status, read stderr
  1582. X     */
  1583. X    if(wait_status)
  1584. X    {
  1585. X        free(*expcmd);
  1586. X        count = read(stderr_pipe[P_READ],s132,sizeof(s132) - 1);
  1587. X        if(count < 0)
  1588. X            strcpy(s132,errno_text(errno));
  1589. X        else
  1590. X            s132[count] = 0;
  1591. X        if(s132[count - 1] == '\n')
  1592. X            s132[count - 1] = 0;
  1593. X        close(stderr_pipe[P_READ]);
  1594. X        if(strncmp(s132,"echo: ",6))
  1595. X            *expcmd = s132;
  1596. X        else
  1597. X            *expcmd = s132 + 6;
  1598. X        if(restart_rcvr)
  1599. X            start_rcvr_process(0);
  1600. X        return(-1);
  1601. X    }
  1602. X    close(stderr_pipe[P_READ]);
  1603. X
  1604. X    /*
  1605. X     * whew: we have (I think) a file list expansion
  1606. X     */
  1607. X    if(restart_rcvr)
  1608. X        start_rcvr_process(0);
  1609. X
  1610. X    return(0);
  1611. X}    /* end of expand_wildcard_list */
  1612. X
  1613. X/* vi: set tabstop=4 shiftwidth=4: */
  1614. X/* end of ecufork.c */
  1615. SHAR_EOF
  1616. chmod 0644 ecufork.c ||
  1617. echo 'restore of ecufork.c failed'
  1618. Wc_c="`wc -c < 'ecufork.c'`"
  1619. test 13563 -eq "$Wc_c" ||
  1620.     echo 'ecufork.c: original size 13563, current size' "$Wc_c"
  1621. rm -f _shar_wnt_.tmp
  1622. fi
  1623. # ============= ecufork.h ==============
  1624. if test -f 'ecufork.h' -a X"$1" != X"-c"; then
  1625.     echo 'x - skipping ecufork.h (File already exists)'
  1626.     rm -f _shar_wnt_.tmp
  1627. else
  1628. > _shar_wnt_.tmp
  1629. echo 'x - extracting ecufork.h (Text)'
  1630. sed 's/^X//' << 'SHAR_EOF' > 'ecufork.h' &&
  1631. X/*+-------------------------------------------------------------------------
  1632. X    ecufork.h 
  1633. X    wht@n4hgf.Mt-Park.GA.US
  1634. X
  1635. Xfor now just vehicle for deciding whether or not to debug fork/waits
  1636. X--------------------------------------------------------------------------*/
  1637. X/*+:EDITS:*/
  1638. X/*:09-10-1992-13:58-wht@n4hgf-ECU release 3.20 */
  1639. X/*:08-22-1992-15:38-wht@n4hgf-ECU release 3.20 BETA */
  1640. X/*:03-27-1992-16:21-wht@n4hgf-re-include protection for all .h files */
  1641. X/*:07-25-1991-12:55-wht@n4hgf-ECU release 3.10 */
  1642. X/*:08-14-1990-20:40-wht@n4hgf-ecu3.00-flush old edit history */
  1643. X
  1644. X#ifndef _ecufork_h
  1645. X#define _ecufork_h
  1646. X
  1647. X/* #define FORK_DEBUG */
  1648. X
  1649. X#endif /* _ecufork_h */
  1650. X
  1651. X/* vi: set tabstop=4 shiftwidth=4: */
  1652. X/* end of ecufork.h */
  1653. SHAR_EOF
  1654. chmod 0644 ecufork.h ||
  1655. echo 'restore of ecufork.h failed'
  1656. Wc_c="`wc -c < 'ecufork.h'`"
  1657. test 717 -eq "$Wc_c" ||
  1658.     echo 'ecufork.h: original size 717, current size' "$Wc_c"
  1659. rm -f _shar_wnt_.tmp
  1660. fi
  1661. # ============= ecugrabbag.c ==============
  1662. if test -f 'ecugrabbag.c' -a X"$1" != X"-c"; then
  1663.     echo 'x - skipping ecugrabbag.c (File already exists)'
  1664.     rm -f _shar_wnt_.tmp
  1665. else
  1666. > _shar_wnt_.tmp
  1667. echo 'x - extracting ecugrabbag.c (Text)'
  1668. sed 's/^X//' << 'SHAR_EOF' > 'ecugrabbag.c' &&
  1669. X/*+-----------------------------------------------------------------
  1670. X    ecugrabbag.c -- very machine/OS dependent functions
  1671. X    wht@n4hgf.Mt-Park.GA.US
  1672. X
  1673. X  Defined functions:
  1674. X    bell_alarm(xbell_type)
  1675. X    bell_notify(xbell_type)
  1676. X    bell_notify_text(bn)
  1677. X    kbd_escape(xkey)
  1678. X    morse_bell(xbell_type,count)
  1679. X    parse_bell_notify_argument(strarg)
  1680. X    rename(from,to)
  1681. X    send_bell_fd(fd,count,nap_msec)
  1682. X    send_get_response(narg,arg)
  1683. X    set_bell_fd(fd,pitch,duration)
  1684. X    set_default_escape_prompt()
  1685. X    show_escape_prompt()
  1686. X    signal_name_text(sig)
  1687. X    xbell(type,count)
  1688. X    xbell_fd(fd,type,count)
  1689. X    xterm_title(text,code)
  1690. X
  1691. X  This module is a grab bag for historical reasons.  Needs reorg.
  1692. X------------------------------------------------------------------*/
  1693. X/*+:EDITS:*/
  1694. X/*:09-10-1992-13:58-wht@n4hgf-ECU release 3.20 */
  1695. X/*:08-22-1992-15:38-wht@n4hgf-ECU release 3.20 BETA */
  1696. X/*:04-09-1992-05:47-wht@n4hgf-cleanup new "bn" argument parsing */
  1697. X/*:02-16-1992-01:41-wht@n4hgf-turn off xterm_title */
  1698. X/*:12-13-1991-17:14-wht@n4hgf-add bell_notify_text */
  1699. X/*:12-13-1991-17:14-wht@n4hgf-add parse_bell_notify_argument */
  1700. X/*:09-03-1991-18:23-wht@n4hgf-sigint rearrangement in send_get_response */
  1701. X/*:08-28-1991-14:07-wht@n4hgf2-SVR4 cleanup by aega84!lh */
  1702. X/*:08-13-1991-15:28-wht@n4hgf-more problems with history manager */
  1703. X/*:07-25-1991-12:57-wht@n4hgf-ECU release 3.10 */
  1704. X/*:07-17-1991-07:04-wht@n4hgf-avoid SCO UNIX nap bug */
  1705. X/*:07-14-1991-18:18-wht@n4hgf-new ttygets functions */
  1706. X/*:06-29-1991-15:42-wht@n4hgf-if WHT and xterm, play with title bar */
  1707. X/*:06-04-1991-13:19-wht@n4hgf-WHT version always gets morse for bells */
  1708. X/*:05-07-1991-06:10-wht@n4hgf-subtle changes in send_and_get_response */
  1709. X/*:03-18-1991-22:31-wht@n4hgf-ISC 2.2 has rename() */
  1710. X/*:01-16-1991-23:54-wht@n4hgf-if WHT, bell_notify always available */
  1711. X/*:01-09-1991-22:31-wht@n4hgf-ISC port */
  1712. X/*:12-04-1990-03:55-wht@n4hgf-bell_notify only if on multiscreen */
  1713. X/*:09-19-1990-19:36-wht@n4hgf-ecu_log_event now gets pid for log from caller */
  1714. X/*:08-14-1990-20:40-wht@n4hgf-ecu3.00-flush old edit history */
  1715. X
  1716. X#include "ecu.h"
  1717. X#include "ecukey.h"
  1718. X#include "ecufkey.h"
  1719. X#include "ecuxkey.h"
  1720. X#include "ecutty.h"
  1721. X#include "ecufork.h"
  1722. X#include "esd.h"
  1723. X
  1724. X#if defined(MORSE)
  1725. X/* the space between # and include prevents make depend from seeing this */
  1726. X# include <local/morse_dvr.h>
  1727. X#endif
  1728. X
  1729. Xchar *get_ttyname();
  1730. X
  1731. Xextern char curr_dir[]; /* current working key defns */
  1732. Xextern KDE keyset_table[];
  1733. Xextern char keyset_name[];
  1734. X
  1735. XESD *icmd_prompt;        /* interactive command prompt */
  1736. Xint icmd_prompt_len;
  1737. X
  1738. X/*+-------------------------------------------------------------------------
  1739. X    show_escape_prompt()
  1740. Xreturns number of character positions written to screen
  1741. X--------------------------------------------------------------------------*/
  1742. Xshow_escape_prompt()
  1743. X{
  1744. X    char prompt_last;
  1745. X
  1746. X    prompt_last = 'd';    /* dummy */
  1747. X    if(icmd_prompt->cb)
  1748. X        prompt_last = *(icmd_prompt->pb + icmd_prompt->cb - 1);
  1749. X
  1750. X    icmd_prompt_len = 0;
  1751. X    shmx_make_rcvr_sleep(1);
  1752. X    if(!(colors_current & 0xFFFF0000L) || !(colors_current & 0xFFFFL))
  1753. X        setcolor(colors_normal);
  1754. X    else
  1755. X        setcolor(colors_current);
  1756. X    tcap_stand_out();
  1757. X    if(icmd_prompt->cb)
  1758. X    {
  1759. X        ff(se," %s",icmd_prompt->pb);
  1760. X        icmd_prompt_len += icmd_prompt->cb + 1;
  1761. X    }
  1762. X    if(isalnum(prompt_last))
  1763. X    {
  1764. X        fputs(" %",se);
  1765. X        icmd_prompt_len += 2;
  1766. X    }
  1767. X    tcap_stand_end();
  1768. X    fputc(' ',se);
  1769. X    icmd_prompt_len++;
  1770. X    return(icmd_prompt_len);
  1771. X
  1772. X}    /* end of show_escape_prompt */
  1773. X
  1774. X/*+-------------------------------------------------------------------------
  1775. X    set_default_escape_prompt()
  1776. X--------------------------------------------------------------------------*/
  1777. Xvoid
  1778. Xset_default_escape_prompt()
  1779. X{
  1780. X    register char *cptr;
  1781. X    char *getenv();
  1782. X
  1783. X    if((cptr = getenv("ECUPROMPT")) != (char *)0)
  1784. X    {
  1785. X        strncpy(icmd_prompt->pb,cptr,icmd_prompt->maxcb);
  1786. X        *(icmd_prompt->pb + icmd_prompt->maxcb - 1) = 0;
  1787. X        icmd_prompt->cb = strlen(icmd_prompt->pb);
  1788. X        esd_null_terminate(icmd_prompt);
  1789. X    }
  1790. X
  1791. X}    /* end of set_default_escape_prompt */
  1792. X
  1793. X/*+-------------------------------------------------------------------------
  1794. X    kbd_escape() -- xmtr got extended key -- process it
  1795. Xreturns(1)
  1796. X--------------------------------------------------------------------------*/
  1797. Xkbd_escape(xkey)
  1798. Xuchar xkey;
  1799. X{
  1800. X    register itmp;
  1801. X    int ttygets_flags = TG_XDELIM;
  1802. X    uchar delim;
  1803. X    int strpos;
  1804. X    int old_ttymode = get_ttymode();
  1805. X    register backspace_count;
  1806. X    register KDE *tkde;
  1807. X    uchar icmd_buf[128];
  1808. X
  1809. X    if((xkey >= XF_ALTA) && (xkey <= XF_ALTZ))
  1810. X    {
  1811. X        char alt_key_proc_name[8];
  1812. X        char *arg = alt_key_proc_name;
  1813. X        int narg = 1;
  1814. X        int restart_rcvr = need_rcvr_restart();
  1815. X        kill_rcvr_process(SIGUSR1);
  1816. X        sprintf(alt_key_proc_name,"alt_%c",xkey - XF_ALTA + 'a');
  1817. X        ttymode(2);
  1818. X        ttyflush(0);
  1819. X        if(do_proc(narg,&arg))
  1820. X            ring_bell();
  1821. X        sigint = 0;
  1822. X        proc_file_reset();
  1823. X        ttymode(old_ttymode);
  1824. X        if(restart_rcvr)
  1825. X            start_rcvr_process(0);
  1826. X        return(1);
  1827. X    }
  1828. X
  1829. X    switch(xkey)
  1830. X    {
  1831. X        case XFhome:     /* home key pressed ? */
  1832. X            icmd_buf[0] = 0;
  1833. X            backspace_count = show_escape_prompt();
  1834. X            strpos = 0;
  1835. X            icmd_buf[0] = 0;
  1836. XGET_ICMD:
  1837. X            ttygets(icmd_buf,sizeof(icmd_buf),ttygets_flags,&delim,&strpos);
  1838. X            switch(delim)
  1839. X            {
  1840. X                case XFhome:
  1841. X                case XFpgup:
  1842. X                case XFcurup:
  1843. X                    if(icmd_history_manager(delim,icmd_buf,sizeof(icmd_buf)))
  1844. X                    {
  1845. X                        ring_bell();
  1846. X                        ttygets_flags |= 4;
  1847. X                        goto GET_ICMD;
  1848. X                    }
  1849. X                    break;
  1850. X                case ESC:
  1851. X                case NL:
  1852. X                    break;
  1853. X                default:
  1854. X                    ring_bell();
  1855. X                    itmp = strlen((char *)icmd_buf);
  1856. X                    while(itmp--)
  1857. X                        ff(se,"\b \b");
  1858. X                    ttygets_flags |= 4;
  1859. X                    goto GET_ICMD;
  1860. X            }
  1861. X            if((delim == ESC) || !icmd_buf[0])
  1862. X            {
  1863. X                while(backspace_count--)
  1864. X                    ff(se,"\b \b");
  1865. X                break;
  1866. X            }
  1867. X            if(icmd(icmd_buf))
  1868. X                termecu(TERMECU_OK);
  1869. X            break;
  1870. X
  1871. X        default:
  1872. X            if((itmp = xf_to_ikde(xkey)) < 0)
  1873. X            {
  1874. X                ring_bell();
  1875. X                break;
  1876. X            }
  1877. X            tkde = &keyset_table[itmp];
  1878. X            if((itmp = tkde->count) > 0)
  1879. X            {
  1880. X            register char *cptr = tkde->str;
  1881. X                while(itmp--)
  1882. X                    lputc(*cptr++);
  1883. X            }
  1884. X            else if(tkde->count < 0)
  1885. X            {
  1886. X                switch(tkde->count)
  1887. X                {
  1888. X                    case KACT_LOCAL_SHELL:
  1889. X                        fputs("\r\n",se);
  1890. X                        tcap_stand_out();
  1891. X                        ff(se," local shell in %s ",curr_dir);
  1892. X                        tcap_stand_end();
  1893. X                        ff(se,"\r\n");
  1894. X                        shell("!");
  1895. X                        break;
  1896. X                    case KACT_REDISPLAY:
  1897. X                        redisplay_rcvr_screen();
  1898. X                }
  1899. X            }
  1900. X            else
  1901. X                ring_bell();
  1902. X            break;
  1903. X    }
  1904. X    return(1);
  1905. X}    /* end of kbd_escape */
  1906. X
  1907. X/*+-------------------------------------------------------------------------
  1908. X    set_bell_fd(fd,pitch,duration)
  1909. XExample: 1B 5B 3D 34 30 30 30 3B 31 42 | .[=4000;1B
  1910. X--------------------------------------------------------------------------*/
  1911. Xvoid
  1912. Xset_bell_fd(fd,pitch,duration)
  1913. Xint fd;
  1914. Xint pitch;
  1915. Xint duration;
  1916. X{
  1917. X#if defined(M_SYSV)
  1918. X    char bell_cmd[32];
  1919. X
  1920. X    if(!tty_is_multiscreen)
  1921. X        return;
  1922. X
  1923. X    sprintf(bell_cmd,"\033[=%d;%dB",pitch,duration);
  1924. X    write(fd,bell_cmd,strlen(bell_cmd));
  1925. X#endif
  1926. X}    /* end of set_bell_fd */
  1927. X
  1928. X/*+-------------------------------------------------------------------------
  1929. X    send_bell_fd(fd,count,nap_msec)
  1930. X--------------------------------------------------------------------------*/
  1931. Xvoid
  1932. Xsend_bell_fd(fd,count,nap_msec)
  1933. Xregister fd;
  1934. Xregister count;
  1935. Xregister nap_msec;
  1936. X{
  1937. X    static char bellch = 0x07;
  1938. X
  1939. X    if(count)
  1940. X    {
  1941. X        while(count--)
  1942. X        {
  1943. X            write(fd,&bellch,1);    
  1944. X            Nap((long)nap_msec);
  1945. X        }
  1946. X    }
  1947. X}    /* end of send_bell_fd */
  1948. X
  1949. X/*+-------------------------------------------------------------------------
  1950. X    xbell_fd(fd,type,count)
  1951. X--------------------------------------------------------------------------*/
  1952. Xvoid
  1953. Xxbell_fd(fd,type,count)
  1954. Xregister fd;
  1955. Xregister type;
  1956. Xregister count;
  1957. X{
  1958. X#if defined(M_SYSV)
  1959. X    register itmp;
  1960. X
  1961. X    if(!tty_is_multiscreen)
  1962. X    {
  1963. X        ring_bell();
  1964. X        return;
  1965. X    }
  1966. X
  1967. X    if(count)
  1968. X    {
  1969. X        while(count--)
  1970. X        {
  1971. X            switch(type)
  1972. X            {
  1973. X                case XBELL_DONE:        /* octaves */
  1974. X                    set_bell_fd(fd,1000,1);
  1975. X                    send_bell_fd(fd,1,100);
  1976. X                    set_bell_fd(fd,2000,1);
  1977. X                    send_bell_fd(fd,1,100);
  1978. X                    set_bell_fd(fd,4000,1);
  1979. X                    send_bell_fd(fd,1,100);
  1980. X                    break;
  1981. X                case XBELL_ATTENTION:        /* morse .-.-.- ATTENTION */
  1982. X                    for(itmp = 0; itmp < 3; itmp++)
  1983. X                    {
  1984. X                        set_bell_fd(fd,2000,1);
  1985. X                        send_bell_fd(fd,1,140);
  1986. X                        set_bell_fd(fd,2000,3);
  1987. X                        send_bell_fd(fd,1,340);
  1988. X                    }
  1989. X                    break;
  1990. X                case XBELL_C:        /* morse -.-. C */
  1991. X                    for(itmp = 0; itmp < 2; itmp++)
  1992. X                    {
  1993. X                        set_bell_fd(fd,2000,3);
  1994. X                        send_bell_fd(fd,1,320);
  1995. X                        set_bell_fd(fd,2000,1);
  1996. X                        send_bell_fd(fd,1,120);
  1997. X                    }
  1998. X                    break;
  1999. X                case XBELL_3T:        /* 3 morse T's */
  2000. X                    set_bell_fd(fd,2000,3);
  2001. X                    send_bell_fd(fd,3,460);
  2002. X                    break;
  2003. X                default:
  2004. X                    set_bell_fd(fd,2000,4);
  2005. X                    send_bell_fd(fd,1,100);
  2006. X                    break;
  2007. X            }
  2008. X        }
  2009. X    }
  2010. X                
  2011. X    set_bell_fd(fd,4000,1);
  2012. X#endif    
  2013. X}    /* end of xbell_fd */
  2014. X
  2015. X/*+-------------------------------------------------------------------------
  2016. X    morse_bell(xbell_type,count)
  2017. X--------------------------------------------------------------------------*/
  2018. X#if defined(MORSE)
  2019. Xmorse_bell(xbell_type,count)
  2020. Xint xbell_type;
  2021. Xint count;
  2022. X{
  2023. X    register morse_fd;
  2024. X    int morse_frequency = 800;
  2025. X    char morse_char;
  2026. X    static int morse_ticks = 0;
  2027. X
  2028. X#if !defined(WHT)
  2029. X    if(!tty_is_multiscreen)
  2030. X    {
  2031. X        ring_bell();
  2032. X        return(0);
  2033. X    }
  2034. X#endif
  2035. X
  2036. X    if(!morse_ticks)
  2037. X        morse_ticks = hz / 25;
  2038. X
  2039. X    if((morse_fd = open("/dev/morse",O_WRONLY,0)) < 0)
  2040. X        return(-1);
  2041. X
  2042. X    ioctl(morse_fd,MORSE_SET_SPEED,&morse_ticks);
  2043. X    ioctl(morse_fd,MORSE_SET_FREQUENCY,&morse_frequency);
  2044. X    switch(xbell_type)
  2045. X    {
  2046. X        case XBELL_DONE:
  2047. X            morse_char = 'd';
  2048. X/*
  2049. X            morse_frequency = 400;
  2050. X            ioctl(morse_fd,MORSE_SET_FREQUENCY,&morse_frequency);
  2051. X*/
  2052. X            break;
  2053. X        case XBELL_ATTENTION:
  2054. X            morse_char = '.';
  2055. X            break;
  2056. X        case XBELL_C:
  2057. X            morse_char = 'c';
  2058. X            break;
  2059. X        case XBELL_3T:
  2060. X            morse_char = 'o';
  2061. X            break;
  2062. X        default:
  2063. X            morse_char = BT;
  2064. X            break;
  2065. X    }
  2066. X    while(count--)
  2067. X        write(morse_fd,&morse_char,1);
  2068. X    close(morse_fd);
  2069. X    return(0);
  2070. X}    /* end of morse_bell */
  2071. X#endif
  2072. X
  2073. X/*+-------------------------------------------------------------------------
  2074. X    xbell(type,count)
  2075. X--------------------------------------------------------------------------*/
  2076. Xvoid
  2077. Xxbell(type,count)
  2078. Xint type;
  2079. Xint count;
  2080. X{
  2081. X#if defined(WHT) && defined(MORSE)
  2082. X    if(morse_bell(type,count))
  2083. X        ring_bell();
  2084. X#else
  2085. X#if defined(WHT) && defined(AUDIO)
  2086. X    void audio_notify();
  2087. X    audio_notify(type);
  2088. X#else
  2089. X    if(!tty_is_multiscreen)
  2090. X    {
  2091. X        ring_bell();
  2092. X        return;
  2093. X    }
  2094. X
  2095. X#if defined(MORSE)
  2096. X    if(morse_bell(type,count))
  2097. X#endif
  2098. X        xbell_fd(1,type,count);
  2099. X#endif /* WHT && AUDIO */
  2100. X#endif /* WHT && MORSE */
  2101. X
  2102. X}    /* end of xbell */
  2103. X
  2104. X/*+-------------------------------------------------------------------------
  2105. X    bell_alarm(xbell_type)
  2106. X  ring bell on multiscreens; if morse driver included, use it instead
  2107. X--------------------------------------------------------------------------*/
  2108. Xint
  2109. Xbell_alarm(xbell_type)
  2110. Xint xbell_type;
  2111. X{
  2112. X#if defined(M_SYSV)
  2113. X    register notify_fd;
  2114. X    register fork_pid;
  2115. X    static long notify_time = 0L;
  2116. X    char *get_ttyname();
  2117. X    char devname[64];
  2118. X    int devnum;
  2119. X    int ttnum;
  2120. X
  2121. X#if !(defined(WHT) && defined(MORSE))
  2122. X    if(!tty_is_multiscreen)
  2123. X    {
  2124. X        ring_bell();
  2125. X        return(1);
  2126. X    }
  2127. X#endif
  2128. X
  2129. X    ttnum = atoi(get_ttyname() + 8);
  2130. X
  2131. X/* if happened less than 15 secs ago, forget it */
  2132. X    if((time((long *)0) - notify_time) < 15L)
  2133. X        return(0);
  2134. X
  2135. X    notify_time = time((long *)0);
  2136. X
  2137. X#if defined(MORSE)
  2138. X    if(morse_bell(xbell_type,1))
  2139. X    {
  2140. X#endif
  2141. X        if((fork_pid = smart_fork()) != 0)
  2142. X        {
  2143. X#if defined(FORK_DEBUG)
  2144. X            sprintf(devname,"DEBUG bell notify pid %d",fork_pid);
  2145. X            ecu_log_event(getpid(),devname);    /* bell notify */
  2146. X#endif
  2147. X            return(fork_pid > 0);
  2148. X        }
  2149. X
  2150. X        for(devnum = 1; devnum < 13; devnum++)
  2151. X        {
  2152. X            if(devnum == ttnum)        /* don't bell notify ecu's tty */
  2153. X                continue;
  2154. X            sprintf(devname,"/dev/tty%02d",devnum);
  2155. X            if((notify_fd = open(devname,O_WRONLY,0)) >= 0)
  2156. X            {
  2157. X                xbell_fd(notify_fd,xbell_type,1);
  2158. X                close(notify_fd);
  2159. X            }
  2160. X        }
  2161. X
  2162. X        _exit(0);        /* end of child tine (of the fork, naturally) */
  2163. X#if defined(MORSE)
  2164. X    }
  2165. X    /*NOTREACHED*/
  2166. X#endif
  2167. X#else /* not SCO (M_SYSV) */
  2168. X    ring_bell();
  2169. X#endif
  2170. X    return(1);
  2171. X}    /* end of bell_alarm */
  2172. X
  2173. X/*+-------------------------------------------------------------------------
  2174. X    bell_notify(xbell_type)
  2175. X--------------------------------------------------------------------------*/
  2176. Xvoid
  2177. Xbell_notify(xbell_type)
  2178. Xint xbell_type;
  2179. X{
  2180. X#if defined(M_SYSV)
  2181. X    if(
  2182. X#if !defined(WHT) && !defined(PTY_BELL_NOTIFY)
  2183. X        tty_is_multiscreen &&
  2184. X#endif
  2185. X             shm->bell_notify_state)
  2186. X    {
  2187. X        bell_alarm(xbell_type);
  2188. X    }
  2189. X#endif
  2190. X}    /* end of bell_notify */
  2191. X
  2192. X/*+-------------------------------------------------------------------------
  2193. X    parse_bell_notify_argument(strarg) - parse "bell notify" argument
  2194. X
  2195. X  Returns 0,1,2 according to parsing rules
  2196. X          -1 on error
  2197. X--------------------------------------------------------------------------*/
  2198. Xint
  2199. Xparse_bell_notify_argument(strarg)
  2200. Xchar *strarg;
  2201. X{
  2202. X    static STR_CLASSIFY sc[] = {
  2203. X        { "off",    3,0 },
  2204. X        { "on",        2,1 },
  2205. X        { "alert",  1,2 },
  2206. X        { (char *)0,0,-1 },
  2207. X    };
  2208. X    int itmp;
  2209. X
  2210. X    if(isdigit(*strarg))
  2211. X    {
  2212. X        if( ( (itmp = atoi(strarg)) >= 0) && (itmp < 3) )
  2213. X            return(itmp);
  2214. X        return(-1);
  2215. X    }
  2216. X
  2217. X    return(str_classify(sc,strarg));
  2218. X
  2219. X}    /* end of parse_bell_notify_argument */
  2220. X
  2221. X/*+-------------------------------------------------------------------------
  2222. X    bell_notify_text(bn) - text for bell notify status
  2223. X--------------------------------------------------------------------------*/
  2224. Xchar *
  2225. Xbell_notify_text(bn)
  2226. Xint bn;
  2227. X{
  2228. X    char *cptr = "?";
  2229. X
  2230. X    switch(bn)
  2231. X    {
  2232. X        case 0: cptr = "OFF"; break;
  2233. X        case 1: cptr = "ON"; break;
  2234. X        case 2: cptr = "ON+ALERT"; break;
  2235. X        default: cptr = "???"; break;
  2236. X    }
  2237. X    return(cptr);
  2238. X}    /* end of bell_notify_text */
  2239. X
  2240. X/*+-------------------------------------------------------------------------
  2241. X    signal_name_text(sig)
  2242. X--------------------------------------------------------------------------*/
  2243. Xchar *
  2244. Xsignal_name_text(sig)
  2245. Xint sig;
  2246. X{
  2247. X    register char *cptr;
  2248. X    static char sigunknown[20];
  2249. X
  2250. X    sig &= 0x7F;
  2251. X    switch(sig)
  2252. X    {
  2253. X        case SIGHUP:    cptr = "SIGHUP"; break;
  2254. X        case SIGINT:    cptr = "SIGINT"; break;
  2255. X        case SIGQUIT:    cptr = "SIGQUIT"; break;
  2256. X        case SIGILL:    cptr = "SIGILL"; break;
  2257. X        case SIGTRAP:    cptr = "SIGTRAP"; break;
  2258. X#ifdef SIGIOT
  2259. X        case SIGIOT:    cptr = "SIGIOT"; break;
  2260. X#endif
  2261. X#ifdef SIGEMT
  2262. X        case SIGEMT:    cptr = "SIGEMT"; break;
  2263. X#endif
  2264. X        case SIGFPE:    cptr = "SIGFPE"; break;
  2265. X        case SIGKILL:    cptr = "SIGKILL"; break;
  2266. X        case SIGBUS:    cptr = "SIGBUS"; break;
  2267. X        case SIGSEGV:    cptr = "SIGSEGV"; break;
  2268. X        case SIGSYS:    cptr = "SIGSYS"; break;
  2269. X        case SIGPIPE:    cptr = "SIGPIPE"; break;
  2270. X        case SIGALRM:    cptr = "SIGALRM"; break;
  2271. X        case SIGTERM:    cptr = "SIGTERM"; break;
  2272. X        case SIGUSR1:    cptr = "SIGUSR1"; break;
  2273. X        case SIGUSR2:    cptr = "SIGUSR2"; break;
  2274. X        case SIGCLD:    cptr = "SIGCLD"; break;
  2275. X#if    defined(SIGPWR)
  2276. X        case SIGPWR:    cptr = "SIGPWR"; break;
  2277. X#endif
  2278. X#if    defined(SIGSTOP)
  2279. X        case SIGSTOP:   cptr = "SIGSTOP"; break;
  2280. X#endif
  2281. X#if    defined(SIGTSOP)
  2282. X        case SIGTSTP:   cptr = "SIGTSTP"; break;
  2283. X#endif
  2284. X#if    defined(SIGCONT)
  2285. X        case SIGCONT:   cptr = "SIGCONT"; break;
  2286. X#endif
  2287. X#if    defined(SIGTTIN)
  2288. X        case SIGTTIN:   cptr = "SIGTTIN"; break;
  2289. X#endif
  2290. X#if    defined(SIGTTOU)
  2291. X        case SIGTTOU:   cptr = "SIGTTOU"; break;
  2292. X#endif
  2293. X        default:
  2294. X            sprintf(sigunknown,"SIGNAL %u",sig);
  2295. X            return(sigunknown);
  2296. X    }
  2297. X    return(cptr);
  2298. X
  2299. X}    /* end of signal_name_text */
  2300. X
  2301. X/*+-------------------------------------------------------------------------
  2302. X    rename(from,to)
  2303. X--------------------------------------------------------------------------*/
  2304. X#if defined(M_XENIX) && !defined(BUILDING_LINT_ARGS)
  2305. Xint
  2306. Xrename(from,to)
  2307. Xchar *from;
  2308. Xchar *to;
  2309. X{
  2310. X    struct stat ss;
  2311. X    int save_errno;
  2312. X    extern int errno;
  2313. X
  2314. X    if(!stat(to,&ss))    /* if to exists, flunk */
  2315. X    {
  2316. X        errno = EEXIST;    /* fake "file exists" error */
  2317. X        return(-1);
  2318. X    }
  2319. X
  2320. X    if(link(from,to))    /* if cannot link, flunk */
  2321. X        return(-1);
  2322. X
  2323. X    if(unlink(from))    /* if cannot unlink, flunk */
  2324. X    {
  2325. X        save_errno = errno;
  2326. X        unlink(to);
  2327. X        errno = save_errno;
  2328. SHAR_EOF
  2329. true || echo 'restore of ecugrabbag.c failed'
  2330. fi
  2331. echo 'End of ecu320 part 7'
  2332. echo 'File ecugrabbag.c is continued in part 8'
  2333. echo 8 > _shar_seq_.tmp
  2334. exit 0
  2335.  
  2336. exit 0 # Just in case...
  2337.