home *** CD-ROM | disk | FTP | other *** search
/ Fresh Fish 1 / FFMCD01.bin / bbs / libdisks / d700t799 / disk718.lha / Less / less-177 / src.lha / src / lsystem.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-04-16  |  5.6 KB  |  311 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.             shell=(char *)strdup(shell);
  124.         if (*cmd == '\0')
  125.             p = save(shell);
  126.         else
  127.         {
  128.             p = (char *) ecalloc(strlen(shell) + strlen(cmd) + 7, 
  129.                     sizeof(char));
  130. #if __AMIGA            
  131.             sprintf(p, "%s -C %s", shell, cmd);
  132. #else
  133.             sprintf(p, "%s -c \"%s\"", shell, cmd);
  134. #endif
  135.         }
  136.     }
  137.     if (p == NULL)
  138.     {
  139.         if (*cmd == '\0')
  140.             p = save("sh");
  141.         else
  142.             p = save(cmd);
  143.     }
  144.  
  145.     system(p);
  146.     free(p);
  147. #endif
  148.  
  149.     /*
  150.      * Restore standard input, reset signals, raw mode, etc.
  151.      */
  152. #if __MSDOS__
  153.     close(inp2);
  154.     dup2(0,inp);
  155.     close(inp);
  156. #else
  157.     close(0);
  158.     dup(inp);
  159.     close(inp);
  160. #endif
  161.  
  162.     init_signals(1);
  163.     raw_mode(1);
  164.     init();
  165.     screen_trashed = 1;
  166.  
  167.     /*
  168.      * Reopen the current input file.
  169.      */
  170.     (void) edit(curr_filename, 0);
  171.  
  172. #if defined(SIGWINCH) || defined(SIGWIND)
  173.     /*
  174.      * Since we were ignoring window change signals while we executed
  175.      * the system command, we must assume the window changed.
  176.      * Warning: this leaves a signal pending (in "sigs"),
  177.      * so psignals() should be called soon after lsystem().
  178.      */
  179.     winch();
  180. #endif
  181. }
  182.  
  183. #if PIPEC
  184.  
  185. /*
  186.  * Pipe a section of the input file into the given shell command.
  187.  * The section to be piped is the section "between" the current
  188.  * position and the position marked by the given letter.
  189.  *
  190.  * The "current" position means the top line displayed if the mark
  191.  * is after the current screen, or the bottom line displayed if
  192.  * the mark is before the current screen.
  193.  * If the mark is on the current screen, the whole screen is displayed.
  194.  */
  195.     public int
  196. pipe_mark(c, cmd)
  197.     int c;
  198.     char *cmd;
  199. {
  200.     POSITION mpos, tpos, bpos;
  201.  
  202.     /*
  203.      * mpos = the marked position.
  204.      * tpos = top of screen.
  205.      * bpos = bottom of screen.
  206.      */
  207.     mpos = markpos(c);
  208.     if (mpos == NULL_POSITION)
  209.         return (-1);
  210.     tpos = position(TOP);
  211.     if (tpos == NULL_POSITION)
  212.         tpos = ch_zero();
  213.     bpos = position(BOTTOM);
  214.  
  215.      if (c == '.') 
  216.          return (pipe_data(cmd, tpos, bpos));
  217.      else if (mpos <= tpos)
  218.          return (pipe_data(cmd, mpos, tpos));
  219.      else if (bpos == NULL_POSITION)
  220.          return (pipe_data(cmd, tpos, bpos));
  221.      else
  222.          return (pipe_data(cmd, tpos, mpos));
  223. }
  224.  
  225. /*
  226.  * Create a pipe to the given shell command.
  227.  * Feed it the file contents between the positions spos and epos.
  228.  */
  229.     public int
  230. pipe_data(cmd, spos, epos)
  231.     char *cmd;
  232.     POSITION spos;
  233.     POSITION epos;
  234. {
  235.     register FILE *f;
  236.     register int c;
  237.     extern FILE *popen();
  238.  
  239.     /*
  240.      * This is structured much like lsystem().
  241.      * Since we're running a shell program, we must be careful
  242.      * to perform the necessary deinitialization before running
  243.      * the command, and reinitialization after it.
  244.      */
  245.     if (ch_seek(spos) != 0)
  246.     {
  247.         error("Cannot seek to start position", NULL_PARG);
  248.         return (-1);
  249.     }
  250.  
  251.     if ((f = popen(cmd, "w")) == NULL)
  252.     {
  253.         error("Cannot create pipe", NULL_PARG);
  254.         return (-1);
  255.     }
  256.     lower_left();
  257.     clear_eol();
  258.     putstr("!");
  259.     putstr(cmd);
  260.     putstr("\n");
  261.  
  262.     deinit();
  263.     flush();
  264.     raw_mode(0);
  265.     init_signals(0);
  266. #ifdef SIGPIPE
  267.     SIGNAL(SIGPIPE, SIG_IGN);
  268. #endif
  269.  
  270.     while (epos == NULL_POSITION || spos++ <= epos)
  271.     {
  272.         /*
  273.          * Read a character from the file and give it to the pipe.
  274.          */
  275.         c = ch_forw_get();
  276.         if (c == EOI)
  277.             break;
  278.         if (putc(c, f) == EOF)
  279.             break;
  280.     }
  281.  
  282.     /*
  283.      * Finish up the last line.
  284.      */
  285.      while (c != '\n' && c != EOI ) 
  286.      {
  287.          c = ch_forw_get();
  288.          if (c == EOI)
  289.              break;
  290.          if (putc(c, f) == EOF)
  291.              break;
  292.      }
  293.  
  294.     pclose(f);
  295.  
  296. #ifdef SIGPIPE
  297.     SIGNAL(SIGPIPE, SIG_DFL);
  298. #endif
  299.     init_signals(1);
  300.     raw_mode(1);
  301.     init();
  302.     screen_trashed = 1;
  303. #if defined(SIGWINCH) || defined(SIGWIND)
  304.     /* {{ Probably don't need this here. }} */
  305.     winch();
  306. #endif
  307.     return (0);
  308. }
  309.  
  310. #endif
  311.