home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Source Code 1993 July / THE_SOURCE_CODE_CD_ROM.iso / bsd_srcs / usr.bin / more / os.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-08-03  |  6.6 KB  |  284 lines

  1. /*
  2.  * Copyright (c) 1988 Mark Nudleman
  3.  * Copyright (c) 1988 Regents of the University of California.
  4.  * All rights reserved.
  5.  *
  6.  * Redistribution and use in source and binary forms, with or without
  7.  * modification, are permitted provided that the following conditions
  8.  * are met:
  9.  * 1. Redistributions of source code must retain the above copyright
  10.  *    notice, this list of conditions and the following disclaimer.
  11.  * 2. Redistributions in binary form must reproduce the above copyright
  12.  *    notice, this list of conditions and the following disclaimer in the
  13.  *    documentation and/or other materials provided with the distribution.
  14.  * 3. All advertising materials mentioning features or use of this software
  15.  *    must display the following acknowledgement:
  16.  *    This product includes software developed by the University of
  17.  *    California, Berkeley and its contributors.
  18.  * 4. Neither the name of the University nor the names of its contributors
  19.  *    may be used to endorse or promote products derived from this software
  20.  *    without specific prior written permission.
  21.  *
  22.  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  23.  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  24.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  25.  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  26.  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  27.  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  28.  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  29.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  30.  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  31.  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  32.  * SUCH DAMAGE.
  33.  */
  34.  
  35. #ifndef lint
  36. static char sccsid[] = "@(#)os.c    5.12 (Berkeley) 3/1/91";
  37. #endif /* not lint */
  38.  
  39. /*
  40.  * Operating system dependent routines.
  41.  *
  42.  * Most of the stuff in here is based on Unix, but an attempt
  43.  * has been made to make things work on other operating systems.
  44.  * This will sometimes result in a loss of functionality, unless
  45.  * someone rewrites code specifically for the new operating system.
  46.  *
  47.  * The makefile provides defines to decide whether various
  48.  * Unix features are present.
  49.  */
  50.  
  51. #include <sys/param.h>
  52. #include <sys/stat.h>
  53. #include <sys/file.h>
  54. #include <signal.h>
  55. #include <setjmp.h>
  56. #include <stdio.h>
  57. #include <less.h>
  58. #include "pathnames.h"
  59.  
  60. int reading;
  61.  
  62. extern int screen_trashed;
  63.  
  64. static jmp_buf read_label;
  65.  
  66. /*
  67.  * Pass the specified command to a shell to be executed.
  68.  * Like plain "system()", but handles resetting terminal modes, etc.
  69.  */
  70. lsystem(cmd)
  71.     char *cmd;
  72. {
  73.     int inp;
  74.     char cmdbuf[256];
  75.     char *shell, *getenv();
  76.  
  77.     /*
  78.      * Print the command which is to be executed,
  79.      * unless the command starts with a "-".
  80.      */
  81.     if (cmd[0] == '-')
  82.         cmd++;
  83.     else
  84.     {
  85.         lower_left();
  86.         clear_eol();
  87.         putstr("!");
  88.         putstr(cmd);
  89.         putstr("\n");
  90.     }
  91.  
  92.     /*
  93.      * De-initialize the terminal and take out of raw mode.
  94.      */
  95.     deinit();
  96.     flush();
  97.     raw_mode(0);
  98.  
  99.     /*
  100.      * Restore signals to their defaults.
  101.      */
  102.     init_signals(0);
  103.  
  104.     /*
  105.      * Force standard input to be the terminal, "/dev/tty",
  106.      * even if less's standard input is coming from a pipe.
  107.      */
  108.     inp = dup(0);
  109.     (void)close(0);
  110.     if (open(_PATH_TTY, O_RDONLY, 0) < 0)
  111.         (void)dup(inp);
  112.  
  113.     /*
  114.      * Pass the command to the system to be executed.
  115.      * If we have a SHELL environment variable, use
  116.      * <$SHELL -c "command"> instead of just <command>.
  117.      * If the command is empty, just invoke a shell.
  118.      */
  119.     if ((shell = getenv("SHELL")) != NULL && *shell != '\0')
  120.     {
  121.         if (*cmd == '\0')
  122.             cmd = shell;
  123.         else
  124.         {
  125.             (void)sprintf(cmdbuf, "%s -c \"%s\"", shell, cmd);
  126.             cmd = cmdbuf;
  127.         }
  128.     }
  129.     if (*cmd == '\0')
  130.         cmd = "sh";
  131.  
  132.     (void)system(cmd);
  133.  
  134.     /*
  135.      * Restore standard input, reset signals, raw mode, etc.
  136.      */
  137.     (void)close(0);
  138.     (void)dup(inp);
  139.     (void)close(inp);
  140.  
  141.     init_signals(1);
  142.     raw_mode(1);
  143.     init();
  144.     screen_trashed = 1;
  145. #if defined(SIGWINCH) || defined(SIGWIND)
  146.     /*
  147.      * Since we were ignoring window change signals while we executed
  148.      * the system command, we must assume the window changed.
  149.      */
  150.     winch();
  151. #endif
  152. }
  153.  
  154. /*
  155.  * Like read() system call, but is deliberately interruptable.
  156.  * A call to intread() from a signal handler will interrupt
  157.  * any pending iread().
  158.  */
  159. iread(fd, buf, len)
  160.     int fd;
  161.     char *buf;
  162.     int len;
  163. {
  164.     register int n;
  165.  
  166.     if (setjmp(read_label))
  167.         /*
  168.          * We jumped here from intread.
  169.          */
  170.         return (READ_INTR);
  171.  
  172.     flush();
  173.     reading = 1;
  174.     n = read(fd, buf, len);
  175.     reading = 0;
  176.     if (n < 0)
  177.         return (-1);
  178.     return (n);
  179. }
  180.  
  181. intread()
  182. {
  183.     (void)sigsetmask(0L);
  184.     longjmp(read_label, 1);
  185. }
  186.  
  187. /*
  188.  * Expand a filename, substituting any environment variables, etc.
  189.  * The implementation of this is necessarily very operating system
  190.  * dependent.  This implementation is unabashedly only for Unix systems.
  191.  */
  192. FILE *popen();
  193.  
  194. char *
  195. glob(filename)
  196.     char *filename;
  197. {
  198.     FILE *f;
  199.     char *p;
  200.     int ch;
  201.     char *cmd, *malloc(), *getenv();
  202.     static char buffer[MAXPATHLEN];
  203.  
  204.     if (filename[0] == '#')
  205.         return (filename);
  206.  
  207.     /*
  208.      * We get the shell to expand the filename for us by passing
  209.      * an "echo" command to the shell and reading its output.
  210.      */
  211.     p = getenv("SHELL");
  212.     if (p == NULL || *p == '\0')
  213.     {
  214.         /*
  215.          * Read the output of <echo filename>.
  216.          */
  217.         cmd = malloc((u_int)(strlen(filename)+8));
  218.         if (cmd == NULL)
  219.             return (filename);
  220.         (void)sprintf(cmd, "echo \"%s\"", filename);
  221.     } else
  222.     {
  223.         /*
  224.          * Read the output of <$SHELL -c "echo filename">.
  225.          */
  226.         cmd = malloc((u_int)(strlen(p)+12));
  227.         if (cmd == NULL)
  228.             return (filename);
  229.         (void)sprintf(cmd, "%s -c \"echo %s\"", p, filename);
  230.     }
  231.  
  232.     if ((f = popen(cmd, "r")) == NULL)
  233.         return (filename);
  234.     free(cmd);
  235.  
  236.     for (p = buffer;  p < &buffer[sizeof(buffer)-1];  p++)
  237.     {
  238.         if ((ch = getc(f)) == '\n' || ch == EOF)
  239.             break;
  240.         *p = ch;
  241.     }
  242.     *p = '\0';
  243.     (void)pclose(f);
  244.     return(buffer);
  245. }
  246.  
  247. char *
  248. bad_file(filename, message, len)
  249.     char *filename, *message;
  250.     u_int len;
  251. {
  252.     extern int errno;
  253.     struct stat statbuf;
  254.     char *strcat(), *strerror();
  255.  
  256.     if (stat(filename, &statbuf) < 0) {
  257.         (void)sprintf(message, "%s: %s", filename, strerror(errno));
  258.         return(message);
  259.     }
  260.     if ((statbuf.st_mode & S_IFMT) == S_IFDIR) {
  261.         static char is_dir[] = " is a directory";
  262.  
  263.         strtcpy(message, filename, (int)(len-sizeof(is_dir)-1));
  264.         (void)strcat(message, is_dir);
  265.         return(message);
  266.     }
  267.     return((char *)NULL);
  268. }
  269.  
  270. /*
  271.  * Copy a string, truncating to the specified length if necessary.
  272.  * Unlike strncpy(), the resulting string is guaranteed to be null-terminated.
  273.  */
  274. strtcpy(to, from, len)
  275.     char *to, *from;
  276.     int len;
  277. {
  278.     char *strncpy();
  279.  
  280.     (void)strncpy(to, from, (int)len);
  281.     to[len-1] = '\0';
  282. }
  283.  
  284.