Logo Search packages:      
Sourcecode: sash version File versions

sash.c

/*
 * Copyright (c) 2004 by David I. Bell
 * Permission is granted to use, distribute, or modify this source,
 * provided that this copyright notice remains intact.
 *
 * Stand-alone shell for system maintainance for Linux.
 * This program should NOT be built using shared libraries.
 */

#include <sys/types.h>
#include <sys/wait.h>
#include <signal.h>
#include <errno.h>

#include "sash.h"


static const char * const     version = "3.7";


/*
 * The special maximum argument value which means that there is
 * no limit to the number of arguments on the command line.
 */
#define     INFINITE_ARGS     0x7fffffff


/*
 * One entry of the command table.
 */
typedef struct
{
      const char *      name;
      void        (*func)(int argc, const char ** argv);
      int         minArgs;
      int         maxArgs;
      const char *      description;
      const char *      usage;
} CommandEntry;


/*
 * The table of built-in commands.
 * This is terminated wih an entry containing NULL values.
 */
static const CommandEntry     commandEntryTable[] =
{
      {
            "alias",    do_alias,   1,    INFINITE_ARGS,
            "Define a command alias",
            "[name [command]]"
      },

      {
            "aliasall", do_aliasall,      1,    1,
            "Define aliases for all of the build-in commands",
            ""
      },

      {
            "-ar",            do_ar,            3,    INFINITE_ARGS,
            "Extract or list files from an AR file",
            "[txp]v arFileName fileName ..."
      },

      {
            "cd",       do_cd,            1,    2,
            "Change current directory",
            "[dirName]"
      },

#if   HAVE_LINUX_ATTR
      {
            "-chattr",  do_chattr,  3,    INFINITE_ARGS,
            "Change ext2 file attributes",
            "[+i] [-i] [+a] [-a] fileName ..."
      },
#endif

      {
            "-chgrp",   do_chgrp,   3,    INFINITE_ARGS,
            "Change the group id of some files",
            "gid fileName ..."
      },

      {
            "-chmod",   do_chmod,   3,    INFINITE_ARGS,
            "Change the protection of some files",
            "mode fileName ..."
      },

      {
            "-chown",   do_chown,   3,    INFINITE_ARGS,
            "Change the owner id of some files",
            "uid fileName ..."
      },

      {
            "-cmp",           do_cmp,           3,    3,
            "Compare two files for equality",
            "fileName1 fileName2"
      },

      {
            "-cp",            do_cp,            3,    INFINITE_ARGS,
            "Copy files",
            "srcName ... destName"
      },

      {
            "-dd",            do_dd,            3,    INFINITE_ARGS,
            "Copy data between two files",
            "if=name of=name [bs=n] [count=n] [skip=n] [seek=n]"
      },

      {
            "-echo",    do_echo,    1,    INFINITE_ARGS,
            "Echo the arguments",
            "[args] ..."
      },

      {
            "-ed",            do_ed,            1,    2,
            "Edit a fileName using simple line mode commands",
            "[fileName]"
      },

      {
            "exec",           do_exec,    2,    INFINITE_ARGS,
            "Execute another program in place of this sash process",
            "fileName [args]"
      },

      {
            "exit",           do_exit,    1,    1,
            "Exit from sash",
            ""
      },

      {
            "-file",    do_file,    1,    INFINITE_ARGS,
            "Describe information about files",
            "fileName ..."
      },

      {
            "-find",    do_find,    2,    INFINITE_ARGS,
            "Find files in a directory tree meeting some conditions",
            "dirName [-xdev] [-type chars] [-name pattern] [-size minSize]"
      },

      {
            "-grep",    do_grep,    3,    INFINITE_ARGS,
            "Look for lines containing a word in some files",
            "[-in] word fileName ..."
      },

#if   HAVE_GZIP
      {
            "-gunzip",  do_gunzip,  2,    INFINITE_ARGS,
            "Uncompress files which were saved in GZIP or compress format",
            "fileName ... [-o outputPath]"
      },

      {
            "-gzip",    do_gzip,    2,    INFINITE_ARGS,
            "Compress files into GZIP format",
            "fileName ... [-o outputPath]"
      },
#endif

      {
            "help",           do_help,    1,    2,
            "Print help about a command",
            "[word]"
      },

      {
            "-kill",    do_kill,    2,    INFINITE_ARGS,
            "Send a signal to the specified process",
            "[-sig] pid ..."
      },

      {
            "-ln",            do_ln,            3,    INFINITE_ARGS,
            "Link one fileName to another",
            "[-s] srcName ... destName"
      },

      {
            "-ls",            do_ls,            1,    INFINITE_ARGS,
            "List information about files or directories",
            "[-lidFC] fileName ..."
      },

#if   HAVE_LINUX_ATTR
      {
            "-lsattr",  do_lsattr,  2,    INFINITE_ARGS,
            "List ext2 file attributes",
            "fileName ..."
      },
#endif

      {
            "-mkdir",   do_mkdir,   2,    INFINITE_ARGS,
            "Create a directory",
            "dirName ..."
      },

      {
            "-mknod",   do_mknod,   5,    5,
            "Create a special type of file",
            "fileName type major minor"
      },

      {
            "-more",    do_more,    2,    INFINITE_ARGS,
            "Type file contents page by page",
            "fileName ..."
      },

      {
            "-mount",   do_mount,   3,    INFINITE_ARGS,
            "Mount or remount a filesystem on a directory",
#if   HAVE_LINUX_MOUNT
            "[-t type] [-r] [-s] [-e] [-m] devName dirName"
#elif HAVE_BSD_MOUNT
            "[-t type] [-r] [-s] [-e] devName dirName"
#else
            "[-t type] devName dirName"
#endif
      },

      {
            "-mv",            do_mv,            3,    INFINITE_ARGS,
            "Move or rename files",
            "srcName ... destName"
      },

      {
            "-printenv",      do_printenv,      1,    2,
            "Print environment variables",
            "[name]"
      },

      {
            "prompt",   do_prompt,  2,    INFINITE_ARGS,
            "Set the prompt string for sash",
            "string"
      },

      {
            "-pwd",           do_pwd,           1,    1,
            "Print the current working directory",
            ""
      },

      {
            "quit",           do_exit,    1,    1,
            "Exit from sash",
            ""
      },

      {
            "-rm",            do_rm,            2,    INFINITE_ARGS,
            "Remove the specified files",
            "fileName ..."
      },

      {
            "-rmdir",   do_rmdir,   2,    INFINITE_ARGS,
            "Remove the specified empty directories",
            "dirName ..."
      },

      {
            "setenv",   do_setenv,  3,    3,
            "Set an environment variable value",
            "name value"
      },

      {
            "source",   do_source,  2,    2,
            "Read commands from the specified file",
            "fileName"
      },

      {
            "-sum",           do_sum,           2,    INFINITE_ARGS,
            "Calculate checksums of the specified files",
            "fileName ..."
      },

      {
            "-sync",    do_sync,    1,    1,
            "Sync the disks to force cached data to them",
            ""
      },

      {
            "-tar",           do_tar,           2,    INFINITE_ARGS,
            "Create, extract, or list files from a TAR file",
            "[cxtv]f tarFileName fileName ..."
      },

      {
            "-touch",   do_touch,   2,    INFINITE_ARGS,
            "Update times or create the specified files",
            "fileName ..."
      },

      {
            "umask",    do_umask,   1,    2,
            "Set the umask value for file protections",
            "[mask]"
      },

      {
#if   HAVE_BSD_MOUNT
            "-umount",  do_umount,  2,    3,
            "Unmount a filesystem",
            "[-f] fileName"
#else
            "-umount",  do_umount,  2,    2,
            "Unmount a filesystem",
            "fileName"
#endif
      },

      {
            "unalias",  do_unalias, 2,    2,
            "Remove a command alias",
            "name"
      },

      {
            "-where",   do_where,   2,    2,
            "Type the location of a program",
            "program"
      },

      {
            NULL,       0,          0,    0,
            NULL,
            NULL
      }
};


