home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1992 March / Source_Code_CD-ROM_Walnut_Creek_March_1992.iso / usenet / altsrcs / 2 / 2995 / lsystem.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-03-06  |  5.1 KB  |  285 lines

  1. /*
  2.  * Routines to execute other programs.
  3.  * Necessarily very OS dependent.
  4.  */
  5.  
  6. #include <stdio.h>
  7. #include <signal.h>
  8.  
  9. #include "less.h"
  10. #include "position.h"
  11.  
  12. #if __MSDOS__
  13. #include <process.h>
  14. #include <dos.h>
  15. #include <fcntl.h>
  16. #include <io.h>
  17. #include <errno.h>
  18. #include <dir.h>
  19. #include <string.h>
  20. #include <stdlib.h>
  21. #include <time.h>
  22. #include <ctype.h>
  23. char get_swchar();
  24. void swchar_to_dos();
  25. void swchar_to_unix();
  26. #endif
  27.  
  28. extern char *getenv();
  29.  
  30. extern int screen_trashed;
  31. extern IFILE curr_ifile;
  32.  
  33.  
  34. /*
  35.  * Pass the specified command to a shell to be executed.
  36.  * Like plain "system()", but handles resetting terminal modes, etc.
  37.  */
  38.     public void
  39. lsystem(cmd)
  40.     char *cmd;
  41. {
  42.     register int inp;
  43.     register char *shell;
  44.     register char *p;
  45.     register char *curr_filename;
  46.  
  47.     /*
  48.      * Print the command which is to be executed,
  49.      * unless the command starts with a "-".
  50.      */
  51.     if (cmd[0] == '-')
  52.         cmd++;
  53.     else
  54.     {
  55.         lower_left();
  56.         clear_eol();
  57.         putstr("!");
  58.         putstr(cmd);
  59.         putstr("\n");
  60.     }
  61.  
  62.     /*
  63.      * Close the current input file.
  64.      */
  65.     curr_filename = get_filename(curr_ifile);
  66.     (void) edit(NULL, 0);
  67.  
  68.     /*
  69.      * De-initialize the terminal and take out of raw mode.
  70.      */
  71.     deinit();
  72.     flush();    /* Make sure the deinit chars get out */
  73.     raw_mode(0);
  74.  
  75.     /*
  76.      * Restore signals to their defaults.
  77.      */
  78.     init_signals(0);
  79.  
  80.     /*
  81.      * Force standard input to be the user's terminal
  82.      * (the normal standard input), even if less's standard input 
  83.      * is coming from a pipe.
  84.      */
  85. #if __MSDOS__
  86. {
  87.     register int inp2;
  88.  
  89.     inp = dup(0);
  90.     inp2 = open("CON", O_TEXT|O_RDONLY);
  91.     dup2(0,inp2);
  92. }
  93. #else
  94.     inp = dup(0);
  95.     close(0);
  96.     if (open("/dev/tty", 0) < 0)
  97.         dup(inp);
  98. #endif
  99.  
  100.     /*
  101.      * Pass the command to the system to be executed.
  102.      * If we have a SHELL environment variable, use
  103.      * <$SHELL -c "command"> instead of just <command>.
  104.      * If the command is empty, just invoke a shell.
  105.      */
  106. #if __MSDOS__
  107. {
  108.     int result;
  109.     char sw_char;
  110.  
  111.     sw_char = get_swchar();
  112.     swchar_to_dos();
  113.     result = system(cmd);
  114.     if (result != 0)
  115.         perror("less");
  116.     if (sw_char == '-')
  117.         swchar_to_unix();
  118. }
  119. #else
  120.     p = NULL;
  121.     if ((shell = getenv("SHELL")) != NULL && *shell != '\0')
  122.     {
  123.         if (*cmd == '\0')
  124.             p = save(shell);
  125.         else
  126.         {
  127.             p = (char *) ecalloc(strlen(shell) + strlen(cmd) + 7, 
  128.                     sizeof(char));
  129.             sprintf(p, "%s -c \"%s\"", shell, cmd);
  130.         }
  131.     }
  132.     if (p == NULL)
  133.     {
  134.         if (*cmd == '\0')
  135.             p = save("sh");
  136.         else
  137.             p = save(cmd);
  138.     }
  139.  
  140.     system(p);
  141.     free(p);
  142. #endif
  143.  
  144.     /*
  145.      * Restore standard input, reset signals, raw mode, etc.
  146.      */
  147. #if __MSDOS__
  148.     close(inp2);
  149.     dup2(0,inp);
  150.     close(inp);
  151. #else
  152.     close(0);
  153.     dup(inp);
  154.     close(inp);
  155. #endif
  156.  
  157.     init_signals(1);
  158.     raw_mode(1);
  159.     init();
  160.     screen_trashed = 1;
  161.  
  162.     /*
  163.      * Reopen the current input file.
  164.      */
  165.     (void) edit(curr_filename, 0);
  166.  
  167. #if defined(SIGWINCH) || defined(SIGWIND)
  168.     /*
  169.      * Since we were ignoring window change signals while we executed
  170.      * the system command, we must assume the window changed.
  171.      * Warning: this leaves a signal pending (in "sigs"),
  172.      * so psignals() should be called soon after lsystem().
  173.      */
  174.     winch();
  175. #endif
  176. }
  177.  
  178. #if PIPEC
  179.  
  180. /*
  181.  * Pipe a section of the input file into the given shell command.
  182.  * The section to be piped is the section "between" the current
  183.  * position and the position marked by the given letter.
  184.  *
  185.  * The "current" position means the top line displayed if the mark
  186.  * is after the current screen, or the bottom line displayed if
  187.  * the mark is before the current screen.
  188.  * If the mark is on the current screen, the whole screen is displayed.
  189.  */
  190.     public int
  191. pipe_mark(c, cmd)
  192.     int c;
  193.     char *cmd;
  194. {
  195.     POSITION mpos, tpos, bpos;
  196.  
  197.     /*
  198.      * mpos = the marked position.
  199.      * tpos = top of screen.
  200.      * bpos = bottom of screen.
  201.      */
  202.     mpos = markpos(c);
  203.     if (mpos == NULL_POSITION)
  204.         return (-1);
  205.     tpos = position(TOP);
  206.     if (tpos == NULL_POSITION)
  207.         tpos = ch_zero();
  208.     bpos = position(BOTTOM_PLUS_ONE);
  209.  
  210.     if (mpos <= tpos)
  211.         return (pipe_data(cmd, mpos, bpos));
  212.     else if (bpos == NULL_POSITION || mpos <= bpos)
  213.         return (pipe_data(cmd, tpos, bpos));
  214.     else
  215.         return (pipe_data(cmd, tpos, mpos));
  216. }
  217.  
  218. /*
  219.  * Create a pipe to the given shell command.
  220.  * Feed it the file contents between the positions spos and epos.
  221.  */
  222.     public int
  223. pipe_data(cmd, spos, epos)
  224.     char *cmd;
  225.     POSITION spos;
  226.     POSITION epos;
  227. {
  228.     register FILE *f;
  229.     register int c;
  230.     int inp;
  231.     extern FILE *popen();
  232.  
  233.     /*
  234.      * This is structured much like lsystem().
  235.      * Since we're running a shell program, we must be careful
  236.      * to perform the necessary deinitialization before running
  237.      * the command, and reinitialization after it.
  238.      */
  239.     if (ch_seek(spos) != 0)
  240.     {
  241.         error("Cannot seek to start position", NULL_PARG);
  242.         return (-1);
  243.     }
  244.  
  245.     if ((f = popen(cmd, "w")) == NULL)
  246.     {
  247.         error("Cannot create pipe", NULL_PARG);
  248.         return (-1);
  249.     }
  250.     lower_left();
  251.     clear_eol();
  252.     putstr("!");
  253.     putstr(cmd);
  254.     putstr("\n");
  255.  
  256.     deinit();
  257.     flush();
  258.     raw_mode(0);
  259.     init_signals(0);
  260.  
  261.     while (epos == NULL_POSITION || spos++ < epos)
  262.     {
  263.         /*
  264.          * Read a character from the file and give it to the pipe.
  265.          */
  266.         c = ch_forw_get();
  267.         if (c == EOI)
  268.             break;
  269.         putc(c, f);
  270.     }
  271.     pclose(f);
  272.  
  273.     init_signals(1);
  274.     raw_mode(1);
  275.     init();
  276.     screen_trashed = 1;
  277. #if defined(SIGWINCH) || defined(SIGWIND)
  278.     /* {{ Probably don't need this here. }} */
  279.     winch();
  280. #endif
  281.     return (0);
  282. }
  283.  
  284. #endif
  285.