home *** CD-ROM | disk | FTP | other *** search
/ The Pier Shareware 6 / The_Pier_Shareware_Number_6_(The_Pier_Exchange)_(1995).iso / 036 / less232.zip / LSYSTEM.C < prev    next >
C/C++ Source or Header  |  1994-09-24  |  7KB  |  325 lines

  1. /*
  2.  * Copyright (c) 1984,1985,1989,1994  Mark Nudelman
  3.  * All rights reserved.
  4.  *
  5.  * Redistribution and use in source and binary forms, with or without
  6.  * modification, are permitted provided that the following conditions
  7.  * are met:
  8.  * 1. Redistributions of source code must retain the above copyright
  9.  *    notice, this list of conditions and the following disclaimer.
  10.  * 2. Redistributions in binary form must reproduce the above copyright
  11.  *    notice in the documentation and/or other materials provided with 
  12.  *    the distribution.
  13.  *
  14.  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY
  15.  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  16.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 
  17.  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE
  18.  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 
  19.  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT 
  20.  * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 
  21.  * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
  22.  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 
  23.  * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN 
  24.  * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  25.  */
  26.  
  27.  
  28. /*
  29.  * Routines to execute other programs.
  30.  * Necessarily very OS dependent.
  31.  */
  32.  
  33. #include <signal.h>
  34. #include "less.h"
  35. #include "position.h"
  36.  
  37. #if HAVE_FCNTL_H
  38. #include <fcntl.h>
  39. #endif
  40. #if MSOFTC
  41. #include <dos.h>
  42. #endif
  43. #if OS2
  44. #include <process.h>
  45. #endif
  46.  
  47. extern int screen_trashed;
  48. extern IFILE curr_ifile;
  49.  
  50.  
  51. #if HAVE_SYSTEM
  52.  
  53. /*
  54.  * Pass the specified command to a shell to be executed.
  55.  * Like plain "system()", but handles resetting terminal modes, etc.
  56.  */
  57.     public void
  58. lsystem(cmd)
  59.     char *cmd;
  60. {
  61.     register int inp;
  62. #if MSOFTC || OS2
  63.     register int inp2;
  64. #endif
  65.     register char *shell;
  66.     register char *p;
  67.     IFILE save_ifile;
  68.  
  69.     /*
  70.      * Print the command which is to be executed,
  71.      * unless the command starts with a "-".
  72.      */
  73.     if (cmd[0] == '-')
  74.         cmd++;
  75.     else
  76.     {
  77.         clear_bot();
  78.         putstr("!");
  79.         putstr(cmd);
  80.         putstr("\n");
  81.     }
  82.  
  83.     /*
  84.      * Close the current input file.
  85.      */
  86.     save_ifile = curr_ifile;
  87.     (void) edit_ifile(NULL_IFILE);
  88.  
  89.     /*
  90.      * De-initialize the terminal and take out of raw mode.
  91.      */
  92.     deinit();
  93.     flush();    /* Make sure the deinit chars get out */
  94.     raw_mode(0);
  95.  
  96.     /*
  97.      * Restore signals to their defaults.
  98.      */
  99.     init_signals(0);
  100.  
  101.     /*
  102.      * Force standard input to be the user's terminal
  103.      * (the normal standard input), even if less's standard input 
  104.      * is coming from a pipe.
  105.      */
  106. #if MSOFTC || OS2
  107.     inp = dup(0);
  108.     inp2 = open("CON", O_TEXT|O_RDONLY);
  109.     dup2(0,inp2);
  110. #else
  111.     inp = dup(0);
  112.     close(0);
  113.     if (open("/dev/tty", 0) < 0)
  114.         dup(inp);
  115. #endif
  116.  
  117.     /*
  118.      * Pass the command to the system to be executed.
  119.      * If we have a SHELL environment variable, use
  120.      * <$SHELL -c "command"> instead of just <command>.
  121.      * If the command is empty, just invoke a shell.
  122.      */
  123. #if HAVE_SHELL
  124.     p = NULL;
  125.     if ((shell = getenv("SHELL")) != NULL && *shell != '\0')
  126.     {
  127.         if (*cmd == '\0')
  128.             p = save(shell);
  129.         else
  130.         {
  131.             p = (char *) ecalloc(strlen(shell) + strlen(cmd) + 7, 
  132.                     sizeof(char));
  133.             sprintf(p, "%s -c \"%s\"", shell, cmd);
  134.         }
  135.     }
  136.     if (p == NULL)
  137.     {
  138.         if (*cmd == '\0')
  139.             p = save("sh");
  140.         else
  141.             p = save(cmd);
  142.     }
  143.  
  144.     system(p);
  145.     free(p);
  146. #else
  147. #if OS2
  148.         if ( *cmd == 0 )
  149.         {
  150.           if ( (p = getenv("COMSPEC")) == NULL )
  151.             p = "cmd.exe";
  152.  
  153.           spawnlp(P_WAIT, p, p, NULL);
  154.         }
  155.         else
  156. #endif
  157.     system(cmd);
  158. #endif
  159.  
  160.     /*
  161.      * Restore standard input, reset signals, raw mode, etc.
  162.      */
  163. #if MSOFTC || OS2
  164.     close(inp2);
  165.     dup2(0,inp);
  166.     close(inp);
  167. #else
  168.     close(0);
  169.     dup(inp);
  170.     close(inp);
  171. #endif
  172.  
  173.     init_signals(1);
  174.     raw_mode(1);
  175.     init();
  176.     screen_trashed = 1;
  177.  
  178.     /*
  179.      * Reopen the current input file.
  180.      */
  181.     if (edit_ifile(save_ifile))
  182.         quit(-1);
  183.  
  184. #if defined(SIGWINCH) || defined(SIGWIND)
  185.     /*
  186.      * Since we were ignoring window change signals while we executed
  187.      * the system command, we must assume the window changed.
  188.      * Warning: this leaves a signal pending (in "sigs"),
  189.      * so psignals() should be called soon after lsystem().
  190.      */
  191.     winch(0);
  192. #endif
  193. }
  194.  
  195. #endif
  196.  
  197. #if PIPEC
  198.  
  199. /*
  200.  * Pipe a section of the input file into the given shell command.
  201.  * The section to be piped is the section "between" the current
  202.  * position and the position marked by the given letter.
  203.  *
  204.  * The "current" position means the top line displayed if the mark
  205.  * is after the current screen, or the bottom line displayed if
  206.  * the mark is before the current screen.
  207.  * If the mark is on the current screen, the whole screen is displayed.
  208.  */
  209.     public int
  210. pipe_mark(c, cmd)
  211.     int c;
  212.     char *cmd;
  213. {
  214.     POSITION mpos, tpos, bpos;
  215.  
  216.     /*
  217.      * mpos = the marked position.
  218.      * tpos = top of screen.
  219.      * bpos = bottom of screen.
  220.      */
  221.     mpos = markpos(c);
  222.     if (mpos == NULL_POSITION)
  223.         return (-1);
  224.     tpos = position(TOP);
  225.     if (tpos == NULL_POSITION)
  226.         tpos = ch_zero();
  227.     bpos = position(BOTTOM);
  228.  
  229.      if (c == '.') 
  230.          return (pipe_data(cmd, tpos, bpos));
  231.      else if (mpos <= tpos)
  232.          return (pipe_data(cmd, mpos, tpos));
  233.      else if (bpos == NULL_POSITION)
  234.          return (pipe_data(cmd, tpos, bpos));
  235.      else
  236.          return (pipe_data(cmd, tpos, mpos));
  237. }
  238.  
  239. /*
  240.  * Create a pipe to the given shell command.
  241.  * Feed it the file contents between the positions spos and epos.
  242.  */
  243.     public int
  244. pipe_data(cmd, spos, epos)
  245.     char *cmd;
  246.     POSITION spos;
  247.     POSITION epos;
  248. {
  249.     register FILE *f;
  250.     register int c;
  251.     extern FILE *popen();
  252.  
  253.     /*
  254.      * This is structured much like lsystem().
  255.      * Since we're running a shell program, we must be careful
  256.      * to perform the necessary deinitialization before running
  257.      * the command, and reinitialization after it.
  258.      */
  259.     if (ch_seek(spos) != 0)
  260.     {
  261.         error("Cannot seek to start position", NULL_PARG);
  262.         return (-1);
  263.     }
  264.  
  265.     if ((f = popen(cmd, "w")) == NULL)
  266.     {
  267.         error("Cannot create pipe", NULL_PARG);
  268.         return (-1);
  269.     }
  270.     clear_bot();
  271.     putstr("!");
  272.     putstr(cmd);
  273.     putstr("\n");
  274.  
  275.     deinit();
  276.     flush();
  277.     raw_mode(0);
  278.     init_signals(0);
  279. #ifdef SIGPIPE
  280.     SIGNAL(SIGPIPE, SIG_IGN);
  281. #endif
  282.  
  283.     c = EOI;
  284.     while (epos == NULL_POSITION || spos++ <= epos)
  285.     {
  286.         /*
  287.          * Read a character from the file and give it to the pipe.
  288.          */
  289.         c = ch_forw_get();
  290.         if (c == EOI)
  291.             break;
  292.         if (putc(c, f) == EOF)
  293.             break;
  294.     }
  295.  
  296.     /*
  297.      * Finish up the last line.
  298.      */
  299.      while (c != '\n' && c != EOI ) 
  300.      {
  301.          c = ch_forw_get();
  302.          if (c == EOI)
  303.              break;
  304.          if (putc(c, f) == EOF)
  305.              break;
  306.      }
  307.  
  308.     pclose(f);
  309.  
  310. #ifdef SIGPIPE
  311.     SIGNAL(SIGPIPE, SIG_DFL);
  312. #endif
  313.     init_signals(1);
  314.     raw_mode(1);
  315.     init();
  316.     screen_trashed = 1;
  317. #if defined(SIGWINCH) || defined(SIGWIND)
  318.     /* {{ Probably don't need this here. }} */
  319.     winch(0);
  320. #endif
  321.     return (0);
  322. }
  323.  
  324. #endif
  325.