/*
 * The definition of an command alias.
 */
typedef struct
{
      char *      name;
      char *      value;
} Alias;


/*
 * Local data.
 */
static      Alias *     aliasTable;
static      int   aliasCount;

static      FILE *      sourcefiles[MAX_SOURCE];
static      int   sourceCount;

static      BOOL  intCrlf = TRUE;
static      char *      prompt;


/*
 * Local procedures.
 */
static      void  catchInt(int);
static      void  catchQuit(int);
static      void  readFile(const char * name);
static      void  command(const char * cmd);
static      BOOL  tryBuiltIn(const char * cmd);
static      void  runCmd(const char * cmd);
static      void  childProcess(const char * cmd);
static      void  showPrompt(void);
static      void  usage(void);
static      Alias *     findAlias(const char * name);


/*
 * Global interrupt flag.
 */
BOOL  intFlag;


int
main(int argc, const char ** argv)
{
      const char *      cp;
      const char *      singleCommand;
      const char *      commandFile;
      BOOL        quietFlag;
      BOOL        aliasFlag;
        BOOL            interactiveFlag;
      char        buf[PATH_LEN];

      singleCommand = NULL;
      commandFile = NULL;
      quietFlag = FALSE;
      aliasFlag = FALSE;
        interactiveFlag = FALSE;

      /*
       * Look for options.
       */
      argv++;
      argc--;

      while ((argc > 0) && (**argv == '-'))
      {
            cp = *argv++ + 1;
            argc--;

            while (*cp) switch (*cp++)
            {
                        case '-':
                                /*
                                 * Ignore.  This is so that we can be
                                 * run from login.
                                 */
                                break;
                  case 'c':
                        /*
                         * Execute specified command.
                         */
                        if ((argc != 1) || singleCommand || interactiveFlag)
                              usage();

                        singleCommand = *argv++;
                        argc--;

                        break;

                  case 'f':
                        /*
                         * Execute commands from file.
                         * This is used for sash script files.
                         * The quiet flag is also set.
                         */
                        if ((argc != 1) || commandFile)
                              usage();

                        quietFlag = TRUE;
                        commandFile = *argv++;
                        argc--;

                        break;

                  case 'i':
                        /*
                         * Be an interactive shell
                         * ..is a no-op, but some contexts require this
                         * ..interactiveFlag is to avoid -ic as a legacy
                         */
                         if (singleCommand)
                              usage();
                         
                         interactiveFlag = TRUE;
                         break;
                         
                  case 'p':
                        /*
                         * Set the prompt string.
                         */
                        if ((argc <= 0) || (**argv == '-'))
                              usage();

                        if (prompt)
                              free(prompt);

                        prompt = strdup(*argv++);
                        argc--;

                        break;

                  case 'q':
                        quietFlag = TRUE;
                        break;

                  case 'a':
                        aliasFlag = TRUE;
                        break;

                  case 'h':
                  case '?':
                        usage();
                        break;

                  default:
                        fprintf(stderr, "Unknown option -%c\n", cp[-1]);

                        return 1;
            }
      }

      /*
       * No more arguments are allowed.
       */
      if (argc > 0)
            usage();

      /*
       * Default our path if it is not set.
       */
      if (getenv("PATH") == NULL)
            putenv("PATH=/bin:/usr/bin:/sbin:/usr/sbin:/etc");

      /*
       * If the alias flag is set then define all aliases.
       */
      if (aliasFlag)
            do_aliasall(0, NULL);

      /*
       * If we are to execute a single command, then do so and exit.
       */
      if (singleCommand)
      {
            command(singleCommand);

            return 0;
      }

      /*
       * Print a hello message unless we are told to be silent.
       */
      if (!quietFlag && isatty(STDIN))
      {
            printf("Stand-alone shell (version %s)\n", version);

            if (aliasFlag)
                  printf("Built-in commands are aliased to standard commands\n");
      }

      signal(SIGINT, catchInt);
      signal(SIGQUIT, catchQuit);

      /*
       * Execute the user's alias file if present.
       */
      cp = getenv("HOME");

      if (cp)
      {
            strcpy(buf, cp);
            strcat(buf, "/");
            strcat(buf, ".aliasrc");

            if ((access(buf, 0) == 0) || (errno != ENOENT))
                  readFile(buf);
      }

      /*
       * Read commands from stdin or from a command file.
       */
      readFile(commandFile);

      return 0;
}


