home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 11 Util / 11-Util.zip / LESS177.ZIP / src / lsystem.c < prev    next >
C/C++ Source or Header  |  1992-07-18  |  7KB  |  345 lines

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