home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / unix / volume16 / less5 / part02 / os.c < prev    next >
Encoding:
C/C++ Source or Header  |  1988-09-22  |  5.8 KB  |  339 lines

  1. /*
  2.  * Operating system dependent routines.
  3.  *
  4.  * Most of the stuff in here is based on Unix, but an attempt
  5.  * has been made to make things work on other operating systems.
  6.  * This will sometimes result in a loss of functionality, unless
  7.  * someone rewrites code specifically for the new operating system.
  8.  *
  9.  * The makefile provides defines to decide whether various
  10.  * Unix features are present.
  11.  */
  12.  
  13. #include <stdio.h>
  14. #include <signal.h>
  15. #include <setjmp.h>
  16. #include "less.h"
  17.  
  18. char *getenv();
  19.  
  20. public int reading;
  21.  
  22. extern int screen_trashed;
  23.  
  24. static jmp_buf read_label;
  25.  
  26. /*
  27.  * Pass the specified command to a shell to be executed.
  28.  * Like plain "system()", but handles resetting terminal modes, etc.
  29.  */
  30.     public void
  31. lsystem(cmd)
  32.     char *cmd;
  33. {
  34.     int inp;
  35.     char cmdbuf[256];
  36.     char *shell;
  37.  
  38.     /*
  39.      * Print the command which is to be executed,
  40.      * unless the command starts with a "-".
  41.      */
  42.     if (cmd[0] == '-')
  43.         cmd++;
  44.     else
  45.     {
  46.         lower_left();
  47.         clear_eol();
  48.         putstr("!");
  49.         putstr(cmd);
  50.         putstr("\n");
  51.     }
  52.  
  53.     /*
  54.      * De-initialize the terminal and take out of raw mode.
  55.      */
  56.     deinit();
  57.     flush();
  58.     raw_mode(0);
  59.  
  60.     /*
  61.      * Restore signals to their defaults.
  62.      */
  63.     init_signals(0);
  64.  
  65.     /*
  66.      * Force standard input to be the terminal, "/dev/tty",
  67.      * even if less's standard input is coming from a pipe.
  68.      */
  69.     inp = dup(0);
  70.     close(0);
  71.     if (open("/dev/tty", 0) < 0)
  72.         dup(inp);
  73.  
  74.     /*
  75.      * Pass the command to the system to be executed.
  76.      * If we have a SHELL environment variable, use
  77.      * <$SHELL -c "command"> instead of just <command>.
  78.      * If the command is empty, just invoke a shell.
  79.      */
  80.     if ((shell = getenv("SHELL")) != NULL && *shell != '\0')
  81.     {
  82.         if (*cmd == '\0')
  83.             cmd = shell;
  84.         else
  85.         {
  86.             sprintf(cmdbuf, "%s -c \"%s\"", shell, cmd);
  87.             cmd = cmdbuf;
  88.         }
  89.     }
  90.     if (*cmd == '\0')
  91.         cmd = "sh";
  92.  
  93.     system(cmd);
  94.  
  95.     /*
  96.      * Restore standard input, reset signals, raw mode, etc.
  97.      */
  98.     close(0);
  99.     dup(inp);
  100.     close(inp);
  101.  
  102.     init_signals(1);
  103.     raw_mode(1);
  104.     init();
  105.     screen_trashed = 1;
  106. #if defined(SIGWINCH) || defined(SIGWIND)
  107.     /*
  108.      * Since we were ignoring window change signals while we executed
  109.      * the system command, we must assume the window changed.
  110.      */
  111.     winch();
  112. #endif
  113. }
  114.  
  115. /*
  116.  * Like read() system call, but is deliberately interruptable.
  117.  * A call to intread() from a signal handler will interrupt
  118.  * any pending iread().
  119.  */
  120.     public int
  121. iread(fd, buf, len)
  122.     int fd;
  123.     char *buf;
  124.     int len;
  125. {
  126.     register int n;
  127.  
  128.     if (setjmp(read_label))
  129.         /*
  130.          * We jumped here from intread.
  131.          */
  132.         return (READ_INTR);
  133.  
  134.     flush();
  135.     reading = 1;
  136.     n = read(fd, buf, len);
  137.     reading = 0;
  138.     if (n < 0)
  139.         return (-1);
  140.     return (n);
  141. }
  142.  
  143.     public void
  144. intread()
  145. {
  146. #if SIGSETMASK
  147.     sigsetmask(0);
  148. #endif
  149.     longjmp(read_label, 1);
  150. }
  151.  
  152. #if GET_TIME
  153.     public long
  154. get_time()
  155. {
  156.     long t;
  157.  
  158.     time(&t);
  159.     return (t);
  160. }
  161. #endif
  162.  
  163. /*
  164.  * Expand a filename, substituting any environment variables, etc.
  165.  * The implementation of this is necessarily very operating system
  166.  * dependent.  This implementation is unabashedly only for Unix systems.
  167.  */
  168. #if GLOB
  169.  
  170. FILE *popen();
  171.  
  172.     public char *
  173. glob(filename)
  174.     char *filename;
  175. {
  176.     FILE *f;
  177.     char *p;
  178.     int ch;
  179.     char *cmd;
  180.     static char buffer[FILENAME];
  181.  
  182.     if (filename[0] == '#')
  183.         return (filename);
  184.  
  185.     /*
  186.      * We get the shell to expand the filename for us by passing
  187.      * an "echo" command to the shell and reading its output.
  188.      */
  189.     p = getenv("SHELL");
  190.     if (p == NULL || *p == '\0')
  191.     {
  192.         /*
  193.          * Read the output of <echo filename>.
  194.          */
  195.         cmd = calloc(strlen(filename)+8, sizeof(char));
  196.         if (cmd == NULL)
  197.             return (filename);
  198.         sprintf(cmd, "echo \"%s\"", filename);
  199.     } else
  200.     {
  201.         /*
  202.          * Read the output of <$SHELL -c "echo filename">.
  203.          */
  204.         cmd = calloc(strlen(p)+12);
  205.         if (cmd == NULL)
  206.             return (filename);
  207.         sprintf(cmd, "%s -c \"echo %s\"", p, filename);
  208.     }
  209.  
  210.     if ((f = popen(cmd, "r")) == NULL)
  211.         return (filename);
  212.     free(cmd);
  213.  
  214.     for (p = buffer;  p < &buffer[sizeof(buffer)-1];  p++)
  215.     {
  216.         if ((ch = getc(f)) == '\n' || ch == EOF)
  217.             break;
  218.         *p = ch;
  219.     }
  220.     *p = '\0';
  221.     pclose(f);
  222.     return (buffer);
  223. }
  224.  
  225. #else
  226.  
  227.     public char *
  228. glob(filename)
  229.     char *filename;
  230. {
  231.     return (filename);
  232. }
  233.  
  234. #endif
  235.  
  236.  
  237. /*
  238.  * Returns NULL if the file can be opened and
  239.  * is an ordinary file, otherwise an error message
  240.  * (if it cannot be opened or is a directory, etc.)
  241.  */
  242.  
  243. #if STAT
  244.  
  245. #include <sys/types.h>
  246. #include <sys/stat.h>
  247.  
  248.     public char *
  249. bad_file(filename, message, len)
  250.     char *filename;
  251.     char *message;
  252.     unsigned int len;
  253. {
  254.     struct stat statbuf;
  255.  
  256.     if (stat(filename, &statbuf) < 0)
  257.         return (errno_message(filename, message, len));
  258.  
  259.     if ((statbuf.st_mode & S_IFMT) == S_IFDIR)
  260.     {
  261.         static char is_dir[] = " is a directory";
  262.         strtcpy(message, filename, len-sizeof(is_dir)-1);
  263.         strcat(message, is_dir);
  264.         return (message);
  265.     }
  266.     if ((statbuf.st_mode & S_IFMT) != S_IFREG)
  267.     {
  268.         static char not_reg[] = " is not a regular file";
  269.         strtcpy(message, filename, len-sizeof(not_reg)-1);
  270.         strcat(message, not_reg);
  271.         return (message);
  272.     }
  273.     return (NULL);
  274. }
  275.  
  276. #else
  277.  
  278.     public char *
  279. bad_file(filename, message, len)
  280.     char *filename;
  281.     char *message;
  282.     unsigned int len;
  283. {
  284.     return (NULL);
  285. }
  286.  
  287. #endif
  288.  
  289. /*
  290.  * errno_message: Return an error message based on the value of "errno".
  291.  * okreadfail: Return true if the previous failure of a read
  292.  *    (on the input tty) should be considered ok.
  293.  */
  294.  
  295. #if PERROR
  296.  
  297. extern char *sys_errlist[];
  298. extern int sys_nerr;
  299. extern int errno;
  300.  
  301.     public char *
  302. errno_message(filename, message, len)
  303.     char *filename;
  304.     char *message;
  305.     unsigned int len;
  306. {
  307.     char *p;
  308.     char msg[16];
  309.  
  310.     if (errno < sys_nerr)
  311.         p = sys_errlist[errno];
  312.     else
  313.     {
  314.         sprintf(msg, "Error %d", errno);
  315.         p = msg;
  316.     }
  317.     strtcpy(message, filename, len-strlen(p)-3);
  318.     strcat(message, ": ");
  319.     strcat(message, p);
  320.     return (message);
  321. }
  322.  
  323. #else
  324.  
  325.     public char *
  326. errno_message(filename, message, len)
  327.     char *filename;
  328.     char *message;
  329.     unsigned int len;
  330. {
  331.     static char msg[] = ": cannot open";
  332.  
  333.     strtcpy(message, filename, len-sizeof(msg)-1);
  334.     strcat(message, msg);
  335.     return (message);
  336. }
  337.  
  338. #endif
  339.