/*
 * Read commands from the specified file.
 * A null name pointer indicates to read from stdin.
 */
static void
readFile(const char * name)
{
      FILE *      fp;
      int   cc;
      BOOL  ttyFlag;
      char  buf[CMD_LEN];

      if (sourceCount >= MAX_SOURCE)
      {
            fprintf(stderr, "Too many source files\n");

            return;
      }

      fp = stdin;

      if (name)
      {
            fp = fopen(name, "r");

            if (fp == NULL)
            {
                  perror(name);

                  return;
            }
      }

      sourcefiles[sourceCount++] = fp;

      ttyFlag = isatty(fileno(fp));

      while (TRUE)
      {
            if (ttyFlag)
                  showPrompt();

            if (intFlag && !ttyFlag && (fp != stdin))
            {
                  fclose(fp);
                  sourceCount--;

                  return;
            }
      
            if (fgets(buf, CMD_LEN - 1, fp) == NULL)
            {
                  if (ferror(fp) && (errno == EINTR))
                  {
                        clearerr(fp);

                        continue;
                  }

                  break;
            }

            cc = strlen(buf);

            if (buf[cc - 1] == '\n')
                  cc--;

            while ((cc > 0) && isBlank(buf[cc - 1]))
                  cc--;

            buf[cc] = '\0';

            command(buf);
      }

      if (ferror(fp))
      {
            perror("Reading command line");

            if (fp == stdin)
                  exit(1);
      }

      clearerr(fp);

      if (fp != stdin)
            fclose(fp);

      sourceCount--;
}


