home *** CD-ROM | disk | FTP | other *** search
/ BCI NET 2 / BCI NET 2.iso / archives / utilities / text / less-278.lha / less-278 / src.lha / source / lsystem.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-02-01  |  6.2 KB  |  301 lines

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