home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / unix / volume16 / fep / part04 < prev    next >
Encoding:
Internet Message Format  |  1988-11-09  |  26.0 KB

  1. Subject:  v16i064:  Front end editor program, Part04/05
  2. Newsgroups: comp.sources.unix
  3. Sender: sources
  4. Approved: rsalz@uunet.UU.NET
  5.  
  6. Submitted-by: Kazumasa Utashiro <kddlab!sra.junet!utashiro>
  7. Posting-number: Volume 16, Issue 64
  8. Archive-name: fep/part04
  9.  
  10. #!/bin/sh
  11. # to extract, remove the header and type "sh filename"
  12. if `test ! -s ./fep_defs.h`
  13. then
  14. echo "writing ./fep_defs.h"
  15. cat > ./fep_defs.h << '\End\Of\File\'
  16. /*    Copyright (c) 1987, 1988 by Software Research Associates, Inc.    */
  17.  
  18. #ifndef lint
  19. # define FEP_DEFS \
  20.     "$Header: fep_defs.h,v 4.0 88/08/05 20:21:51 utashiro Rel $ (SRA)"
  21. #endif lint
  22.  
  23. #define    MAXCOMLEN        512    /* maximum command length */
  24. #define MAXARGS            64    /* maximum number of arguments */
  25. #define ON            1    /* on switch */
  26. #define OFF            0    /* off switch */
  27. #define DFL_HISTLEN        100    /* default history length */
  28. #define DFL_SHOWHIST        20    /* default show history length */
  29. #define    IGNORED            2    /* ignored */
  30. #define    PROCESSED        1    /* processed or not by history */
  31. #define    NOT_PROCESSED        0    /* built-in functions */
  32.  
  33. #define BS            '\b'    /* backspace character */
  34. #define SP            ' '    /* space character */
  35.  
  36. #define    DEFAULT_DELIMITERS    " \t"    /* default delimiter character */
  37.  
  38. /*
  39.  * Pseudo functions
  40.  */
  41. #define eq(a,b)        (strcmp(a,b) == 0)
  42. #define abs(a)        ((a)>0?(a):-(a))
  43. #define max(a,b)    ((a)>(b)?(a):(b))
  44. #define min(a,b)    ((a)<(b)?(a):(b))
  45. #ifdef KANJI
  46. # define isctlchar(c)    (c && !iskanji(c) && (!(c&0140) || c=='\177'))
  47. # define iswordchar(c)    (c && (iskanji(c) || isalnum(c) || iscntrl(c)))
  48. # define isWordchar(c)    ((c) && !isspace((c)))
  49. #else KANJI
  50. # define isctlchar(c)    (c && (!(c&0140) || c=='\177'))
  51. # define iswordchar(c)    (isalnum(c) || iscntrl(c))
  52. # define isWordchar(c)    ((c) && !isspace((c)))
  53. #endif KANJI
  54. #define unctl(c)    (((c)=='\177') ? '?' : ((c) >= 040) ? (c) : (c)|0100)
  55. #define toctrl(c)    ((c)&~0100)
  56.  
  57. #define    INDIRECTED    (1<<(sizeof(char*)*8-1))
  58.             /* this is actually 0x80000000 on 32 bit machine,
  59.             that addresses kernel address space */
  60. #define isIndirect(f)    ((u_int)(f)&(u_int)INDIRECTED)
  61. #define setIndirect(f)    (FUNC)((u_int)(f)|(u_int)INDIRECTED)
  62. #define    maskIndirect(f)    (FUNC *)((u_int)(f)&~(u_int)INDIRECTED)
  63.  
  64. /*
  65.  * Type of character
  66.  */
  67. #ifdef KANJI
  68. # define CHAR        unsigned char
  69. # define CHARMASK    0377
  70. #else KANJI
  71. # define CHAR        char
  72. # define CHARMASK    0177
  73. #endif KANJI
  74.  
  75. /*
  76.  * Only one machine I know alloca() works is vax.
  77.  */
  78. #ifdef vax
  79. # define ALLOCA
  80. #endif vax
  81.  
  82. /*
  83.  * Typedef's
  84.  */
  85. typedef    int    (*FUNC)();        /* pointer to funciton */
  86.  
  87. typedef enum {                /* edit status */
  88.     EDITING,
  89.     NOTEDITING
  90. } EDITSTATUS;
  91.  
  92. typedef enum {                /* edit mode */
  93.     NOTYET,
  94.     EMACS,
  95.     VI
  96. } EDITMODE;
  97.  
  98. typedef struct {            /* bind table entry type */
  99.     char    *bt_s;
  100.     FUNC    bt_func;
  101. } BINDENT;
  102.  
  103. typedef struct _var {
  104.     char *v_name;
  105.     char *v_value;
  106.     char *v_help;
  107.     struct _var *v_next;
  108. } VAR;
  109.  
  110. typedef struct {
  111.     char *buf;            /* buffer */
  112.     char *last_buf;        /* last i/o done pointer */
  113.     int b_max;            /* max size */
  114.     int start;            /* start point */
  115.     int next;            /* next read point */
  116.     int count;            /* count */
  117.     int hiwater;        /* high water mark */
  118. } BUFFER;
  119.  
  120. #define buf_count(b) ((b)->count)
  121. #define buf_remain(b) ((b)->size - (b)->count)
  122. /*
  123. char buf_char (b, n)
  124.     BUFFER *b;
  125.     int n;
  126. {
  127.     if (n >= 0) {
  128.     if (n >= b->count)
  129.         return ((char*)-1);
  130.     return (b->buf[(b->start+n)%b->count]);
  131.     } else {
  132.     if (-n >= b->count)
  133.         return (-1);
  134.     if (b->next+n >= 0)
  135.         return (b->buf[b->next+n]);
  136.     else
  137.         return (b->buf[b->next+n+b->count]);
  138.     }
  139. }
  140. */        
  141. #define buf_char(b,n) \
  142.     (((n)>=0) \
  143.      ?(((n)>=(b)->count) \
  144.        ? ((char)-1) \
  145.        : ((b)->buf[((b)->start+n)%(b)->count])) \
  146.      :((-(n) > (b)->count) \
  147.        ?((char)-1) \
  148.        :((((b)->next+n) >= 0) \
  149.          ? ((b)->buf[(b)->next+(n)]) \
  150.          : ((b)->buf[(b)->next+n+(b)->count]))))
  151. \End\Of\File\
  152. else
  153.   echo "will not over write ./fep_defs.h"
  154. fi
  155. if `test ! -s ./fep_glob.h`
  156. then
  157. echo "writing ./fep_glob.h"
  158. cat > ./fep_glob.h << '\End\Of\File\'
  159. /*    Copyright (c) 1987, 1988 by Software Research Associates, Inc.    */
  160.  
  161. #ifndef lint
  162. # define FEP_GLOB \
  163.     "$Header: fep_glob.h,v 4.0 88/08/05 20:21:55 utashiro Rel $ (SRA)"
  164. #endif lint
  165.  
  166. extern FUNC    *curFuncTab;    /* function table */
  167. extern FUNC    *altFuncTab;    /* altanative function table */
  168. extern int    debug;        /* debug flag */
  169. extern char    *prompt;    /* prompt string */
  170. extern char    *delimiters;    /* delimiter characters */
  171. extern EDITMODE    editmode;    /* edit mode */
  172. extern FILE    *redirect_fp;    /* FILE pointer for I/O redirection */
  173. extern FILE    *script_fp;    /* FILE pointer for script */
  174. extern int    redirect_line;    /* number of line for redirecting */
  175. extern int    redirect_pid;    /* process id redirecting from */
  176. extern int    auto_tty_fix;    /* fix tty mode automatically */
  177. extern int    tty_fix_bell;    /* ring bell when tty mode is changed */
  178. extern int    Transparency;    /* transparent flag */
  179. extern EDITSTATUS   editstatus;    /* edit status */
  180. extern BUFFER    *output_buffer;    /* output buffer */
  181.  
  182. extern int    lines, columns;    /* terminal sizes */
  183. extern char    *term_clear;    /* terminal clear code */
  184.  
  185. /*
  186.  * tty control caracters.
  187.  * defined in fep_main.c
  188.  */
  189. extern struct tchars tchars_buf;
  190. extern struct ltchars ltchars_buf;
  191. extern struct sgttyb initial_ttymode;
  192. \End\Of\File\
  193. else
  194.   echo "will not over write ./fep_glob.h"
  195. fi
  196. if `test ! -s ./fep_funcs.h`
  197. then
  198. echo "writing ./fep_funcs.h"
  199. cat > ./fep_funcs.h << '\End\Of\File\'
  200. /*    Copyright (c) 1987, 1988 by Software Research Associates, Inc.    */
  201.  
  202. #ifndef lint
  203. # define FEP_FUNCS \
  204.     "$Header: fep_funcs.h,v 4.0 88/08/05 20:21:53 utashiro Rel $ (SRA)"
  205. #endif lint
  206.  
  207. /*
  208.  * command line edit functions
  209.  */
  210. int    abort();
  211. int    backward_character();
  212. int    backward_word();
  213. int    backward_Word();
  214. int    beginning_of_line();
  215. int    clear_screen();
  216. int    delete_line();
  217. int    delete_next_character();
  218. int    delete_next_word();
  219. int    delete_next_Word();
  220. int    delete_previous_character();
  221. int    delete_previous_word();
  222. int    delete_previous_Word();
  223. int    delete_to_kill_buffer();
  224. int    terminate();
  225. int    end_of_line();
  226. int    expand_file_name();
  227. int    forward_character();
  228. int    forward_to_end_of_word();
  229. int    forward_to_end_of_Word();
  230. int    forward_word();
  231. int    forward_Word();
  232. int    ignore();
  233. int    insert_and_flush();
  234. int    insert_tab();
  235. int    kill_to_end_of_line();
  236. int    kill_to_top_of_line();
  237. int    list_file_name();
  238. int    literal_next();
  239. int    mark();
  240. int    new_line();
  241. int    next_history();
  242. int    previous_history();
  243. int    reprint();
  244. int    search_reverse();
  245. int    search_forward();
  246. int    self_insert();
  247. int    send_eof();
  248. int    show_bindings();
  249. int    show_history();
  250. int    toggle_transparency();
  251. int    fix_transparency();
  252. int    yank_from_kill_buffer();
  253. int    invoke_shell();
  254. int    show_help();
  255.  
  256. /*
  257.  * Vi mode functions.
  258.  */
  259. int    vi_num();
  260. int    vi_edit();
  261. int    vi_motion();
  262. int    vi_c();
  263. int    vi_d();
  264. int    vi_ins_edit();
  265. int    vi_new_line();
  266.  
  267. /*
  268.  * fep builtin command functions.
  269.  */
  270. int    suspend();
  271. int    bind_to_key();
  272. int    alias();
  273. int    unalias();
  274. int    set();
  275. int    unset();
  276. int    fep_chdir();
  277. int    fep_pwd();
  278. int    fep_history();
  279. int    show_bindings();
  280. int    fep_source();
  281. int    fep_command();
  282. int    fep_save_history();
  283. int    fep_start_script();
  284. int    fep_end_script();
  285. int    fep_read_history();
  286. int    fep_read_from_file();
  287. int    fep_read_from_command();
  288. int    fep_echo();
  289. int    fep_if();
  290. int    fep_else();
  291. int    fep_endif();
  292. int    fep_repaint();
  293. #ifdef STAT
  294. int    fep_showstat();
  295. #endif
  296.  
  297. /*
  298.  * FunctionNameTable
  299.  */
  300. typedef struct {
  301.     int (*func)();
  302.     char *name;
  303.     char *help;
  304. } FunctionTableEnt;
  305.  
  306. extern FunctionTableEnt FunctionNameTable[];
  307. extern FunctionTableEnt BuiltinFuncTable[];
  308.  
  309. char *look_var();
  310. char *push_condition();
  311. char *pop_condition();
  312. char *change_condition();
  313. \End\Of\File\
  314. else
  315.   echo "will not over write ./fep_funcs.h"
  316. fi
  317. if `test ! -s ./fep_stat.h`
  318. then
  319. echo "writing ./fep_stat.h"
  320. cat > ./fep_stat.h << '\End\Of\File\'
  321. /*    Copyright (c) 1987, 1988 by Software Research Associates, Inc.    */
  322.  
  323. #ifndef lint
  324. # define FEP_STAT \
  325.     "$Header: fep_stat.h,v 4.0 88/08/05 20:21:58 utashiro Rel $ (SRA)"
  326. #endif lint
  327.  
  328. extern long stat_obyte;
  329. extern long stat_ibyte;
  330. extern long stat_rerror;
  331. extern long stat_werror;
  332. extern long stat_nselect;
  333.  
  334. struct statistics {
  335.     char *info_name;
  336.     long *info_valp;
  337. };
  338. \End\Of\File\
  339. else
  340.   echo "will not over write ./fep_stat.h"
  341. fi
  342. if `test ! -s ./fep_main.c`
  343. then
  344. echo "writing ./fep_main.c"
  345. cat > ./fep_main.c << '\End\Of\File\'
  346. /*    Copyright (c) 1987, 1988 by Software Research Associates, Inc.    */
  347.  
  348. #ifndef lint
  349. static char rcsid[]=
  350. "$Header: fep_main.c,v 4.0 88/08/05 20:22:17 utashiro Rel $ (SRA)";
  351. #endif lint
  352.  
  353. #include <stdio.h>
  354. #include <signal.h>
  355. #include <sys/types.h>
  356. #include <sys/stat.h>
  357. #include <sys/ioctl.h>
  358. #include <sys/file.h>
  359. #include <sgtty.h>
  360. #include <sys/time.h>
  361. #include <sys/resource.h>
  362. #include <sys/errno.h>
  363.  
  364. #include "fep_defs.h"
  365. #include "fep_glob.h"
  366. #include "fep_funcs.h"
  367. #ifdef STAT
  368. #include "fep_stat.h"
  369. #endif
  370.  
  371. #ifndef lint
  372.   static char fep_defsrc[] = FEP_DEFS;
  373.   static char fep_globrc[] = FEP_GLOB;
  374.   static char fep_funcsrc[] = FEP_FUNCS;
  375. #ifdef STAT
  376.   static char fep_statrc[] = FEP_STAT;
  377. #endif
  378. #endif lint
  379.  
  380. char    *myself;            /* the command name */
  381. char    *prompt = "";            /* prompt string */
  382. char    *delimiters = DEFAULT_DELIMITERS;
  383.                     /* delimiter characters */
  384. int    master;                /* file discriptor for pty master */
  385. int    slave;                /* file discriptor for pty slave */
  386. int    mastermask;            /* 1<<master */
  387. int    stdinmask;            /* 1<<fileno(stdin) */
  388. int    selectmask;            /* stdinmask | mastermask */
  389. int    selectnfds;            /* max (fileno(stdin), master) + 1*/
  390. int    child_pid;            /* child pid */
  391. int    ptyflag = ON;            /* flag to use pty or not */
  392. int    histlen = -1;            /* history length */
  393. int    debug = OFF;            /* debug switch */
  394. int    auto_tty_fix = ON;        /* fix tty mode automaticaly */
  395. FILE    *script_fp = NULL;        /* script file pointer */
  396. int    catchsig();            /* function take care SIGCHILD */
  397.  
  398. struct    sgttyb initial_ttymode;        /* initial tty mode */
  399. struct    sgttyb master_ttymode;        /* master tty mode */
  400. struct    sgttyb slave_ttymode;        /* slave tty mode */
  401.  
  402. int    lines;                /* terminal line size */
  403. int    columns;            /* terminal coulumn size */
  404. char    *term_clear;            /* terminal clear code */
  405.  
  406. FUNC    sighup, sigchld, sigtstp;    /* function buffer for signal */
  407.  
  408. struct    tchars tchars_buf;        /* tty characters */
  409. struct    ltchars ltchars_buf;        /* tty characters */
  410. int    lmode_buf;            /* local mode */
  411. int    line_desc;            /* line descipline */
  412. #ifdef KANJI
  413. struct    jtchars jtchars_buf;        /* kanji tty characters */
  414. int    kmode_buf;            /* kanji mode */
  415. #endif KANJI
  416.  
  417. char    master_tty[16];            /* master tty name */
  418. char    slave_tty[16];            /* slave tty name */
  419.  
  420. BUFFER iobuffer;            /* buffer self */
  421. BUFFER *output_buffer = &iobuffer;    /* buffer pointer */
  422.  
  423. struct cmdinfo {
  424.     char *command;
  425.     char *prompt;
  426.     char *delimiters;
  427. } cmdinfo_tab [] = {
  428.     {"/bin/sh",        "$ ",        " \t()<>{};&|='\""},
  429.     {"sh",            "$ ",        " \t()<>{};&|='\""},
  430.     {"jsh",            "$ ",        " \t()<>{};&|='\""},
  431.     {"/bin/csh",        "% ",        " \t()<>{};&|='\""},
  432.     {"csh",            "% ",        " \t()<>{};&|='\""},
  433.     {"jcsh",        "% ",        " \t()<>{};&|='\""},
  434.     {"/usr/ucb/dbx",    "(dbx) ",    " \t>"},
  435.     {"dbx",            "(dbx) ",    " \t>"},
  436.     {"/etc/lpc",        "lpc> ",    " \t"},
  437.     {"lpc",            "lpc> ",    " \t"},
  438.     {"/usr/ucb/mail",    "& ",        " \t"},
  439.     {"mail",        "& ",        " \t"},
  440.     {"/usr/lib/sendmail",    "> ",        " \t"},
  441.     {"sendmail",        "> ",        " \t"},
  442.     {"/usr/sra/calc",    "CALC: ",    " \t"},
  443.     {"calc",        "CALC: ",    " \t"},
  444.     {0,            0}
  445. };
  446.  
  447. main(argc, argv)
  448.     int argc;
  449.     char *argv[];
  450. {
  451.     int     i;
  452.     char    *cp;
  453.     char    *getenv();
  454.     char    **commandv;
  455.     char    *allocAndCopyThere();
  456.  
  457.     myself = argv[0];
  458.  
  459.     /*
  460.      * Initialize binding table
  461.      */
  462.     init_bind_table ();
  463.  
  464.     /*
  465.      * Set default variables before process arguments.
  466.      */
  467.     set_default_vars ();
  468.  
  469.  
  470.     /*
  471.      * Look environment variable first.
  472.      */
  473.     /* EDITMODE */
  474.     if ((cp=getenv("EDITMODE")) && (eq(cp,"emacs")||eq(cp,"vi")))
  475.     set_only_var ("editmode", cp);
  476.     /* USER */
  477.     if (cp=getenv("USER"))
  478.     set_only_var ("user", cp);
  479.     /* HOME */
  480.     if (cp=getenv("HOME"))
  481.     set_only_var ("home", cp);
  482.     /* TERM */
  483.     if (cp=getenv("TERM"))
  484.     set_only_var ("term", cp);
  485.     /* SHELL */
  486.     if (cp=getenv("SHELL"))
  487.     set_only_var ("shell", cp);
  488.  
  489.     /*
  490.      * Check arguments.
  491.      */
  492.     while (argv[1] && argv[1][0] == '-') {
  493.     switch (argv[1][1]) {
  494.  
  495.         case '\0': /* - */
  496.         ptyflag = 0;
  497.         break;
  498.  
  499.         case 'd':  /* -d */
  500.         debug = ON;
  501.         break;
  502.  
  503.         case 'e': /* -emacs */
  504.         if (strcmp (argv[1], "-emacs") == 0)
  505.             set_only_var ("editmode", "emacs");
  506.         else
  507.             goto DEFAULT;
  508.         break;
  509.  
  510.         case 'h': /* -h */
  511.         if (argv[1][2] == '\0') {
  512.             argv++;
  513.             argc--;
  514.             if (argc == 1)
  515.             usageAndExit ();
  516.             histlen = atoi (argv[1]);
  517.         }
  518.         else {
  519.             histlen = atoi (&argv[1] + 2);
  520.         }
  521.         break;
  522.  
  523.         case 'p': /* -p */
  524.         if (argv[1][2] == '\0') {
  525.             argv++;
  526.             argc--;
  527.             if (argc == 1)
  528.             usageAndExit ();
  529.             prompt = allocAndCopyThere (argv[1]);
  530.         }
  531.         else {
  532.             prompt = allocAndCopyThere (argv[1] + 2);
  533.         }
  534.         break;
  535.  
  536.         case 'v': /* -vi */
  537.         if (strcmp (argv[1], "-vi") == 0)
  538.             set_only_var ("editmode", "vi");
  539.         else
  540.             goto DEFAULT;
  541.         break;
  542. DEFAULT:
  543.         default: 
  544.         printf ("Unknown option \"%s\"\n", argv[1]);
  545.     }
  546.     argv++;
  547.     argc--;
  548.     }
  549.     fflush (stdout);
  550.  
  551.     if (argc < 2 && ptyflag) {
  552.     usageAndExit ();
  553.     }
  554.  
  555.     look_cmdinfo (argv[1]);
  556.  
  557.     /*
  558.      * Set variable of command name.
  559.      */
  560.     {
  561.     char *cp = argv[1], *rindex();
  562.  
  563.     if (any ('/', cp))
  564.         cp = rindex (cp, '/') + 1;
  565.     set_var (cp, "1");
  566.     set_var ("command", cp);
  567.     }
  568.  
  569.     commandv = &argv[1];
  570.  
  571.     if (! isatty (0)) {
  572.     execvp (*commandv, commandv, 0);
  573.     perror (*commandv);
  574.     exit (1);
  575.     }
  576.  
  577.     get_pty_master ();
  578.     fix_tty ();
  579.  
  580.     if (histlen < 0) {
  581.     if (getenv ("HISTLEN"))
  582.         histlen = atoi (getenv ("HISTLEN"));
  583.     else
  584.         histlen = DFL_HISTLEN;
  585.     }
  586.  
  587.     /*
  588.      * Initialize output buffer.
  589.      */
  590.     output_buffer->buf = (char *) malloc (5120);
  591.     if (output_buffer->buf <= 0) {
  592.     fprintf (stderr, "Can't allocate enough momory\n");
  593.     kill_process ();
  594.     exit (1);
  595.     }
  596.     output_buffer->b_max = 5120;
  597.     output_buffer->hiwater = 4096;
  598.     output_buffer->count = output_buffer->next = output_buffer->start = 0;
  599.  
  600.     init_hist (histlen);
  601.     init_edit_params ();
  602.  
  603.     if (ptyflag) {
  604.     child_pid = fork ();
  605.     if (child_pid < 0) {
  606.         perror ("fork");
  607.         kill_process ();
  608.         exit (1);
  609.     }
  610.     if (child_pid == 0)
  611.         exec_to_command (commandv);
  612.     }
  613.     fix_signal ();
  614.  
  615.     input_handler ();
  616. }
  617.  
  618. fix_signal ()
  619. {
  620.  
  621.     sighup = signal (SIGHUP, catchsig);
  622.     sigchld = signal (SIGCHLD, catchsig);
  623.     sigtstp = signal (SIGTSTP, SIG_IGN);    
  624. }
  625.  
  626. recover_signal ()
  627. {
  628.  
  629.     (void) signal (SIGHUP, sighup);
  630.     (void) signal (SIGCHLD, sigchld);
  631.     (void) signal (SIGTSTP, sigtstp);
  632. }
  633.  
  634. input_handler()
  635. {
  636.     char   *inputline;
  637.     char   *getline ();
  638.  
  639.     /*
  640.      * Get slave tty descriptor for auto-tty-fix
  641.      */
  642.     if ((slave = open (slave_tty, O_RDONLY)) < 0)
  643.     perror ("open");
  644.  
  645.     while (inputline = getline ()) {
  646.     register int nbyte = strlen (inputline);
  647.  
  648.     /*
  649.      * Write to master pty
  650.      */
  651.     write (master, inputline, nbyte);
  652.  
  653.     /*
  654.      * NOTE:
  655.      * Saving command line to output buffer is done in getline().
  656.      * Because inputline here is converted by alias.
  657.      */
  658.  
  659. #ifdef STAT
  660.     stat_ibyte += nbyte;
  661. #endif
  662.  
  663.     /*
  664.      * Write to script file.
  665.      */
  666.     if (Transparency == OFF && script_fp)
  667.         fwrite (inputline, sizeof(CHAR), strlen (inputline), script_fp);
  668.     }
  669.     terminate ();
  670. }
  671.  
  672. #define INPUT_BUFFER_SIZE 1024
  673.  
  674. #ifdef USE_TIMEOUT
  675. /*
  676.  * NOTE:
  677.  * Now these time mechanism is not used.
  678.  * Terminal status is get at every input from stdin.
  679.  */
  680. struct timeval timeout_0s    = {0L, 0L};
  681. struct timeval timeout_500ms    = {0L, 500000L};
  682. struct timeval timeout_1s    = {1L, 0L};
  683. struct timeval timeout_5s    = {5L, 0L};
  684. struct timeval timeout_10s    = {10L, 0L};
  685. struct timeval timeout_60s    = {60L, 0L};
  686.  
  687. #define TIMEOUT_IMMID        &timeout_500ms
  688. #define TIMEOUT_SOON        &timeout_1s
  689. #define TIMEOUT_SHORT        &timeout_5s
  690. #define TIMEOUT_MID        &timeout_10s
  691. #define TIMEOUT_LONG        &timeout_60s
  692. #define TIMEOUT_FOREVER        (struct timeval *)0
  693. #define TIMEOUT_NOBLOCK        &timeout_0s
  694.  
  695. struct timeval *timeout_list[] = {
  696.     TIMEOUT_IMMID,
  697.     TIMEOUT_SOON,
  698.     TIMEOUT_SHORT,
  699.     TIMEOUT_MID,
  700.     TIMEOUT_LONG,
  701.     TIMEOUT_FOREVER
  702. };
  703. #else
  704. struct timeval timeout_0s    = {0L, 0L};
  705. #define TIMEOUT_FOREVER        (struct timeval *)0
  706. #define TIMEOUT_NOBLOCK        &timeout_0s
  707. #endif
  708.  
  709. struct timeval *notimeout[] = {
  710.     TIMEOUT_FOREVER
  711. };
  712.  
  713. getcharacter()
  714. {
  715.     char c;
  716.     int n;
  717. /*
  718.     char buf[INPUT_BUFFER_SIZE];
  719. */
  720.     int nfound, readfd, writefd = 0, execptfd = 0;
  721. #ifdef USE_TIMEOUT
  722.     struct timeval **timeout = auto_tty_fix ? timeout_list : notimeout;
  723. #else
  724.     struct timeval **timeout = notimeout;
  725. #endif
  726.  
  727.  
  728.     /*
  729.      * Sorry, this cording depends to an implementation of getc().
  730.      */
  731. #   define CHAR_IN_BUFFER (stdin->_cnt)
  732.     if (CHAR_IN_BUFFER)
  733.     goto RETURNCHAR;
  734.  
  735. RETRY:
  736.     readfd = selectmask;
  737.  
  738. #ifdef STAT
  739.     stat_nselect++;
  740. #endif
  741.     if ((nfound = select (selectnfds, &readfd, 0, 0, *timeout)) < 0)
  742.     perror ("select");
  743.  
  744.     /*
  745.      * Found output from pty.
  746.      */
  747.     if (readfd & mastermask) {
  748.     int nbyte;
  749.  
  750.     /*
  751.      * Read from pty.
  752.      */
  753. /*
  754.     nbyte = read (master, buf, INPUT_BUFFER_SIZE);
  755. */
  756.     nbyte = buf_read (master, output_buffer);
  757.  
  758.     if (nbyte > 0) {
  759.         /*
  760.          * Write to stdout
  761.          */
  762. /*
  763.         write (1, buf, nbyte);
  764. */
  765.         write (1, output_buffer->last_buf, nbyte);
  766.  
  767.         /*
  768.          * Write to script file
  769.          */
  770.         if (script_fp)
  771. /*
  772.         fwrite (buf, sizeof(CHAR), nbyte, script_fp);
  773. */
  774.         fwrite (output_buffer->last_buf,
  775.             sizeof(CHAR), nbyte, script_fp);
  776.  
  777. #ifdef STAT
  778.         stat_obyte += nbyte;
  779. #endif
  780.     }
  781.     else if (nbyte < 0) {
  782.         perror ("read");
  783. #ifdef STAT
  784.         stat_rerror++;
  785. #endif
  786.     }
  787.     }
  788.  
  789.     /*
  790.      * Found input from terminal
  791.      */
  792.     if (CHAR_IN_BUFFER || readfd & stdinmask) {
  793.  
  794. #ifndef USE_TIMEOUT
  795.     /*
  796.      * Look slave tty mode before every input.
  797.      * This will be done only before real input from stdin, because
  798.      * if character remained in FILE buffer, control goes to RETURNCHAR
  799.      * label.
  800.      */
  801.         if (auto_tty_fix)
  802.         (void) fix_transparency ();
  803. #endif
  804.  
  805.     RETURNCHAR:
  806.     if ((c = getc (stdin)) == EOF) {
  807.         if (debug)
  808.         printf ("EOF chatched\n");
  809.         terminate ();
  810.     }
  811.     else
  812.         return (c & CHARMASK);
  813.     }
  814.  
  815. #ifdef USE_TIMEOUT
  816.     /*
  817.      * In the case of timeout.
  818.      */
  819.     if (nfound == 0) {
  820.  
  821.     /*
  822.      * Only to make sure
  823.      */
  824.         if (!auto_tty_fix) {
  825.         printf ("Timeout should not happen!!\n");
  826.         timeout = notimeout;
  827.         goto RETRY;
  828.     }
  829.  
  830.     (void) fix_transparency ();
  831.     ++timeout;
  832.  
  833.     if (debug)
  834.         errorBell();
  835.     }
  836. #endif
  837.  
  838.     goto RETRY;
  839. }
  840.  
  841. int buf_read (fd, bp)
  842.     int fd;            /* file discriptor */
  843.     BUFFER *bp;            /* buffer pointer */
  844. {
  845.     int nbyte;
  846.  
  847.     /*
  848.      * save previous next pointer
  849.      */
  850.     bp->last_buf = bp->buf + bp->next;
  851.  
  852.     /*
  853.      * read from fd as possible
  854.      */
  855.     nbyte = read (fd, bp->buf + bp->next, bp->b_max - bp->next);
  856.  
  857.     /*
  858.      * move next read pointer
  859.      */
  860.     bp->next += nbyte;
  861.  
  862.     /*
  863.      * If count has not reached high-water mark, increment count
  864.      * by read count, otherwise start pointer should be pushed by
  865.      * next pointer.
  866.      */
  867.     if (bp->count < bp->hiwater)
  868.     bp->count += nbyte;
  869.     else
  870.     bp->start += nbyte;
  871.     
  872.     /*
  873.      * If next pointer goes further than high-water mark, discard contents
  874.      * after next pointer, and move start and next pointer to buffer top.
  875.      */
  876.     if (bp->next > bp->hiwater) {
  877.     bp->count = bp->next;
  878.     bp->start = 0;
  879.     bp->next = 0;
  880.     }
  881.  
  882.     return (nbyte);
  883. }
  884.  
  885. buf_put (bp, s)
  886.     BUFFER *bp;            /* buffer pointer */
  887.     char *s;            /* string pointer */
  888. {
  889.     int nbyte;
  890.     int slen;
  891.  
  892.     nbyte = strlen (s);
  893.  
  894.     while (nbyte > 0) {
  895.  
  896.     slen = min (bp->b_max - bp->next, nbyte);
  897.     strncpy (bp->buf + bp->next, s, slen);
  898.     s += slen;
  899.     nbyte -= slen;
  900.     bp->next += slen;
  901.  
  902.     if (bp->count < bp->hiwater)
  903.         bp->count += slen;
  904.     else
  905.         bp->start += slen;
  906.  
  907.     if (bp->next > bp->hiwater) {
  908.         bp->count = bp->next;
  909.         bp->start = 0;
  910.         bp->next = 0;
  911.     }
  912.     }
  913. }
  914.  
  915. swallow_output()
  916. {
  917. /*
  918.     char buf[INPUT_BUFFER_SIZE];
  919. */
  920.     int readfd = mastermask;
  921.     int r;
  922.     int nbyte;
  923.     int ncount = 10;
  924.  
  925.     while (
  926.     ncount-- &&
  927.     select (selectnfds, &readfd, 0, 0, TIMEOUT_NOBLOCK) > 0 &&
  928.     readfd & mastermask
  929.     ) {
  930. /*
  931.     nbyte = read (master, buf, INPUT_BUFFER_SIZE);
  932. */
  933.     nbyte = buf_read (master, output_buffer);
  934.     if (nbyte > 0) {
  935. /*
  936.         write (1, buf, nbyte);
  937. */
  938.         write (1, output_buffer->last_buf, nbyte);
  939. #ifdef STAT
  940.         stat_obyte += nbyte;
  941.         stat_nselect++;
  942. #endif
  943.  
  944.         /*
  945.          * Write to script file
  946.          */
  947.         if (script_fp)
  948. /*
  949.         fwrite (buf, sizeof(CHAR), nbyte, script_fp);
  950. */
  951.         fwrite (output_buffer->last_buf,
  952.             sizeof(CHAR), nbyte, script_fp);
  953.     }
  954.     else if (nbyte < 0) {
  955.         perror ("read");
  956. #ifdef STAT
  957.         stat_rerror++;
  958. #endif
  959.     }
  960.     }
  961.     return;
  962. }
  963.  
  964. #include <sys/wait.h>
  965.  
  966. catchsig()
  967. {
  968.     union wait status;
  969.     struct rusage   ru;
  970.  
  971.     if (wait3 (&status.w_status, WNOHANG | WUNTRACED, &ru) != child_pid)
  972.     return;
  973.     if (WIFSTOPPED (status) /* || WIFSIGNALED (status) */) {
  974.     if (debug) {
  975.         message ("Child has sttoped!!\n");
  976.     }
  977.     suspend ();
  978.     return;
  979.     }
  980.     terminate ();
  981. }
  982.  
  983. exec_to_command(argv)
  984.     char *argv[];
  985. {
  986.     int t;
  987.  
  988.     /*
  989.      * Disconnect control terminal
  990.      */
  991.     t = open ("/dev/tty", 2);
  992.     if (t >= 0) {
  993.     ioctl (t, TIOCNOTTY, (char *) 0);
  994.     (void) close (t);
  995.     }
  996.  
  997.     get_pty_slave ();
  998.  
  999.     (void) close (master);
  1000.     dup2 (slave, 0);
  1001.     dup2 (slave, 1);
  1002.     dup2 (slave, 2);
  1003.     (void) close (slave);
  1004.  
  1005.     ioctl (0, TIOCSETN, (char *) & slave_ttymode);
  1006.  
  1007.     execvp (*argv, argv, 0);
  1008.     perror (*argv);
  1009.     exit (1);
  1010. }
  1011.  
  1012. fix_tty()
  1013. {
  1014.     struct tchars tcbuf;
  1015.     struct ltchars lcbuf;
  1016.  
  1017.     master_ttymode = initial_ttymode;
  1018.     slave_ttymode = initial_ttymode;
  1019.     tcbuf = tchars_buf;
  1020.     lcbuf = ltchars_buf;
  1021.  
  1022.     master_ttymode.sg_flags |= CBREAK;
  1023.     master_ttymode.sg_flags &= ~ECHO;
  1024.  
  1025.     slave_ttymode.sg_erase = -1;
  1026.     slave_ttymode.sg_kill = -1;
  1027.     slave_ttymode.sg_flags &= ~(ECHO|CRMOD);
  1028.  
  1029.     tcbuf.t_intrc = -1;
  1030.     tcbuf.t_quitc = -1;
  1031.     tcbuf.t_eofc = -1;
  1032.     tcbuf.t_brkc = -1;
  1033.  
  1034.     lcbuf.t_suspc = -1;
  1035.     lcbuf.t_dsuspc = -1;
  1036.     lcbuf.t_rprntc = -1;
  1037.     lcbuf.t_flushc = -1;
  1038.     lcbuf.t_werasc = -1;
  1039.     lcbuf.t_lnextc = -1;
  1040.  
  1041.     ioctl (0, TIOCSETN, (char *) & master_ttymode);
  1042.     ioctl (0, TIOCSETC, (char *) & tcbuf);
  1043.     ioctl (0, TIOCSLTC, (char *) & lcbuf);
  1044. }
  1045.  
  1046. kill_process()
  1047. {
  1048.  
  1049.     if (child_pid)
  1050.     (void) killpg (child_pid, SIGTERM);
  1051. }
  1052.  
  1053. terminate()
  1054. {
  1055.     extern int errno;
  1056.  
  1057.     /*
  1058.      * Save history if 'history-file' is set
  1059.      */
  1060.     {
  1061.     char *cp, *mk_home_relative(), *look_var();
  1062.     char buf [256];
  1063.     int num;
  1064.  
  1065.     if (look_var ("savehist") && (cp = look_var ("history-file"))) {
  1066.  
  1067.         num = lookd_var ("savehist");
  1068.         strcpy (buf, mk_home_relative (cp));
  1069.         save_history (buf, num);
  1070.     }
  1071.     }
  1072.  
  1073.     /*
  1074.      * If scripting, close script file.
  1075.      */
  1076.     if (script_fp)
  1077.     fclose (script_fp);
  1078.  
  1079.     (void) signal (SIGCHLD, SIG_IGN);
  1080.     if (killpg (child_pid, SIGTERM) < 0 && errno != ESRCH)
  1081.     if (killpg (child_pid, SIGHUP) < 0)
  1082.         if (killpg (child_pid, SIGKILL) < 0)
  1083.         perror ("kill");
  1084.  
  1085.     ioctl (0, TIOCSETN, (char *) & initial_ttymode);
  1086.     ioctl (0, TIOCSETC, (char *) & tchars_buf);
  1087.     ioctl (0, TIOCSLTC, (char *) & ltchars_buf);
  1088.     exit (0);
  1089. }
  1090.  
  1091. get_pty_master()
  1092. {
  1093.     char    c;
  1094.     struct stat stb;
  1095.     int     i;
  1096.  
  1097.     if (ptyflag == 0) {
  1098.     master = 1;
  1099.     return;
  1100.     }
  1101.     for (c = 'p'; c <= 's'; c++) {
  1102.     for (i = 0; i < 16; i++) {
  1103.         sprintf (master_tty, "/dev/pty%c%x", c, i);
  1104.         master = open (master_tty, O_RDWR);
  1105.         if (master >= 0) {
  1106.         sprintf (slave_tty, "/dev/tty%c%x", c, i);
  1107.         goto FOUND;
  1108.         }
  1109.     }
  1110.     }
  1111.  
  1112.     /*
  1113.      * Can't get master tty
  1114.      */
  1115.     if (master < 0) {
  1116.     fprintf (stderr, "Couldn't open pseudo tty\n");
  1117.     kill_process ();
  1118.     exit (1);
  1119.     }
  1120.  
  1121.  FOUND:
  1122.     ioctl (0, TIOCGETP, (char *) &initial_ttymode);
  1123.     ioctl (0, TIOCGETC, (char *) &tchars_buf);
  1124.     ioctl (0, TIOCGETD, (char *) &line_desc);
  1125.     ioctl (0, TIOCGLTC, (char *) <chars_buf);
  1126.     ioctl (0, TIOCLGET, (char *) &lmode_buf);
  1127.  
  1128. #ifdef TIOCGWINSZ
  1129.     {
  1130.     struct winsize win;
  1131.  
  1132.     if (ioctl (0, TIOCGWINSZ, &win) >= 0) {
  1133.         lines = win.ws_row;
  1134.         columns = win.ws_col;
  1135.     }
  1136.     }
  1137. #endif
  1138.  
  1139. #ifdef KANJI
  1140. # if defined(TIOCKGET) && defined(TIOCKSET)
  1141.     ioctl (0, TIOCKGET, (char *) &kmode_buf);
  1142. # endif
  1143. # if defined(TIOCKGETC) && defined(TIOCKSETC)
  1144.     ioctl (0, TIOCKGETC, (char *) &jtchars_buf);
  1145. # endif
  1146. #endif KANJI
  1147.  
  1148.     stdinmask = 1 << fileno (stdin);
  1149.     mastermask = 1 << master;
  1150.     selectmask = stdinmask | mastermask;
  1151.     selectnfds = max (fileno(stdin), master) + 1;
  1152.  
  1153.     return;
  1154. }
  1155.  
  1156. get_pty_slave()
  1157. {
  1158.  
  1159.     slave = open (slave_tty, 2);
  1160.     if (slave < 0) {
  1161.     perror (slave_tty);
  1162.     exit (1);
  1163.     }
  1164.     ioctl (slave, TIOCSETN, (char *) &initial_ttymode);
  1165.     ioctl (slave, TIOCSETC, (char *) &tchars_buf);
  1166.     ioctl (slave, TIOCSLTC, (char *) <chars_buf);
  1167.     ioctl (slave, TIOCLSET, (char *) &lmode_buf);
  1168.     ioctl (slave, TIOCSETD, (char *) &line_desc);
  1169.  
  1170. #ifdef KANJI
  1171. # if defined(TIOCKGET) && defined(TIOCKSET)
  1172.     ioctl (slave, TIOCKSET, (char *) &kmode_buf);
  1173. # endif
  1174. # if defined(TIOCKGETC) && defined(TIOCKSETC)
  1175.     ioctl (slave, TIOCKSETC, (char *) &jtchars_buf);
  1176. # endif
  1177. #endif KANJI
  1178.  
  1179. #ifdef TIOCSWINSZ
  1180.     {
  1181.     struct winsize win;
  1182.  
  1183.     win.ws_row = lines;
  1184.     win.ws_col = columns;
  1185.     (void) ioctl (slave, TIOCSWINSZ, &win);
  1186.     }
  1187. #endif
  1188. }
  1189.  
  1190. recover_tty()
  1191. {
  1192.  
  1193.     ioctl (0, TIOCSETN, (char *) & initial_ttymode);
  1194.     ioctl (0, TIOCSETC, (char *) & tchars_buf);
  1195.     ioctl (0, TIOCSLTC, (char *) & ltchars_buf);
  1196. }
  1197.  
  1198. suspend()
  1199. {
  1200.     long    pid;
  1201.     int        (*func) ();
  1202.     int        omask;
  1203.     extern int    errno;
  1204.  
  1205.     pid = getpid ();
  1206.  /* reset signal handler so kill below stops us */
  1207.     func = signal (SIGCHLD, SIG_IGN);
  1208.     signal (SIGTSTP, SIG_DFL);
  1209.     recover_tty();
  1210. #define    mask(s)    (1 << ((s)-1))
  1211.     omask = sigsetmask (sigblock (0) & ~mask (SIGTSTP));
  1212.     kill (0, SIGTSTP);
  1213.  
  1214.     if (kill (child_pid, SIGCONT) < 0 && errno == ESRCH) {
  1215.     printf ("Where my child has gone?!\n");
  1216.     terminate ();
  1217.     }
  1218.     killpg (child_pid, SIGCONT);
  1219.     kill (0, SIGCONT);
  1220.     signal (SIGCHLD, func);
  1221.     signal (SIGTSTP, SIG_IGN);
  1222.     sigblock (mask (SIGTSTP));
  1223.     fix_tty ();
  1224.     if (look_var ("auto-repaint"))
  1225.     fep_repaint(0);
  1226. }
  1227.  
  1228. look_cmdinfo (command)
  1229.     char *command;
  1230. {
  1231.     struct cmdinfo *p;
  1232.     char *allocAndCopyThere();
  1233.  
  1234.     if (strcmp (prompt, "") != 0)
  1235.     return;
  1236.  
  1237.     for (p = cmdinfo_tab; p->command; p++) {
  1238.     if (strcmp (command, p->command) == 0) {
  1239.         prompt = allocAndCopyThere (p->prompt);
  1240.         set_var ("prompt", p->prompt);
  1241.         set_var ("delimiters", p->delimiters);
  1242.         break;
  1243.     }
  1244.     }
  1245. }
  1246.  
  1247. usageAndExit()
  1248. {
  1249.  
  1250.     printf ("Usage: %s [-emacs|-vi] command\n", myself);
  1251.     exit (1);
  1252. }
  1253. \End\Of\File\
  1254. else
  1255.   echo "will not over write ./fep_main.c"
  1256. fi
  1257. echo "Finished archive 4 of 5"
  1258. exit
  1259.  
  1260.