/*
 * Parse and execute one null-terminated command line string.
 * This breaks the command line up into words, checks to see if the
 * command is an alias, and expands wildcards.
 */
static void
command(const char * cmd)
{
      const char *      endCmd;
      const Alias *     alias;
      char        newCommand[CMD_LEN];
      char        cmdName[CMD_LEN];

      /*
       * Rest the interrupt flag and free any memory chunks that
       * were allocated by the previous command.
       */
      intFlag = FALSE;

      freeChunks();

      /*
       * Skip leading blanks.
       */
      while (isBlank(*cmd))
            cmd++;

      /*
       * If the command is empty or is a comment then ignore it.
       */
      if ((*cmd == '\0') || (*cmd == '#'))
            return;

      /*
       * Look for the end of the command name and then copy the
       * command name to a buffer so we can null terminate it.
       */
      endCmd = cmd;

      while (*endCmd && !isBlank(*endCmd))
            endCmd++;

      memcpy(cmdName, cmd, endCmd - cmd);

      cmdName[endCmd - cmd] = '\0';

      /*
       * Search for the command name in the alias table.
       * If it is found, then replace the command name with
       * the alias value, and append the current command
       * line arguments to that.
       */
      alias = findAlias(cmdName);

      if (alias)
      {
            strcpy(newCommand, alias->value);
            strcat(newCommand, endCmd);

            cmd = newCommand;
      }

      /*
       * Now look for the command in the builtin table, and execute
       * the command if found.
       */
      if (tryBuiltIn(cmd))
            return;

      /*
       * The command is not a built-in, so run the program along
       * the PATH list.
       */
      runCmd(cmd);
}


/*
 * Try to execute a built-in command.
 * Returns TRUE if the command is a built in, whether or not the
 * command succeeds.  Returns FALSE if this is not a built-in command.
 */
static BOOL
tryBuiltIn(const char * cmd)
{
      const char *            endCmd;
      const CommandEntry *    entry;
      int               argc;
      const char **           argv;
      char              cmdName[CMD_LEN];

      /*
       * Look for the end of the command name and then copy the
       * command name to a buffer so we can null terminate it.
       */
      endCmd = cmd;

      while (*endCmd && !isBlank(*endCmd))
            endCmd++;

      memcpy(cmdName, cmd, endCmd - cmd);

      cmdName[endCmd - cmd] = '\0';

      /*
       * Search the command table looking for the command name.
       */
      for (entry = commandEntryTable; entry->name != NULL; entry++)
      {
            if (strcmp(entry->name, cmdName) == 0)
                  break;
      }

      /*
       * If the command is not a built-in, return indicating that.
       */
      if (entry->name == NULL)
            return FALSE;

      /*
       * The command is a built-in.
       * Break the command up into arguments and expand wildcards.
       */
      if (!makeArgs(cmd, &argc, &argv))
            return TRUE;

      /*
       * Give a usage string if the number of arguments is too large
       * or too small.
       */
      if ((argc < entry->minArgs) || (argc > entry->maxArgs))
      {
            fprintf(stderr, "usage: %s %s\n", entry->name, entry->usage);

            return TRUE;
      }

      /*
       * Call the built-in function with the argument list.
       */
      entry->func(argc, argv);

      return TRUE;
}


/*
 * Execute the specified command either by forking and executing
 * the program ourself, or else by using the shell.
 */
static void
runCmd(const char * cmd)
{
      const char *      cp;
      BOOL        magic;
      pid_t       pid;
      int         status;

      /*
       * Check the command for any magic shell characters
       * except for quoting.
       */
      magic = FALSE;

      for (cp = cmd; *cp; cp++)
      {
            if ((*cp >= 'a') && (*cp <= 'z'))
                  continue;

            if ((*cp >= 'A') && (*cp <= 'Z'))
                  continue;

            if (isDecimal(*cp))
                  continue;

            if (isBlank(*cp))
                  continue;

            if ((*cp == '.') || (*cp == '/') || (*cp == '-') ||
                  (*cp == '+') || (*cp == '=') || (*cp == '_') ||
                  (*cp == ':') || (*cp == ',') || (*cp == '\'') ||
                  (*cp == '"'))
            {
                  continue;
            }

            magic = TRUE;
      }

      /*
       * If there were any magic characters used then run the
       * command using the shell.
       */
      if (magic)
      {
            system(cmd);

            return;
      }

      /*
       * No magic characters were in the command, so we can do the fork
       * and exec ourself.
       */
      pid = fork();

      if (pid < 0)
      {
            perror("fork failed");

            return;
      }

      /*
       * If we are the child process, then go execute the program.
       */
      if (pid == 0)
            childProcess(cmd);

      /*
       * We are the parent process.
       * Wait for the child to complete.
       */
      status = 0;
      intCrlf = FALSE;

      while (((pid = waitpid(pid, &status, 0)) < 0) && (errno == EINTR))
            ;

      intCrlf = TRUE;

      if (pid < 0)
      {
            fprintf(stderr, "Error from waitpid: %s", strerror(errno));

            return;
      }

      if (WIFSIGNALED(status))
      {
            fprintf(stderr, "pid %ld: killed by signal %d\n",
                  (long) pid, WTERMSIG(status));
      }
}


/*
 * Here as the child process to try to execute the command.
 * This is only called if there are no meta-characters in the command.
 * This procedure never returns.
 */
static void
childProcess(const char * cmd)
{
      const char **     argv;
      int         argc;

      /*
       * Close any extra file descriptors we have opened.
       */   
      while (--sourceCount >= 0)
      {
            if (sourcefiles[sourceCount] != stdin)
                  fclose(sourcefiles[sourceCount]);
      }

      /*
       * Break the command line up into individual arguments.
       * If this fails, then run the shell to execute the command.
       */
      if (!makeArgs(cmd, &argc, &argv))
      {
            system(cmd);
            exit(0);
      }

      /*
       * Try to execute the program directly.
       */
      execvp(argv[0], (char **) argv);

      /*
       * The exec failed, so try to run the command using the shell
       * in case it is a shell script.
       */
      if (errno == ENOEXEC)
      {
            system(cmd);
            exit(0);
      }

      /*
       * There was something else wrong, complain and exit.
       */
      perror(argv[0]);
      exit(1);
}


void
do_help(int argc, const char ** argv)
{
      const CommandEntry *    entry;
      const char *            str;

      str = NULL;

      if (argc == 2)
            str = argv[1];

      /*
       * Check for an exact match, in which case describe the program.
       */
      if (str)
      {
            for (entry = commandEntryTable; entry->name; entry++)
            {
                  if (strcmp(str, entry->name) == 0)
                  {
                        printf("%s\n", entry->description);

                        printf("usage: %s %s\n", entry->name,
                              entry->usage);

                        return;
                  }
            }
      }

      /*
       * Print short information about commands which contain the
       * specified word.
       */
      for (entry = commandEntryTable; entry->name; entry++)
      {
            if ((str == NULL) || (strstr(entry->name, str) != NULL) ||
                  (strstr(entry->usage, str) != NULL))
            {
                  printf("%-10s %s\n", entry->name, entry->usage);
            }
      }
}


void
do_alias(int argc, const char ** argv)
{
      const char *      name;
      char *            value;
      Alias *           alias;
      int         count;
      char        buf[CMD_LEN];

      if (argc < 2)
      {
            count = aliasCount;

            for (alias = aliasTable; count-- > 0; alias++)
                  printf("%s\t%s\n", alias->name, alias->value);

            return;
      }

      name = argv[1];

      if (argc == 2)
      {
            alias = findAlias(name);

            if (alias)
                  printf("%s\n", alias->value);
            else
                  fprintf(stderr, "Alias \"%s\" is not defined\n", name);

            return;     
      }

      if (strcmp(name, "alias") == 0)
      {
            fprintf(stderr, "Cannot alias \"alias\"\n");

            return;
      }

      if (!makeString(argc - 2, argv + 2, buf, CMD_LEN))
            return;

      value = malloc(strlen(buf) + 1);

      if (value == NULL)
      {
            fprintf(stderr, "No memory for alias value\n");

            return;
      }

      strcpy(value, buf);

      alias = findAlias(name);

      if (alias)
      {
            free(alias->value);
            alias->value = value;

            return;
      }

      if ((aliasCount % ALIAS_ALLOC) == 0)
      {
            count = aliasCount + ALIAS_ALLOC;

            if (aliasTable)
            {
                  alias = (Alias *) realloc(aliasTable,
                        sizeof(Alias) * count);
            }
            else
                  alias = (Alias *) malloc(sizeof(Alias) * count);

            if (alias == NULL)
            {
                  free(value);
                  fprintf(stderr, "No memory for alias table\n");

                  return;
            }

            aliasTable = alias;
      }

      alias = &aliasTable[aliasCount];

      alias->name = malloc(strlen(name) + 1);

      if (alias->name == NULL)
      {
            free(value);
            fprintf(stderr, "No memory for alias name\n");

            return;
      }

      strcpy(alias->name, name);
      alias->value = value;
      aliasCount++;
}


/*
 * Build aliases for all of the built-in commands which start with a dash,
 * using the names without the dash.
 */
void
do_aliasall(int argc, const char **argv)
{
      const CommandEntry *    entry;
      const char *            name;
      const char *            newArgv[4];

      for (entry = commandEntryTable; entry->name; entry++)
      {
            name = entry->name;

            if (*name != '-')
                  continue;

            newArgv[0] = "alias";
            newArgv[1] = name + 1;
            newArgv[2] = name;
            newArgv[3] = NULL;

            do_alias(3, newArgv);
      }
}


/*
 * Look up an alias name, and return a pointer to it.
 * Returns NULL if the name does not exist.
 */
static Alias *
findAlias(const char * name)
{
      Alias *     alias;
      int   count;

      count = aliasCount;

      for (alias = aliasTable; count-- > 0; alias++)
      {
            if (strcmp(name, alias->name) == 0)
                  return alias;
      }

      return NULL;
}


void
do_source(int argc, const char ** argv)
{
      readFile(argv[1]);
}


void
do_exec(int argc, const char ** argv)
{
      const char *      name;

      name = argv[1];

      while (--sourceCount >= 0)
      {
            if (sourcefiles[sourceCount] != stdin)
                  fclose(sourcefiles[sourceCount]);
      }

      argv[argc] = NULL;

      execvp(name, (char **) argv + 1);
      perror(name);
}


void
do_prompt(int argc, const char ** argv)
{
      char *      cp;
      char  buf[CMD_LEN];

      if (!makeString(argc - 1, argv + 1, buf, CMD_LEN))
            return;

      cp = malloc(strlen(buf) + 2);

      if (cp == NULL)
      {
            fprintf(stderr, "No memory for prompt\n");

            return;
      }

      strcpy(cp, buf);
      strcat(cp, " ");

      if (prompt)
            free(prompt);

      prompt = cp;
}


void
do_unalias(int argc, const char ** argv)
{
      Alias *     alias;

      while (--argc > 0)
      {
            alias = findAlias(*++argv);

            if (alias == NULL)
                  continue;

            free(alias->name);
            free(alias->value);
            aliasCount--;
            alias->name = aliasTable[aliasCount].name;
            alias->value = aliasTable[aliasCount].value;    
      }
}


/*
 * Display the prompt string.
 */
static void
showPrompt(void)
{
      const char *      cp;

      cp = "> ";

      if (prompt)
            cp = prompt;

      write(STDOUT, cp, strlen(cp));
}     


static void
catchInt(int val)
{
      signal(SIGINT, catchInt);

      intFlag = TRUE;

      if (intCrlf)
            write(STDOUT, "\n", 1);
}


static void
catchQuit(int val)
{
      signal(SIGQUIT, catchQuit);

      intFlag = TRUE;

      if (intCrlf)
            write(STDOUT, "\n", 1);
}


/*
 * Print the usage information and quit.
 */
static void
usage(void)
{
      fprintf(stderr, "Stand-alone shell (version %s)\n", version);
      fprintf(stderr, "\n");
      fprintf(stderr, "Usage: sash [-a] [-q] [-f fileName] [-c command] [-p prompt] [-i]\n");

      exit(1);
}

/* END CODE */

Generated by  Doxygen 1.6.0   Back to index