Blame cmdline.c

Packit Service 501009
/* cmdline.c - core analysis suite
Packit Service 501009
 *
Packit Service 501009
 * Copyright (C) 1999, 2000, 2001, 2002 Mission Critical Linux, Inc.
Packit Service 501009
 * Copyright (C) 2002-2015,2019 David Anderson
Packit Service 501009
 * Copyright (C) 2002-2015,2019 Red Hat, Inc. All rights reserved.
Packit Service 501009
 *
Packit Service 501009
 * This program is free software; you can redistribute it and/or modify
Packit Service 501009
 * it under the terms of the GNU General Public License as published by
Packit Service 501009
 * the Free Software Foundation; either version 2 of the License, or
Packit Service 501009
 * (at your option) any later version.
Packit Service 501009
 *
Packit Service 501009
 * This program is distributed in the hope that it will be useful,
Packit Service 501009
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit Service 501009
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
Packit Service 501009
 * GNU General Public License for more details.
Packit Service 501009
 */
Packit Service 501009
Packit Service 501009
#include "defs.h"
Packit Service 501009
Packit Service 501009
static void restore_sanity(void);
Packit Service 501009
static void restore_ifile_sanity(void);
Packit Service 501009
static int pseudo_command(char *);
Packit Service 501009
static void check_special_handling(char *);
Packit Service 501009
static int is_executable_in_PATH(char *);
Packit Service 501009
static int is_shell_script(char *);
Packit Service 501009
static void list_aliases(char *);
Packit Service 501009
static int allocate_alias(int);
Packit Service 501009
static int alias_exists(char *);
Packit Service 501009
static void resolve_aliases(void);
Packit Service 501009
static int setup_redirect(int);
Packit Service 501009
int multiple_pipes(char **);
Packit Service 501009
static int output_command_to_pids(void);
Packit Service 501009
static void set_my_tty(void);
Packit Service 501009
static char *signame(int);
Packit Service 501009
static int setup_stdpipe(void);
Packit Service 501009
static void wait_for_children(ulong);
Packit Service 501009
#define ZOMBIES_ONLY (1)
Packit Service 501009
#define ALL_CHILDREN (2)
Packit Service 501009
int shell_command(char *);
Packit Service 501009
static void modify_orig_line(char *, struct args_input_file *);
Packit Service 501009
static void modify_expression_arg(char *, char **, struct args_input_file *);
Packit Service 501009
static int verify_args_input_file(char *);
Packit Service 501009
static char *crash_readline_completion_generator(const char *, int);
Packit Service 501009
static char **crash_readline_completer(const char *, int, int);
Packit Service 501009
Packit Service 501009
#define READLINE_LIBRARY
Packit Service 501009
Packit Service 501009
#include <readline.h>
Packit Service 501009
#include <rldefs.h>
Packit Service 501009
#include <history.h>
Packit Service 501009
Packit Service 501009
static void readline_init(void);
Packit Service 501009
Packit Service 501009
static struct alias_data alias_head = { 0 }; 
Packit Service 501009
Packit Service 501009
void
Packit Service 501009
process_command_line(void)
Packit Service 501009
{
Packit Service 501009
	/*
Packit Service 501009
	 *  Restore normal environment, clearing out any excess baggage
Packit Service 501009
	 *  piled up by the previous command.
Packit Service 501009
	 */
Packit Service 501009
	restore_sanity();
Packit Service 501009
	fp = stdout;
Packit Service 501009
	BZERO(pc->command_line, BUFSIZE);
Packit Service 501009
Packit Service 501009
	if (!(pc->flags & 
Packit Service 501009
	    (READLINE|SILENT|CMDLINE_IFILE|RCHOME_IFILE|RCLOCAL_IFILE))) 
Packit Service 501009
		fprintf(fp, "%s", pc->prompt);
Packit Service 501009
	fflush(fp);
Packit Service 501009
Packit Service 501009
	/*
Packit Service 501009
	 *  Input can come from five possible sources:
Packit Service 501009
	 *
Packit Service 501009
	 *    1. an .rc file located in the user's HOME directory.
Packit Service 501009
         *    2. an .rc file located in the current directory.
Packit Service 501009
	 *    3. an input file that was designated by the -i flag at 
Packit Service 501009
	 *       program invocation.
Packit Service 501009
	 *    4. from a terminal.
Packit Service 501009
	 *    5. from a pipe, if stdin is a pipe rather than a terminal.
Packit Service 501009
	 *
Packit Service 501009
	 *  But first, handle the interruption of an input file caused
Packit Service 501009
	 *  by a FATAL error in one of its commands.
Packit Service 501009
	 *
Packit Service 501009
	 */
Packit Service 501009
	if (pc->ifile_in_progress) {
Packit Service 501009
		switch (pc->ifile_in_progress)
Packit Service 501009
		{
Packit Service 501009
		case RCHOME_IFILE:
Packit Service 501009
			pc->flags |= INIT_IFILE|RCHOME_IFILE;
Packit Service 501009
			sprintf(pc->command_line, "< %s/.%src", 
Packit Service 501009
				pc->home, pc->program_name);
Packit Service 501009
			break;
Packit Service 501009
		case RCLOCAL_IFILE:
Packit Service 501009
			sprintf(pc->command_line, "< .%src", pc->program_name);
Packit Service 501009
			pc->flags |= INIT_IFILE|RCLOCAL_IFILE;
Packit Service 501009
			break;
Packit Service 501009
		case CMDLINE_IFILE:
Packit Service 501009
			sprintf(pc->command_line, "< %s", pc->input_file);
Packit Service 501009
			pc->flags |= INIT_IFILE|CMDLINE_IFILE;
Packit Service 501009
			break;
Packit Service 501009
		case RUNTIME_IFILE:
Packit Service 501009
			sprintf(pc->command_line, "%s", pc->runtime_ifile_cmd);
Packit Service 501009
			pc->flags |= IFILE_ERROR;
Packit Service 501009
			break;
Packit Service 501009
		default:
Packit Service 501009
			error(FATAL, "invalid input file\n");
Packit Service 501009
		}
Packit Service 501009
	} else if (pc->flags & RCHOME_IFILE) {
Packit Service 501009
                sprintf(pc->command_line, "< %s/.%src", 
Packit Service 501009
			pc->home, pc->program_name);
Packit Service 501009
		pc->flags |= INIT_IFILE;
Packit Service 501009
	} else if (pc->flags & RCLOCAL_IFILE) { 
Packit Service 501009
                sprintf(pc->command_line, "< .%src", pc->program_name);
Packit Service 501009
		pc->flags |= INIT_IFILE;
Packit Service 501009
	} else if (pc->flags & CMDLINE_IFILE) {
Packit Service 501009
		sprintf(pc->command_line, "< %s", pc->input_file);
Packit Service 501009
		pc->flags |= INIT_IFILE;
Packit Service 501009
	} else if (pc->flags & TTY) {
Packit Service 501009
		if (!(pc->readline = readline(pc->prompt))) {
Packit Service 501009
			args[0] = NULL;
Packit Service 501009
			fprintf(fp, "\n");
Packit Service 501009
			return;
Packit Service 501009
		}
Packit Service 501009
		if (strlen(pc->readline) >= BUFSIZE)
Packit Service 501009
			error(FATAL, "input line exceeds maximum of 1500 bytes\n");	
Packit Service 501009
		else	
Packit Service 501009
			strcpy(pc->command_line, pc->readline);
Packit Service 501009
		free(pc->readline); 
Packit Service 501009
Packit Service 501009
		clean_line(pc->command_line);
Packit Service 501009
		pseudo_command(pc->command_line);
Packit Service 501009
		strcpy(pc->orig_line, pc->command_line);
Packit Service 501009
Packit Service 501009
		if (strlen(pc->command_line) && !iscntrl(pc->command_line[0])) 
Packit Service 501009
			add_history(pc->command_line);
Packit Service 501009
		
Packit Service 501009
		check_special_handling(pc->command_line);
Packit Service 501009
        } else {
Packit Service 501009
        	if (fgets(pc->command_line, BUFSIZE-1, stdin) == NULL)
Packit Service 501009
			clean_exit(1);
Packit Service 501009
		clean_line(pc->command_line);
Packit Service 501009
		strcpy(pc->orig_line, pc->command_line);
Packit Service 501009
        }
Packit Service 501009
Packit Service 501009
	/*
Packit Service 501009
	 *  First clean out all linefeeds and leading/trailing spaces.
Packit Service 501009
	 *  Then substitute aliases for the real thing they represent.
Packit Service 501009
	 */
Packit Service 501009
	clean_line(pc->command_line);
Packit Service 501009
	resolve_aliases();
Packit Service 501009
Packit Service 501009
	/*
Packit Service 501009
	 *  Setup output redirection based upon the command line itself or
Packit Service 501009
	 *  based upon the default scrolling behavior, if any.
Packit Service 501009
	 */
Packit Service 501009
Packit Service 501009
	switch (setup_redirect(FROM_COMMAND_LINE))
Packit Service 501009
	{
Packit Service 501009
	case REDIRECT_NOT_DONE:
Packit Service 501009
	case REDIRECT_TO_STDPIPE:
Packit Service 501009
	case REDIRECT_TO_PIPE:
Packit Service 501009
	case REDIRECT_TO_FILE:
Packit Service 501009
		break;
Packit Service 501009
Packit Service 501009
	case REDIRECT_SHELL_ESCAPE:
Packit Service 501009
	case REDIRECT_SHELL_COMMAND:
Packit Service 501009
	case REDIRECT_FAILURE:  
Packit Service 501009
		RESTART();
Packit Service 501009
		break;
Packit Service 501009
	}
Packit Service 501009
Packit Service 501009
	/*
Packit Service 501009
	 *  Setup the global argcnt and args[] array for use by everybody
Packit Service 501009
	 *  during the life of this command.
Packit Service 501009
	 */
Packit Service 501009
	argcnt = parse_line(pc->command_line, args);
Packit Service 501009
}
Packit Service 501009
Packit Service 501009
Packit Service 501009
/*
Packit Service 501009
 *  Allow input file redirection without having to put a space between 
Packit Service 501009
 *  the < and the filename.  Allow the "pointer-to" asterisk to "touch"
Packit Service 501009
 *  the structure/union name.
Packit Service 501009
 */
Packit Service 501009
static void 
Packit Service 501009
check_special_handling(char *s)
Packit Service 501009
{
Packit Service 501009
	char local[BUFSIZE];
Packit Service 501009
Packit Service 501009
	strcpy(local, s);
Packit Service 501009
Packit Service 501009
	if ((local[0] == '*') && (!whitespace(local[1]))) {
Packit Service 501009
		sprintf(s, "* %s", &local[1]);
Packit Service 501009
		return;
Packit Service 501009
	}
Packit Service 501009
Packit Service 501009
        if ((local[0] == '<') && (!whitespace(local[1]))) {
Packit Service 501009
                sprintf(s, "< %s", &local[1]);
Packit Service 501009
                return;
Packit Service 501009
        }
Packit Service 501009
}
Packit Service 501009
Packit Service 501009
static int
Packit Service 501009
is_executable_in_PATH(char *filename)
Packit Service 501009
{
Packit Service 501009
	char *buf1, *buf2;
Packit Service 501009
	char *tok, *path;
Packit Service 501009
	int retval;
Packit Service 501009
Packit Service 501009
        if ((path = getenv("PATH"))) {
Packit Service 501009
		buf1 = GETBUF(strlen(path)+1);
Packit Service 501009
		buf2 = GETBUF(strlen(path)+1);
Packit Service 501009
		strcpy(buf2, path);
Packit Service 501009
	} else
Packit Service 501009
		return FALSE;
Packit Service 501009
Packit Service 501009
	retval = FALSE;
Packit Service 501009
	tok = strtok(buf2, ":");
Packit Service 501009
	while (tok) {
Packit Service 501009
		sprintf(buf1, "%s/%s", tok, filename);
Packit Service 501009
		if (file_exists(buf1, NULL) && 
Packit Service 501009
		    (access(buf1, X_OK) == 0)) {
Packit Service 501009
			retval = TRUE;
Packit Service 501009
			break;
Packit Service 501009
		}
Packit Service 501009
		tok = strtok(NULL, ":");
Packit Service 501009
	}
Packit Service 501009
Packit Service 501009
	FREEBUF(buf1);
Packit Service 501009
	FREEBUF(buf2);
Packit Service 501009
Packit Service 501009
	return retval;
Packit Service 501009
}
Packit Service 501009
Packit Service 501009
/*
Packit Service 501009
 *  At this point the only pseudo commands are the "r" (repeat) and 
Packit Service 501009
 *  the "h" (history) command:
Packit Service 501009
 *
Packit Service 501009
 *    1. an "r" alone, or "!!" along, just means repeat the last command.
Packit Service 501009
 *    2. an "r" followed by a number, means repeat that command from the
Packit Service 501009
 *       history table.
Packit Service 501009
 *    3. an "!" followed by a number that is not the name of a command 
Packit Service 501009
 *       in the user's PATH, means repeat that command from the history table.
Packit Service 501009
 *    4. an "r" followed by one or more non-decimal characters means to
Packit Service 501009
 *       seek back until a line-beginning match is found. 
Packit Service 501009
 *    5. an "h" alone, or a string beginning with "hi", means history.
Packit Service 501009
 */
Packit Service 501009
static int
Packit Service 501009
pseudo_command(char *input)
Packit Service 501009
{
Packit Service 501009
        int i;
Packit Service 501009
	HIST_ENTRY *entry;
Packit Service 501009
	int idx, found;
Packit Service 501009
	char *p;
Packit Service 501009
Packit Service 501009
        clean_line(input);
Packit Service 501009
Packit Service 501009
        /*  
Packit Service 501009
         *  Just dump all commands that have been entered to date.
Packit Service 501009
         */
Packit Service 501009
        if (STREQ(input, "h") || STRNEQ(input, "hi")) {
Packit Service 501009
                dump_history();
Packit Service 501009
                pc->command_line[0] = NULLCHAR;
Packit Service 501009
                return TRUE;
Packit Service 501009
        }
Packit Service 501009
Packit Service 501009
        if (STREQ(input, "r") || STREQ(input, "!!")) {
Packit Service 501009
                if (!history_offset)
Packit Service 501009
                        error(FATAL, "no commands entered!\n");
Packit Service 501009
                entry = history_get(history_offset);
Packit Service 501009
                strcpy(input, entry->line);
Packit Service 501009
                fprintf(fp, "%s%s\n", pc->prompt, input);
Packit Service 501009
                return TRUE;
Packit Service 501009
        }
Packit Service 501009
Packit Service 501009
        if ((input[0] == 'r') && decimal(&input[1], 0)) {
Packit Service 501009
                if (!history_offset)
Packit Service 501009
                        error(FATAL, "no commands entered!\n");
Packit Service 501009
                p = &input[1];
Packit Service 501009
                goto rerun;
Packit Service 501009
        }
Packit Service 501009
Packit Service 501009
        if ((input[0] == '!') && decimal(&input[1], 0) &&
Packit Service 501009
	    !is_executable_in_PATH(first_nonspace(&input[1]))) {
Packit Service 501009
		p = first_nonspace(&input[1]);
Packit Service 501009
		goto rerun;
Packit Service 501009
	}
Packit Service 501009
Packit Service 501009
	if (STRNEQ(input, "r ")) {
Packit Service 501009
                if (!history_offset)
Packit Service 501009
                        error(FATAL, "no commands entered!\n");
Packit Service 501009
Packit Service 501009
		p = first_nonspace(&input[1]);
Packit Service 501009
rerun:
Packit Service 501009
		if (decimal(p, 0)) {
Packit Service 501009
			idx = atoi(p);
Packit Service 501009
			if (idx == 0)
Packit Service 501009
				goto invalid_repeat_request;
Packit Service 501009
			if (idx > history_offset) 
Packit Service 501009
				error(FATAL, "command %d not entered yet!\n",
Packit Service 501009
					idx);	
Packit Service 501009
                	entry = history_get(idx);
Packit Service 501009
               		strcpy(input, entry->line);
Packit Service 501009
                	fprintf(fp, "%s%s\n", pc->prompt, input);
Packit Service 501009
                	return TRUE;
Packit Service 501009
		} 
Packit Service 501009
Packit Service 501009
		idx = -1;
Packit Service 501009
		found = FALSE;
Packit Service 501009
Packit Service 501009
        	for (i = history_offset; i > 0; i--) {
Packit Service 501009
                	entry = history_get(i);
Packit Service 501009
			if (STRNEQ(entry->line, p)) {
Packit Service 501009
				found = TRUE;
Packit Service 501009
				break;
Packit Service 501009
			}
Packit Service 501009
        	}
Packit Service 501009
Packit Service 501009
		if (found) {
Packit Service 501009
			strcpy(input, entry->line);
Packit Service 501009
			fprintf(fp, "%s%s\n", pc->prompt, input);
Packit Service 501009
			return TRUE;
Packit Service 501009
		}
Packit Service 501009
Packit Service 501009
invalid_repeat_request:
Packit Service 501009
		fprintf(fp, "invalid repeat request: %s\n", input);
Packit Service 501009
		strcpy(input, "");
Packit Service 501009
		return TRUE;
Packit Service 501009
	}
Packit Service 501009
Packit Service 501009
	return FALSE;
Packit Service 501009
}
Packit Service 501009
Packit Service 501009
/*
Packit Service 501009
 *  Dump the history table in first-to-last chronological order.
Packit Service 501009
 */
Packit Service 501009
void
Packit Service 501009
dump_history(void)
Packit Service 501009
{
Packit Service 501009
        int i;
Packit Service 501009
        HIST_ENTRY **the_history;
Packit Service 501009
        HIST_ENTRY *entry;
Packit Service 501009
Packit Service 501009
        if (!history_offset)
Packit Service 501009
                error(FATAL, "no commands entered!\n");
Packit Service 501009
Packit Service 501009
        the_history = history_list();
Packit Service 501009
Packit Service 501009
        for (i = 0; i < history_offset; i++) {
Packit Service 501009
                entry = the_history[i];
Packit Service 501009
                fprintf(fp, "[%d] %s\n", i+1, entry->line);
Packit Service 501009
        }
Packit Service 501009
}
Packit Service 501009
Packit Service 501009
/*
Packit Service 501009
 *  Pager arguments.
Packit Service 501009
 */
Packit Service 501009
Packit Service 501009
static char *less_argv[5] = {
Packit Service 501009
	"/usr/bin/less",
Packit Service 501009
	"-E",
Packit Service 501009
	"-X",
Packit Service 501009
        "-Ps -- MORE --  forward\\: <SPACE>, <ENTER> or j  backward\\: b or k  quit\\: q",
Packit Service 501009
	NULL
Packit Service 501009
};
Packit Service 501009
Packit Service 501009
static char *more_argv[2] = {
Packit Service 501009
	"/bin/more",
Packit Service 501009
	NULL
Packit Service 501009
};
Packit Service 501009
Packit Service 501009
static char **CRASHPAGER_argv = NULL;
Packit Service 501009
Packit Service 501009
int
Packit Service 501009
CRASHPAGER_valid(void)
Packit Service 501009
{
Packit Service 501009
	int i, c;
Packit Service 501009
	char *env, *CRASHPAGER_buf;
Packit Service 501009
	char *arglist[MAXARGS];
Packit Service 501009
Packit Service 501009
	if (CRASHPAGER_argv)
Packit Service 501009
		return TRUE;
Packit Service 501009
Packit Service 501009
	if (!(env = getenv("CRASHPAGER")))
Packit Service 501009
		return FALSE;
Packit Service 501009
Packit Service 501009
	if (strstr(env, "|") || strstr(env, "<") || strstr(env, ">")) {	
Packit Service 501009
		error(INFO, 
Packit Service 501009
		    "CRASHPAGER ignored: contains invalid character: \"%s\"\n", 
Packit Service 501009
			env);
Packit Service 501009
		return FALSE;
Packit Service 501009
	}
Packit Service 501009
Packit Service 501009
	if ((CRASHPAGER_buf = (char *)malloc(strlen(env)+1)) == NULL)
Packit Service 501009
		return FALSE;
Packit Service 501009
Packit Service 501009
	strcpy(CRASHPAGER_buf, env);
Packit Service 501009
Packit Service 501009
	if (!(c = parse_line(CRASHPAGER_buf, arglist)) ||
Packit Service 501009
	    !file_exists(arglist[0], NULL) || access(arglist[0], X_OK) || 
Packit Service 501009
	    !(CRASHPAGER_argv = (char **)malloc(sizeof(char *) * (c+1)))) {
Packit Service 501009
		free(CRASHPAGER_buf);
Packit Service 501009
		if (strlen(env))
Packit Service 501009
			error(INFO, 
Packit Service 501009
		    		"CRASHPAGER ignored: \"%s\"\n", env);
Packit Service 501009
		return FALSE;
Packit Service 501009
	}
Packit Service 501009
Packit Service 501009
	for  (i = 0; i < c; i++)
Packit Service 501009
		CRASHPAGER_argv[i] = arglist[i];
Packit Service 501009
	CRASHPAGER_argv[i] = NULL;
Packit Service 501009
	
Packit Service 501009
	return TRUE;
Packit Service 501009
}
Packit Service 501009
Packit Service 501009
/*
Packit Service 501009
 *  Set up a command string buffer for error/help output.
Packit Service 501009
 */
Packit Service 501009
char *
Packit Service 501009
setup_scroll_command(void)
Packit Service 501009
{
Packit Service 501009
	char *buf;
Packit Service 501009
	long i, len;
Packit Service 501009
Packit Service 501009
	if (!(pc->flags & SCROLL))
Packit Service 501009
		return NULL;
Packit Service 501009
Packit Service 501009
	switch (pc->scroll_command)
Packit Service 501009
	{
Packit Service 501009
	case SCROLL_LESS:
Packit Service 501009
 		buf = GETBUF(strlen(less_argv[0])+1);
Packit Service 501009
		strcpy(buf, less_argv[0]);
Packit Service 501009
		break;
Packit Service 501009
	case SCROLL_MORE:
Packit Service 501009
 		buf = GETBUF(strlen(more_argv[0])+1);
Packit Service 501009
		strcpy(buf, more_argv[0]);
Packit Service 501009
		break;
Packit Service 501009
	case SCROLL_CRASHPAGER:
Packit Service 501009
		for (i = len = 0; CRASHPAGER_argv[i]; i++)
Packit Service 501009
			len += strlen(CRASHPAGER_argv[i])+1;
Packit Service 501009
Packit Service 501009
		buf = GETBUF(len);
Packit Service 501009
		
Packit Service 501009
        	for  (i = 0; CRASHPAGER_argv[i]; i++) {
Packit Service 501009
			sprintf(&buf[strlen(buf)], "%s%s", 
Packit Service 501009
				i ? " " : "",
Packit Service 501009
				CRASHPAGER_argv[i]);
Packit Service 501009
		}
Packit Service 501009
		break;
Packit Service 501009
	default:
Packit Service 501009
		return NULL;
Packit Service 501009
        }
Packit Service 501009
Packit Service 501009
	return buf;
Packit Service 501009
}
Packit Service 501009
Packit Service 501009
/*
Packit Service 501009
 *  Parse the command line for pipe or redirect characters:  
Packit Service 501009
 *
Packit Service 501009
 *   1. if a "|" character is found, popen() what comes after it, and 
Packit Service 501009
 *      modify the contents of the global "fp" FILE pointer.
Packit Service 501009
 *   2. if one or two ">" characters are found, fopen() the filename that
Packit Service 501009
 *      follows, and modify the contents of the global "fp" FILE pointer.
Packit Service 501009
 * 
Packit Service 501009
 *  Care is taken to segregate:
Packit Service 501009
 *
Packit Service 501009
 *   1. expressions encompassed by parentheses, or
Packit Service 501009
 *   2. strings encompassed by single or double quotation marks
Packit Service 501009
 *
Packit Service 501009
 *  When either of the above are in affect, no redirection is done.
Packit Service 501009
 *
Packit Service 501009
 *  Lastly, if no redirection is requested by the user on the command line,
Packit Service 501009
 *  output is passed to the default scrolling command, which is popen()'d
Packit Service 501009
 *  and again, the contents of the global "fp" FILE pointer is modified.
Packit Service 501009
 *  This default behavior is not performed if the command is coming from
Packit Service 501009
 *  an input file, nor if scrolling has been turned off.
Packit Service 501009
 */
Packit Service 501009
static int
Packit Service 501009
setup_redirect(int origin)
Packit Service 501009
{
Packit Service 501009
	char *p, which;
Packit Service 501009
	int append;
Packit Service 501009
	int expression;
Packit Service 501009
	int string;
Packit Service 501009
	int ret ATTRIBUTE_UNUSED;
Packit Service 501009
	FILE *pipe;
Packit Service 501009
	FILE *ofile;
Packit Service 501009
Packit Service 501009
	pc->redirect = origin;
Packit Service 501009
	pc->eoc_index = 0;
Packit Service 501009
Packit Service 501009
	p = pc->command_line;
Packit Service 501009
Packit Service 501009
        if (STREQ(p, "|") || STREQ(p, "!")) {
Packit Service 501009
		ret = system("/bin/sh");
Packit Service 501009
		pc->redirect |= REDIRECT_SHELL_ESCAPE;
Packit Service 501009
		return REDIRECT_SHELL_ESCAPE;
Packit Service 501009
	}
Packit Service 501009
Packit Service 501009
	if (FIRSTCHAR(p) == '|' || FIRSTCHAR(p) == '!')
Packit Service 501009
		pc->redirect |= REDIRECT_SHELL_COMMAND;
Packit Service 501009
Packit Service 501009
	expression = 0;
Packit Service 501009
	string = FALSE;
Packit Service 501009
Packit Service 501009
	while (*p) {
Packit Service 501009
		if (*p == '(')
Packit Service 501009
			expression++;
Packit Service 501009
		if (*p == ')')
Packit Service 501009
			expression--;
Packit Service 501009
Packit Service 501009
		if ((*p == '"') || (*p == '\''))
Packit Service 501009
			string = !string;
Packit Service 501009
Packit Service 501009
		if (!(expression || string) && 
Packit Service 501009
		    ((*p == '|') || (*p == '!'))) {
Packit Service 501009
			which = *p;
Packit Service 501009
			*p = NULLCHAR;
Packit Service 501009
			pc->eoc_index = p - pc->command_line;
Packit Service 501009
			p++;
Packit Service 501009
			p = strip_beginning_whitespace(p);
Packit Service 501009
Packit Service 501009
			if (!strlen(p)) {
Packit Service 501009
				error(INFO, "no shell command after '%c'\n",
Packit Service 501009
					which);
Packit Service 501009
				pc->redirect |= REDIRECT_FAILURE;
Packit Service 501009
				return REDIRECT_FAILURE;
Packit Service 501009
			}
Packit Service 501009
		
Packit Service 501009
			if (LASTCHAR(p) == '|')
Packit Service 501009
				error(FATAL_RESTART, "pipe to nowhere?\n");
Packit Service 501009
Packit Service 501009
			if (pc->redirect & REDIRECT_SHELL_COMMAND)
Packit Service 501009
				return shell_command(p);
Packit Service 501009
Packit Service 501009
                        if ((pipe = popen(p, "w")) == NULL) {
Packit Service 501009
                                error(INFO, "cannot open pipe\n");
Packit Service 501009
				pc->redirect |= REDIRECT_FAILURE;
Packit Service 501009
				return REDIRECT_FAILURE;
Packit Service 501009
                        }
Packit Service 501009
                        setbuf(pipe, NULL);
Packit Service 501009
Packit Service 501009
			switch (origin)
Packit Service 501009
			{
Packit Service 501009
			case FROM_COMMAND_LINE:
Packit Service 501009
				fp = pc->pipe = pipe;
Packit Service 501009
				break;
Packit Service 501009
Packit Service 501009
			case FROM_INPUT_FILE:
Packit Service 501009
				fp = pc->ifile_pipe = pipe;
Packit Service 501009
				break;
Packit Service 501009
			}
Packit Service 501009
Packit Service 501009
			if (multiple_pipes(&p))
Packit Service 501009
				pc->redirect |= REDIRECT_MULTI_PIPE;
Packit Service 501009
Packit Service 501009
			strcpy(pc->pipe_command, p);
Packit Service 501009
			null_first_space(pc->pipe_command);
Packit Service 501009
Packit Service 501009
			pc->redirect |= REDIRECT_TO_PIPE;
Packit Service 501009
Packit Service 501009
			if (!(pc->redirect & REDIRECT_SHELL_COMMAND)) {
Packit Service 501009
				if ((pc->pipe_pid = output_command_to_pids()))
Packit Service 501009
					pc->redirect |= REDIRECT_PID_KNOWN;
Packit Service 501009
				else 
Packit Service 501009
					error(FATAL_RESTART, 
Packit Service 501009
						"pipe operation failed\n");
Packit Service 501009
			}
Packit Service 501009
Packit Service 501009
			return REDIRECT_TO_PIPE;
Packit Service 501009
		}
Packit Service 501009
Packit Service 501009
                if (!(expression || string) && (*p == '>') &&
Packit Service 501009
		    !((p > pc->command_line) && (*(p-1) == '-'))) {
Packit Service 501009
                	append = FALSE;
Packit Service 501009
Packit Service 501009
			*p = NULLCHAR;
Packit Service 501009
			pc->eoc_index = p - pc->command_line;
Packit Service 501009
                        if (*(p+1) == '>') {
Packit Service 501009
                                append = TRUE;
Packit Service 501009
				*p = NULLCHAR;
Packit Service 501009
				p++;
Packit Service 501009
			}
Packit Service 501009
			p++;
Packit Service 501009
			p = strip_beginning_whitespace(p);
Packit Service 501009
Packit Service 501009
                        if (!strlen(p)) {
Packit Service 501009
                                error(INFO, "no file name after %s\n",
Packit Service 501009
					append ? ">>" : ">");
Packit Service 501009
				pc->redirect |= REDIRECT_FAILURE;
Packit Service 501009
                                return REDIRECT_FAILURE;
Packit Service 501009
                        }
Packit Service 501009
Packit Service 501009
			if (pc->flags & IFILE_ERROR)
Packit Service 501009
				append = TRUE;
Packit Service 501009
Packit Service 501009
        		if ((ofile = 
Packit Service 501009
			    fopen(p, append ? "a+" : "w+")) == NULL) {
Packit Service 501009
                		error(INFO, "unable to open %s\n", p);
Packit Service 501009
				pc->redirect = REDIRECT_FAILURE;
Packit Service 501009
				return REDIRECT_FAILURE;
Packit Service 501009
        		}
Packit Service 501009
			setbuf(ofile, NULL);
Packit Service 501009
Packit Service 501009
                        switch (origin)
Packit Service 501009
                        {
Packit Service 501009
                        case FROM_COMMAND_LINE:
Packit Service 501009
                                fp = pc->ofile = ofile;
Packit Service 501009
                                break;
Packit Service 501009
Packit Service 501009
                        case FROM_INPUT_FILE:
Packit Service 501009
                                fp = pc->ifile_ofile = ofile;
Packit Service 501009
                                break;
Packit Service 501009
                        }
Packit Service 501009
Packit Service 501009
			pc->redirect |= REDIRECT_TO_FILE;
Packit Service 501009
			return REDIRECT_TO_FILE;
Packit Service 501009
		}
Packit Service 501009
Packit Service 501009
		p++;
Packit Service 501009
	}
Packit Service 501009
Packit Service 501009
	if ((origin == FROM_COMMAND_LINE) && (pc->flags & TTY) && 
Packit Service 501009
	    (pc->flags & SCROLL) && pc->scroll_command) {
Packit Service 501009
		if (!strlen(pc->command_line) ||
Packit Service 501009
		    STREQ(pc->command_line, "q") ||
Packit Service 501009
		    STREQ(pc->command_line, "Q") ||
Packit Service 501009
		    STREQ(pc->command_line, "exit") ||
Packit Service 501009
		    STRNEQ(pc->command_line, "<")) {
Packit Service 501009
			pc->redirect |= REDIRECT_NOT_DONE;
Packit Service 501009
			return REDIRECT_NOT_DONE;
Packit Service 501009
		}
Packit Service 501009
Packit Service 501009
                if (!setup_stdpipe()) {
Packit Service 501009
                        error(INFO, "cannot open pipe\n");
Packit Service 501009
			pc->redirect |= REDIRECT_FAILURE;
Packit Service 501009
                        return REDIRECT_FAILURE;
Packit Service 501009
                }
Packit Service 501009
                fp = pc->stdpipe;
Packit Service 501009
Packit Service 501009
		pc->redirect |= REDIRECT_TO_STDPIPE;
Packit Service 501009
	
Packit Service 501009
		switch (pc->scroll_command)
Packit Service 501009
		{
Packit Service 501009
		case SCROLL_LESS:
Packit Service 501009
			strcpy(pc->pipe_command, less_argv[0]);
Packit Service 501009
			break;
Packit Service 501009
		case SCROLL_MORE:
Packit Service 501009
			strcpy(pc->pipe_command, more_argv[0]);
Packit Service 501009
			break;
Packit Service 501009
		case SCROLL_CRASHPAGER:
Packit Service 501009
			strcpy(pc->pipe_command, CRASHPAGER_argv[0]);
Packit Service 501009
			break;
Packit Service 501009
		}
Packit Service 501009
Packit Service 501009
                return REDIRECT_TO_STDPIPE;
Packit Service 501009
	}
Packit Service 501009
Packit Service 501009
	pc->redirect |= REDIRECT_NOT_DONE;
Packit Service 501009
Packit Service 501009
	return REDIRECT_NOT_DONE;
Packit Service 501009
}
Packit Service 501009
Packit Service 501009
/*
Packit Service 501009
 *  Find the last command in an input line that possibly contains 
Packit Service 501009
 *  multiple pipes.
Packit Service 501009
 */
Packit Service 501009
int
Packit Service 501009
multiple_pipes(char **input)
Packit Service 501009
{
Packit Service 501009
	char *p, *found;
Packit Service 501009
	int quote;
Packit Service 501009
Packit Service 501009
	found = NULL;
Packit Service 501009
	quote = FALSE;
Packit Service 501009
Packit Service 501009
	for (p = *input; *p; p++) {
Packit Service 501009
		if ((*p == '\'') || (*p == '"')) {
Packit Service 501009
			quote = !quote;
Packit Service 501009
			continue;
Packit Service 501009
		} else if (quote)
Packit Service 501009
			continue;
Packit Service 501009
Packit Service 501009
		if (*p == '|') {
Packit Service 501009
			if (STRNEQ(p, "||"))
Packit Service 501009
				break;
Packit Service 501009
                        found = first_nonspace(p+1);
Packit Service 501009
		}
Packit Service 501009
	}
Packit Service 501009
Packit Service 501009
	if (found) {
Packit Service 501009
		*input = found;
Packit Service 501009
		return TRUE;
Packit Service 501009
	} else
Packit Service 501009
		return FALSE;
Packit Service 501009
}
Packit Service 501009
Packit Service 501009
void
Packit Service 501009
debug_redirect(char *s)
Packit Service 501009
{
Packit Service 501009
	int others;
Packit Service 501009
	int alive;
Packit Service 501009
Packit Service 501009
        others = 0;
Packit Service 501009
        console("%s: (", s);
Packit Service 501009
        if (pc->redirect & FROM_COMMAND_LINE)
Packit Service 501009
                console("%sFROM_COMMAND_LINE", others++ ? "|" : "");
Packit Service 501009
        if (pc->redirect & FROM_INPUT_FILE)
Packit Service 501009
                console("%sFROM_INPUT_FILE", others++ ? "|" : "");
Packit Service 501009
        if (pc->redirect & REDIRECT_NOT_DONE)
Packit Service 501009
                console("%sREDIRECT_NOT_DONE", others++ ? "|" : "");
Packit Service 501009
        if (pc->redirect & REDIRECT_TO_PIPE)
Packit Service 501009
                console("%sREDIRECT_TO_PIPE", others++ ? "|" : "");
Packit Service 501009
        if (pc->redirect & REDIRECT_TO_STDPIPE)
Packit Service 501009
                console("%sREDIRECT_TO_STDPIPE", others++ ? "|" : "");
Packit Service 501009
        if (pc->redirect & REDIRECT_TO_FILE)
Packit Service 501009
                console("%sREDIRECT_TO_FILE", others++ ? "|" : "");
Packit Service 501009
        if (pc->redirect & REDIRECT_FAILURE)
Packit Service 501009
                console("%sREDIRECT_FAILURE", others++ ? "|" : "");
Packit Service 501009
        if (pc->redirect & REDIRECT_SHELL_ESCAPE)
Packit Service 501009
                console("%sREDIRECT_SHELL_ESCAPE", others++ ? "|" : "");
Packit Service 501009
        if (pc->redirect & REDIRECT_SHELL_COMMAND)
Packit Service 501009
                console("%sREDIRECT_SHELL_COMMAND", others++ ? "|" : "");
Packit Service 501009
        if (pc->redirect & REDIRECT_PID_KNOWN)
Packit Service 501009
                console("%sREDIRECT_PID_KNOWN", others++ ? "|" : "");
Packit Service 501009
        if (pc->redirect & REDIRECT_MULTI_PIPE)
Packit Service 501009
                console("%sREDIRECT_MULTI_PIPE", others++ ? "|" : "");
Packit Service 501009
        console(")\n");
Packit Service 501009
Packit Service 501009
	if (pc->pipe_pid || strlen(pc->pipe_command)) {
Packit Service 501009
		if (pc->pipe_pid && PID_ALIVE(pc->pipe_pid))
Packit Service 501009
			alive = TRUE;
Packit Service 501009
		else
Packit Service 501009
			alive = FALSE;
Packit Service 501009
        	console("pipe_pid: %d (%s) pipe_command: %s\n", 
Packit Service 501009
			pc->pipe_pid, 
Packit Service 501009
			alive ? "alive" : "dead",
Packit Service 501009
			pc->pipe_command);
Packit Service 501009
	}
Packit Service 501009
}
Packit Service 501009
Packit Service 501009
/*
Packit Service 501009
 *  Determine whether the pid receiving the current piped output is still
Packit Service 501009
 *  alive. 
Packit Service 501009
 *
Packit Service 501009
 *  NOTE: This routine returns TRUE by default, and only returns FALSE if
Packit Service 501009
 *        the pipe_pid exists *and* it's known to have died.  Therefore the
Packit Service 501009
 *        caller must be cognizant of pc->pipe_pid or pc->stdpipe_pid.
Packit Service 501009
 */ 
Packit Service 501009
int
Packit Service 501009
output_open(void)
Packit Service 501009
{
Packit Service 501009
	int waitstatus, waitret;
Packit Service 501009
Packit Service 501009
	if (!(pc->flags & TTY)) 
Packit Service 501009
		return TRUE;
Packit Service 501009
Packit Service 501009
	switch (pc->redirect & PIPE_OPTIONS)
Packit Service 501009
	{
Packit Service 501009
	case (REDIRECT_TO_STDPIPE|FROM_COMMAND_LINE):
Packit Service 501009
		waitret = waitpid(pc->stdpipe_pid, &waitstatus, WNOHANG);
Packit Service 501009
		if ((waitret == pc->stdpipe_pid) || (waitret == -1))
Packit Service 501009
               		return FALSE;
Packit Service 501009
		break;
Packit Service 501009
Packit Service 501009
	case (REDIRECT_TO_PIPE|FROM_INPUT_FILE):
Packit Service 501009
		if (pc->curcmd_flags & REPEAT)
Packit Service 501009
			break;
Packit Service 501009
		/* FALLTHROUGH */
Packit Service 501009
	case (REDIRECT_TO_PIPE|FROM_COMMAND_LINE):
Packit Service 501009
		switch (pc->redirect & (REDIRECT_MULTI_PIPE)) 
Packit Service 501009
		{
Packit Service 501009
		case REDIRECT_MULTI_PIPE:
Packit Service 501009
			if (!PID_ALIVE(pc->pipe_pid))
Packit Service 501009
				return FALSE;
Packit Service 501009
			break;
Packit Service 501009
Packit Service 501009
		default:
Packit Service 501009
               		waitret = waitpid(pc->pipe_pid, &waitstatus, WNOHANG);
Packit Service 501009
                	if (waitret == pc->pipe_pid) 
Packit Service 501009
                        	return FALSE;
Packit Service 501009
			if (waitret == -1) {  /* intervening sh */
Packit Service 501009
				if (!PID_ALIVE(pc->pipe_pid))
Packit Service 501009
					return FALSE;
Packit Service 501009
			}
Packit Service 501009
			break;
Packit Service 501009
		}
Packit Service 501009
		break;
Packit Service 501009
Packit Service 501009
	default:
Packit Service 501009
		break;
Packit Service 501009
	}
Packit Service 501009
Packit Service 501009
	return TRUE;
Packit Service 501009
}
Packit Service 501009
Packit Service 501009
Packit Service 501009
/*
Packit Service 501009
 *  Determine the pids of the current popen'd shell and output command.
Packit Service 501009
 *  This is all done using /proc; the ps kludge at the bottom of this
Packit Service 501009
 *  routine is legacy, and should only get executed if /proc doesn't exist.
Packit Service 501009
 */
Packit Service 501009
static int
Packit Service 501009
output_command_to_pids(void)
Packit Service 501009
{
Packit Service 501009
	DIR *dirp;
Packit Service 501009
        struct dirent *dp;
Packit Service 501009
	FILE *stp;
Packit Service 501009
        char buf1[BUFSIZE];
Packit Service 501009
        char buf2[BUFSIZE];
Packit Service 501009
        char lookfor[BUFSIZE+2];
Packit Service 501009
        char *pid, *name, *status, *p_pid, *pgrp, *comm;
Packit Service 501009
	char *arglist[MAXARGS];
Packit Service 501009
	int argc;
Packit Service 501009
	FILE *pipe;
Packit Service 501009
	int retries, shell_has_exited;
Packit Service 501009
Packit Service 501009
	retries = 0;
Packit Service 501009
	shell_has_exited = FALSE;
Packit Service 501009
	pc->pipe_pid = pc->pipe_shell_pid = 0;
Packit Service 501009
	comm = strrchr(pc->pipe_command, '/');
Packit Service 501009
	sprintf(lookfor, "(%s)", comm ? ++comm : pc->pipe_command);
Packit Service 501009
	stall(1000);
Packit Service 501009
retry:
Packit Service 501009
        if (is_directory("/proc") && (dirp = opendir("/proc"))) {
Packit Service 501009
                for (dp = readdir(dirp); dp && !pc->pipe_pid; 
Packit Service 501009
		     dp = readdir(dirp)) {
Packit Service 501009
			if (!decimal(dp->d_name, 0))
Packit Service 501009
				continue;
Packit Service 501009
                        sprintf(buf1, "/proc/%s/stat", dp->d_name);
Packit Service 501009
                        if (file_exists(buf1, NULL) && 
Packit Service 501009
			    (stp = fopen(buf1, "r"))) {
Packit Service 501009
                                if (fgets(buf2, BUFSIZE, stp)) {
Packit Service 501009
                                        pid = strtok(buf2, " ");
Packit Service 501009
                                        name = strtok(NULL, " ");
Packit Service 501009
                                        status = strtok(NULL, " ");
Packit Service 501009
                                        p_pid = strtok(NULL, " ");
Packit Service 501009
                                        pgrp = strtok(NULL, " ");
Packit Service 501009
				        if (STREQ(name, "(sh)") &&
Packit Service 501009
					    (atoi(p_pid) == getpid())) { 
Packit Service 501009
						pc->pipe_shell_pid = atoi(pid);
Packit Service 501009
						if (STREQ(status, "Z"))
Packit Service 501009
							shell_has_exited = TRUE;
Packit Service 501009
					}
Packit Service 501009
                                        if (STREQ(name, lookfor) &&
Packit Service 501009
                                            ((atoi(p_pid) == getpid()) ||
Packit Service 501009
				             (atoi(p_pid) == pc->pipe_shell_pid)
Packit Service 501009
			                     || (atoi(pgrp) == getpid()))) {
Packit Service 501009
						pc->pipe_pid = atoi(pid);
Packit Service 501009
						console(
Packit Service 501009
                            "FOUND[%d] (%d->%d->%d) %s %s p_pid: %s pgrp: %s\n",
Packit Service 501009
						    retries, getpid(), 
Packit Service 501009
						    pc->pipe_shell_pid, 
Packit Service 501009
						    pc->pipe_pid,
Packit Service 501009
						    name, status, p_pid, pgrp);
Packit Service 501009
					}  
Packit Service 501009
                                }
Packit Service 501009
				fclose(stp);
Packit Service 501009
                        }
Packit Service 501009
                }
Packit Service 501009
		closedir(dirp);
Packit Service 501009
        }
Packit Service 501009
Packit Service 501009
	if (!pc->pipe_pid && !shell_has_exited && 
Packit Service 501009
	    ((retries++ < 10) || pc->pipe_shell_pid)) {
Packit Service 501009
		stall(1000);
Packit Service 501009
		goto retry;
Packit Service 501009
	}
Packit Service 501009
Packit Service 501009
	console("getpid: %d pipe_shell_pid: %d pipe_pid: %d\n",
Packit Service 501009
		getpid(), pc->pipe_shell_pid, pc->pipe_pid);
Packit Service 501009
Packit Service 501009
	if (pc->pipe_pid)	
Packit Service 501009
		return pc->pipe_pid;
Packit Service 501009
Packit Service 501009
	sprintf(buf1, "ps -ft %s", pc->my_tty);
Packit Service 501009
	console("%s: ", buf1);
Packit Service 501009
Packit Service 501009
	if ((pipe = popen(buf1, "r")) == NULL) {
Packit Service 501009
        	error(INFO, "cannot determine output pid\n");
Packit Service 501009
		return 0;
Packit Service 501009
	}
Packit Service 501009
Packit Service 501009
	while (fgets(buf1, BUFSIZE, pipe)) {
Packit Service 501009
		argc = parse_line(buf1, arglist);
Packit Service 501009
		if ((argc >= 8) && 
Packit Service 501009
		    STREQ(arglist[7], pc->pipe_command) &&
Packit Service 501009
		    STRNEQ(pc->my_tty, arglist[5])) {
Packit Service 501009
			pc->pipe_pid = atoi(arglist[1]);
Packit Service 501009
			break;
Packit Service 501009
		}
Packit Service 501009
	}
Packit Service 501009
	pclose(pipe);
Packit Service 501009
	console("%d\n", pc->pipe_pid);
Packit Service 501009
Packit Service 501009
	return pc->pipe_pid;
Packit Service 501009
}
Packit Service 501009
Packit Service 501009
/*
Packit Service 501009
 *  Close straggling, piped-to, output commands.
Packit Service 501009
 */
Packit Service 501009
void
Packit Service 501009
close_output(void)
Packit Service 501009
{
Packit Service 501009
        if ((pc->flags & TTY) &&
Packit Service 501009
	    (pc->pipe_pid || strlen(pc->pipe_command)) && 
Packit Service 501009
            output_open()) 
Packit Service 501009
                kill(pc->pipe_pid, 9);
Packit Service 501009
}
Packit Service 501009
Packit Service 501009
/*
Packit Service 501009
 *  Initialize what's needed for the command line:
Packit Service 501009
 *
Packit Service 501009
 *   1. termios structures for raw and cooked terminal mode.
Packit Service 501009
 *   2. set up SIGINT and SIGPIPE handlers for aborted commands. 
Packit Service 501009
 *   3. set up the command history table.
Packit Service 501009
 *   4. create the prompt string.
Packit Service 501009
 */
Packit Service 501009
void
Packit Service 501009
cmdline_init(void)
Packit Service 501009
{
Packit Service 501009
	int fd = 0;
Packit Service 501009
Packit Service 501009
	/*
Packit Service 501009
	 *  Stash a copy of the original termios setup. 
Packit Service 501009
         *  Build a raw version for quick use for each command entry.
Packit Service 501009
	 */ 
Packit Service 501009
        if (isatty(fileno(stdin)) && ((fd = open("/dev/tty", O_RDONLY)) >= 0)) {
Packit Service 501009
		if (tcgetattr(fd, &pc->termios_orig) == -1) 
Packit Service 501009
			error(FATAL, "tcgetattr /dev/tty: %s\n", 
Packit Service 501009
				strerror(errno));
Packit Service 501009
Packit Service 501009
                if (tcgetattr(fd, &pc->termios_raw) == -1) 
Packit Service 501009
			error(FATAL, "tcgetattr /dev/tty: %s\n", 
Packit Service 501009
				strerror(errno));
Packit Service 501009
                 
Packit Service 501009
                close(fd);
Packit Service 501009
Packit Service 501009
		pc->termios_raw.c_lflag &= ~ECHO & ~ICANON;
Packit Service 501009
        	pc->termios_raw.c_cc[VMIN] = (char)1;
Packit Service 501009
        	pc->termios_raw.c_cc[VTIME] = (char)0;
Packit Service 501009
Packit Service 501009
		restore_sanity();
Packit Service 501009
Packit Service 501009
		pc->flags |= TTY;
Packit Service 501009
		set_my_tty();
Packit Service 501009
Packit Service 501009
		SIGACTION(SIGINT, restart, &pc->sigaction, NULL);
Packit Service 501009
		readline_init();
Packit Service 501009
        }
Packit Service 501009
        else {
Packit Service 501009
		if (fd < 0)
Packit Service 501009
			error(INFO, "/dev/tty: %s\n", strerror(errno));
Packit Service 501009
		if (!(pc->flags & SILENT))
Packit Service 501009
			fprintf(fp, "NOTE: stdin: not a tty\n\n");
Packit Service 501009
                fflush(fp);
Packit Service 501009
		pc->flags &= ~TTY;
Packit Service 501009
        }
Packit Service 501009
Packit Service 501009
	SIGACTION(SIGPIPE, SIG_IGN, &pc->sigaction, NULL);
Packit Service 501009
Packit Service 501009
	set_command_prompt(NULL);
Packit Service 501009
}
Packit Service 501009
Packit Service 501009
Packit Service 501009
/*
Packit Service 501009
 *  Create and stash the original prompt, but allow changes during runtime.
Packit Service 501009
 */
Packit Service 501009
void
Packit Service 501009
set_command_prompt(char *new_prompt)
Packit Service 501009
{
Packit Service 501009
	static char *orig_prompt = NULL;
Packit Service 501009
Packit Service 501009
	if (!orig_prompt) {
Packit Service 501009
		if (!(orig_prompt = (char *)malloc(strlen(pc->program_name)+3)))
Packit Service 501009
			error(FATAL, "cannot malloc prompt string\n");
Packit Service 501009
		sprintf(orig_prompt, "%s> ", pc->program_name);
Packit Service 501009
	}
Packit Service 501009
Packit Service 501009
	if (new_prompt)
Packit Service 501009
		pc->prompt = new_prompt;
Packit Service 501009
	else
Packit Service 501009
		pc->prompt = orig_prompt;
Packit Service 501009
}
Packit Service 501009
Packit Service 501009
/*
Packit Service 501009
 *  SIGINT, SIGPIPE, and SIGSEGV handler.
Packit Service 501009
 *  Signal number 0 is sent for a generic restart.
Packit Service 501009
 */
Packit Service 501009
#define MAX_RECURSIVE_SIGNALS (10)
Packit Service 501009
#define MAX_SIGINTS_ACCEPTED  (1)
Packit Service 501009
Packit Service 501009
void
Packit Service 501009
restart(int sig)
Packit Service 501009
{
Packit Service 501009
	static int in_restart = 0;
Packit Service 501009
Packit Service 501009
	console("restart (%s) %s\n", signame(sig), 
Packit Service 501009
		pc->flags & IN_GDB ? "(in gdb)" : "(in crash)");
Packit Service 501009
Packit Service 501009
	if (sig == SIGUSR2)
Packit Service 501009
		clean_exit(1);
Packit Service 501009
Packit Service 501009
        if (pc->flags & IN_RESTART) {
Packit Service 501009
                fprintf(stderr, 
Packit Service 501009
		   "\nembedded signal received (%s): recursive restart call\n",
Packit Service 501009
			signame(sig));
Packit Service 501009
		if (++in_restart < MAX_RECURSIVE_SIGNALS) 
Packit Service 501009
			return;
Packit Service 501009
		fprintf(stderr, "bailing out...\n");
Packit Service 501009
               	clean_exit(1);
Packit Service 501009
        } else {
Packit Service 501009
		pc->flags |= IN_RESTART;
Packit Service 501009
		in_restart = 0;
Packit Service 501009
	}
Packit Service 501009
Packit Service 501009
	switch (sig) 
Packit Service 501009
	{
Packit Service 501009
        case SIGSEGV:
Packit Service 501009
		fflush(fp);
Packit Service 501009
                fprintf(stderr, "   <segmentation violation%s>\n",
Packit Service 501009
                        pc->flags & IN_GDB ? " in gdb" : "");
Packit Service 501009
        case 0:
Packit Service 501009
	case SIGPIPE:
Packit Service 501009
                restore_sanity();
Packit Service 501009
                break;
Packit Service 501009
Packit Service 501009
	case SIGINT:
Packit Service 501009
		SIGACTION(SIGINT, restart, &pc->sigaction, NULL);
Packit Service 501009
		pc->flags |= _SIGINT_;
Packit Service 501009
		pc->sigint_cnt++;
Packit Service 501009
		pc->flags &= ~IN_RESTART;
Packit Service 501009
		if (pc->sigint_cnt == MAX_SIGINTS_ACCEPTED) {
Packit Service 501009
			restore_sanity();
Packit Service 501009
			if (pc->ifile_in_progress) {
Packit Service 501009
				pc->ifile_in_progress = 0;
Packit Service 501009
				pc->ifile_offset = 0;
Packit Service 501009
			}
Packit Service 501009
			break;
Packit Service 501009
		}
Packit Service 501009
		return;
Packit Service 501009
Packit Service 501009
	default:
Packit Service 501009
		fprintf(stderr, "unexpected signal received: %s\n", 
Packit Service 501009
			signame(sig));
Packit Service 501009
		restore_sanity();
Packit Service 501009
		close_output();
Packit Service 501009
		break;
Packit Service 501009
	}
Packit Service 501009
Packit Service 501009
	fprintf(stderr, "\n");
Packit Service 501009
Packit Service 501009
	pc->flags &= ~(IN_FOREACH|IN_GDB|IN_RESTART);
Packit Service 501009
	longjmp(pc->main_loop_env, 1);
Packit Service 501009
}
Packit Service 501009
Packit Service 501009
/*
Packit Service 501009
 *  Return a signal name string, or a number if the signal is not listed.
Packit Service 501009
 */
Packit Service 501009
static char *
Packit Service 501009
signame(int sig)
Packit Service 501009
{
Packit Service 501009
	static char sigbuf[20];
Packit Service 501009
Packit Service 501009
	switch (sig)
Packit Service 501009
	{
Packit Service 501009
	case SIGINT:
Packit Service 501009
		sprintf(sigbuf, "SIGINT-%d", pc->sigint_cnt+1);
Packit Service 501009
		return sigbuf;
Packit Service 501009
	case SIGPIPE:
Packit Service 501009
		return "SIGPIPE";
Packit Service 501009
	case SIGSEGV:
Packit Service 501009
		return "SIGSEGV";
Packit Service 501009
	default:
Packit Service 501009
		sprintf(sigbuf, "%d", sig);
Packit Service 501009
		return sigbuf;
Packit Service 501009
	}
Packit Service 501009
}
Packit Service 501009
Packit Service 501009
/*
Packit Service 501009
 *  Restore the program environment to the state it was in before the
Packit Service 501009
 *  last command was executed:  
Packit Service 501009
 *
Packit Service 501009
 *   1. close all temporarily opened pipes and output files.
Packit Service 501009
 *   2. set the terminal back to normal cooked mode.
Packit Service 501009
 *   3. free all temporary buffers.
Packit Service 501009
 *   4. restore the last known output radix.
Packit Service 501009
 */
Packit Service 501009
static void
Packit Service 501009
restore_sanity(void)
Packit Service 501009
{
Packit Service 501009
	int fd, waitstatus;
Packit Service 501009
        struct extension_table *ext;
Packit Service 501009
	struct command_table_entry *cp;
Packit Service 501009
Packit Service 501009
        if (pc->stdpipe) {
Packit Service 501009
		close(fileno(pc->stdpipe));
Packit Service 501009
                pc->stdpipe = NULL;
Packit Service 501009
		if (pc->stdpipe_pid && PID_ALIVE(pc->stdpipe_pid)) {
Packit Service 501009
			while (!waitpid(pc->stdpipe_pid, &waitstatus, WNOHANG))
Packit Service 501009
				stall(1000);
Packit Service 501009
		}
Packit Service 501009
		pc->stdpipe_pid = 0;
Packit Service 501009
        }
Packit Service 501009
	if (pc->pipe) {
Packit Service 501009
		close(fileno(pc->pipe));
Packit Service 501009
	 	pc->pipe = NULL;
Packit Service 501009
		console("wait for redirect %d->%d to finish...\n",
Packit Service 501009
			pc->pipe_shell_pid, pc->pipe_pid);
Packit Service 501009
		if (pc->pipe_pid)
Packit Service 501009
			while (PID_ALIVE(pc->pipe_pid)) {
Packit Service 501009
				waitpid(pc->pipe_pid, &waitstatus, WNOHANG);
Packit Service 501009
				stall(1000);
Packit Service 501009
			}
Packit Service 501009
                if (pc->pipe_shell_pid)
Packit Service 501009
		        while (PID_ALIVE(pc->pipe_shell_pid)) {
Packit Service 501009
                        	waitpid(pc->pipe_shell_pid, 
Packit Service 501009
					&waitstatus, WNOHANG);
Packit Service 501009
				stall(1000);
Packit Service 501009
			}
Packit Service 501009
		pc->pipe_pid = 0;
Packit Service 501009
	}
Packit Service 501009
	if (pc->ifile_pipe) {
Packit Service 501009
		fflush(pc->ifile_pipe);
Packit Service 501009
		close(fileno(pc->ifile_pipe));
Packit Service 501009
		pc->ifile_pipe = NULL;
Packit Service 501009
        	if (pc->pipe_pid &&
Packit Service 501009
            	    ((pc->redirect & (PIPE_OPTIONS|REDIRECT_PID_KNOWN)) ==
Packit Service 501009
                    (FROM_INPUT_FILE|REDIRECT_TO_PIPE|REDIRECT_PID_KNOWN))) {
Packit Service 501009
			console("wait for redirect %d->%d to finish...\n",
Packit Service 501009
				pc->pipe_shell_pid, pc->pipe_pid);
Packit Service 501009
                	while (PID_ALIVE(pc->pipe_pid)) {
Packit Service 501009
				waitpid(pc->pipe_pid, &waitstatus, WNOHANG);
Packit Service 501009
				stall(1000);
Packit Service 501009
			}
Packit Service 501009
                        if (pc->pipe_shell_pid) 
Packit Service 501009
                                while (PID_ALIVE(pc->pipe_shell_pid)) {
Packit Service 501009
                                        waitpid(pc->pipe_shell_pid,
Packit Service 501009
                                                &waitstatus, WNOHANG);
Packit Service 501009
					stall(1000);
Packit Service 501009
				}
Packit Service 501009
			if (pc->redirect & (REDIRECT_MULTI_PIPE))
Packit Service 501009
				wait_for_children(ALL_CHILDREN);
Packit Service 501009
		}
Packit Service 501009
	}
Packit Service 501009
Packit Service 501009
	if (pc->ofile) {
Packit Service 501009
		fclose(pc->ofile);
Packit Service 501009
		pc->ofile = NULL;
Packit Service 501009
	}
Packit Service 501009
	if (pc->ifile_ofile) {
Packit Service 501009
		fclose(pc->ifile_ofile);
Packit Service 501009
		pc->ifile_ofile = NULL;
Packit Service 501009
	}
Packit Service 501009
Packit Service 501009
	if (pc->ifile) {
Packit Service 501009
		fclose(pc->ifile);
Packit Service 501009
		pc->ifile = NULL;
Packit Service 501009
	}
Packit Service 501009
Packit Service 501009
        if (pc->args_ifile) {
Packit Service 501009
                fclose(pc->args_ifile);
Packit Service 501009
                pc->args_ifile = NULL;
Packit Service 501009
        }
Packit Service 501009
Packit Service 501009
	if (pc->tmpfile)
Packit Service 501009
		close_tmpfile();
Packit Service 501009
Packit Service 501009
	if (pc->tmpfile2)
Packit Service 501009
		close_tmpfile2();
Packit Service 501009
Packit Service 501009
	if (pc->cmd_cleanup)
Packit Service 501009
		pc->cmd_cleanup(pc->cmd_cleanup_arg);
Packit Service 501009
Packit Service 501009
	if (pc->flags & TTY) {
Packit Service 501009
		if ((fd = open("/dev/tty", O_RDONLY)) < 0) {
Packit Service 501009
			console("/dev/tty: %s\n", strerror(errno));
Packit Service 501009
			clean_exit(1);
Packit Service 501009
		}
Packit Service 501009
	        
Packit Service 501009
	        if (tcsetattr(fd, TCSANOW, &pc->termios_orig) == -1) 
Packit Service 501009
                        error(FATAL, "tcsetattr /dev/tty: %s\n",
Packit Service 501009
                                strerror(errno));
Packit Service 501009
	        
Packit Service 501009
		close(fd);
Packit Service 501009
	}
Packit Service 501009
Packit Service 501009
	wait_for_children(ZOMBIES_ONLY);
Packit Service 501009
Packit Service 501009
	pc->flags &= ~(INIT_IFILE|RUNTIME_IFILE|IFILE_ERROR|_SIGINT_|PLEASE_WAIT);
Packit Service 501009
	pc->sigint_cnt = 0;
Packit Service 501009
	pc->redirect = 0;
Packit Service 501009
	pc->pipe_command[0] = NULLCHAR;
Packit Service 501009
	pc->pipe_pid = 0;
Packit Service 501009
	pc->pipe_shell_pid = 0;
Packit Service 501009
	pc->sbrk = sbrk(0);
Packit Service 501009
	if ((pc->curcmd_flags & (UD2A_INSTRUCTION|BAD_INSTRUCTION)) ==
Packit Service 501009
		(UD2A_INSTRUCTION|BAD_INSTRUCTION))
Packit Service 501009
		error(WARNING, "A (bad) instruction was noted in last disassembly.\n"
Packit Service 501009
                     "         Use \"dis -b [number]\" to set/restore the number of\n"
Packit Service 501009
                     "         encoded bytes to skip after a ud2a (BUG) instruction.\n");
Packit Service 501009
	pc->curcmd_flags = 0;
Packit Service 501009
	pc->curcmd_private = 0;
Packit Service 501009
Packit Service 501009
	restore_gdb_sanity();
Packit Service 501009
Packit Service 501009
	free_all_bufs();
Packit Service 501009
Packit Service 501009
	/*
Packit Service 501009
	 *  Clear the structure cache references -- no-ops if DUMPFILE().
Packit Service 501009
	 */
Packit Service 501009
	clear_task_cache();
Packit Service 501009
	clear_machdep_cache();
Packit Service 501009
	clear_swap_info_cache();
Packit Service 501009
	clear_file_cache();
Packit Service 501009
	clear_dentry_cache();
Packit Service 501009
	clear_inode_cache();
Packit Service 501009
	clear_vma_cache();
Packit Service 501009
	clear_active_set();
Packit Service 501009
Packit Service 501009
	if (kt->ikconfig_flags & IKCONFIG_LOADED)
Packit Service 501009
		read_in_kernel_config(IKCFG_FREE);
Packit Service 501009
Packit Service 501009
	/*
Packit Service 501009
	 *  Call the cleanup() function of any extension.
Packit Service 501009
	 */
Packit Service 501009
        for (ext = extension_table; ext; ext = ext->next) {
Packit Service 501009
                for (cp = ext->command_table; cp->name; cp++) {
Packit Service 501009
                        if (cp->flags & CLEANUP)
Packit Service 501009
                                (*cp->func)();
Packit Service 501009
		}
Packit Service 501009
        }
Packit Service 501009
Packit Service 501009
	if (CRASHDEBUG(5)) {
Packit Service 501009
                dump_filesys_table(0);
Packit Service 501009
		dump_vma_cache(0);
Packit Service 501009
		dump_text_value_cache(0);
Packit Service 501009
	}
Packit Service 501009
	
Packit Service 501009
	if (REMOTE())
Packit Service 501009
		remote_clear_pipeline();
Packit Service 501009
Packit Service 501009
	hq_close();
Packit Service 501009
}
Packit Service 501009
Packit Service 501009
/*
Packit Service 501009
 *  Similar to above, but only called in between each command that is
Packit Service 501009
 *  read from an input file.
Packit Service 501009
 */
Packit Service 501009
static void
Packit Service 501009
restore_ifile_sanity(void)
Packit Service 501009
{
Packit Service 501009
        int fd;
Packit Service 501009
Packit Service 501009
	pc->flags &= ~IFILE_ERROR;
Packit Service 501009
Packit Service 501009
        if (pc->ifile_pipe) {
Packit Service 501009
		close(fileno(pc->ifile_pipe));
Packit Service 501009
                pc->ifile_pipe = NULL;
Packit Service 501009
        }
Packit Service 501009
Packit Service 501009
        if (pc->ifile_ofile) {
Packit Service 501009
                fclose(pc->ifile_ofile);
Packit Service 501009
                pc->ifile_ofile = NULL;
Packit Service 501009
        }
Packit Service 501009
Packit Service 501009
        if (pc->flags & TTY) {
Packit Service 501009
                if ((fd = open("/dev/tty", O_RDONLY)) < 0) {
Packit Service 501009
                        console("/dev/tty: %s\n", strerror(errno));
Packit Service 501009
                        clean_exit(1);
Packit Service 501009
                }
Packit Service 501009
 
Packit Service 501009
                if (tcsetattr(fd, TCSANOW, &pc->termios_orig) == -1) 
Packit Service 501009
			error(FATAL, "tcsetattr /dev/tty: %s\n",
Packit Service 501009
                                strerror(errno));
Packit Service 501009
                
Packit Service 501009
                close(fd);
Packit Service 501009
        }
Packit Service 501009
Packit Service 501009
	if (pc->tmpfile2) {
Packit Service 501009
		close_tmpfile2();
Packit Service 501009
	}
Packit Service 501009
Packit Service 501009
	restore_gdb_sanity();
Packit Service 501009
Packit Service 501009
	free_all_bufs();
Packit Service 501009
Packit Service 501009
	hq_close();
Packit Service 501009
}
Packit Service 501009
Packit Service 501009
/*
Packit Service 501009
 *  Check whether a SIGINT was received during the execution of a command,
Packit Service 501009
 *  clearing the flag if it was set.  This allows individual commands or
Packit Service 501009
 *  entities to do whatever is appropriate to handle CTRL-C.
Packit Service 501009
 */
Packit Service 501009
int
Packit Service 501009
received_SIGINT(void)
Packit Service 501009
{
Packit Service 501009
	if (pc->flags & _SIGINT_) {
Packit Service 501009
		pc->flags &= ~_SIGINT_;
Packit Service 501009
		pc->sigint_cnt = 0;
Packit Service 501009
		if (pc->ifile_in_progress) {
Packit Service 501009
			pc->ifile_in_progress = 0;
Packit Service 501009
			pc->ifile_offset = 0;
Packit Service 501009
		}
Packit Service 501009
		return TRUE;
Packit Service 501009
	} else 
Packit Service 501009
		return FALSE;
Packit Service 501009
}
Packit Service 501009
Packit Service 501009
Packit Service 501009
/*
Packit Service 501009
 *  Look for an executable file that begins with #!
Packit Service 501009
 */
Packit Service 501009
static int
Packit Service 501009
is_shell_script(char *s)
Packit Service 501009
{
Packit Service 501009
        int fd;
Packit Service 501009
        char interp[2];
Packit Service 501009
        struct stat sbuf;
Packit Service 501009
Packit Service 501009
        if ((fd = open(s, O_RDONLY)) < 0) 
Packit Service 501009
                return FALSE;
Packit Service 501009
        
Packit Service 501009
        if (isatty(fd)) {
Packit Service 501009
                close(fd);
Packit Service 501009
                return FALSE;
Packit Service 501009
	}
Packit Service 501009
        
Packit Service 501009
        if (read(fd, interp, 2) != 2) {
Packit Service 501009
                close(fd);
Packit Service 501009
                return FALSE;
Packit Service 501009
        }
Packit Service 501009
Packit Service 501009
        if (!STRNEQ(interp, "#!")) {
Packit Service 501009
                close(fd);
Packit Service 501009
                return FALSE;
Packit Service 501009
        }
Packit Service 501009
Packit Service 501009
        close(fd);
Packit Service 501009
Packit Service 501009
        if (stat(s, &sbuf) == -1) 
Packit Service 501009
		return FALSE;
Packit Service 501009
Packit Service 501009
        if (!(sbuf.st_mode & (S_IXUSR|S_IXGRP|S_IXOTH))) 
Packit Service 501009
		return FALSE;
Packit Service 501009
        
Packit Service 501009
        return TRUE;
Packit Service 501009
}
Packit Service 501009
Packit Service 501009
/*
Packit Service 501009
 *  After verifying the user's input file, loop through each line, executing
Packit Service 501009
 *  one command at a time.  This command pretty much does the same as
Packit Service 501009
 *  get_command_line(), but also kicks off the command execution as well.  
Packit Service 501009
 *  It's kept self-contained, as indicated by the RUNTIME_IFILE flag, and 
Packit Service 501009
 *  keeps its own internal sanity by calling restore_ifile_sanity() between 
Packit Service 501009
 *  each line.
Packit Service 501009
 */ 
Packit Service 501009
void
Packit Service 501009
exec_input_file(void)
Packit Service 501009
{
Packit Service 501009
        char *file;
Packit Service 501009
	FILE *incoming_fp;
Packit Service 501009
        char buf[BUFSIZE];
Packit Service 501009
	ulong this;
Packit Service 501009
Packit Service 501009
	/*
Packit Service 501009
	 *  Do start-up .rc or input files in the proper order.
Packit Service 501009
	 */
Packit Service 501009
	if (pc->flags & RCHOME_IFILE) {
Packit Service 501009
		this = RCHOME_IFILE;
Packit Service 501009
		pc->flags &= ~RCHOME_IFILE;
Packit Service 501009
	} else if (pc->flags & RCLOCAL_IFILE) {
Packit Service 501009
		this = RCLOCAL_IFILE;
Packit Service 501009
		pc->flags &= ~RCLOCAL_IFILE;
Packit Service 501009
	} else if (pc->flags & CMDLINE_IFILE) {
Packit Service 501009
		this = CMDLINE_IFILE;
Packit Service 501009
		pc->flags &= ~CMDLINE_IFILE;
Packit Service 501009
	} else
Packit Service 501009
		this = 0;
Packit Service 501009
Packit Service 501009
        if (pc->flags & RUNTIME_IFILE) {
Packit Service 501009
                error(INFO, "embedded input files not allowed!\n");
Packit Service 501009
                return;
Packit Service 501009
        }
Packit Service 501009
Packit Service 501009
        if (argcnt < 2) {
Packit Service 501009
                error(INFO, "no input file entered!\n");
Packit Service 501009
                return;
Packit Service 501009
        } else
Packit Service 501009
                file = args[1];
Packit Service 501009
Packit Service 501009
        if (!file_exists(file, NULL)) {
Packit Service 501009
                error(INFO, "%s: %s\n", file, strerror(ENOENT));
Packit Service 501009
                return;
Packit Service 501009
        }
Packit Service 501009
Packit Service 501009
        if (is_elf_file(file)) {
Packit Service 501009
                error(INFO, "input from executable files not supported yet!\n");
Packit Service 501009
                return;
Packit Service 501009
        }
Packit Service 501009
Packit Service 501009
        if (is_shell_script(file)) {
Packit Service 501009
                error(INFO, "input from shell scripts not supported yet!\n");
Packit Service 501009
                return;
Packit Service 501009
        }
Packit Service 501009
Packit Service 501009
        if ((pc->ifile = fopen(file, "r")) == NULL) {
Packit Service 501009
                error(INFO, "%s: %s\n", file, strerror(errno));
Packit Service 501009
                return;
Packit Service 501009
        }
Packit Service 501009
Packit Service 501009
        pc->flags |= RUNTIME_IFILE;
Packit Service 501009
	incoming_fp = fp;
Packit Service 501009
Packit Service 501009
	/*
Packit Service 501009
	 *  Handle runtime commands that use input files.
Packit Service 501009
	 */
Packit Service 501009
	if ((pc->ifile_in_progress = this) == 0) {
Packit Service 501009
		if (!pc->runtime_ifile_cmd) {
Packit Service 501009
			if (!(pc->runtime_ifile_cmd = (char *)malloc(BUFSIZE))) {
Packit Service 501009
				error(INFO, 
Packit Service 501009
				    "cannot malloc input file command line buffer\n");
Packit Service 501009
				return;
Packit Service 501009
			}
Packit Service 501009
			BZERO(pc->runtime_ifile_cmd, BUFSIZE);
Packit Service 501009
		}
Packit Service 501009
		if (!strlen(pc->runtime_ifile_cmd))
Packit Service 501009
			strcpy(pc->runtime_ifile_cmd, pc->orig_line);
Packit Service 501009
		pc->ifile_in_progress = RUNTIME_IFILE;
Packit Service 501009
	}
Packit Service 501009
Packit Service 501009
	/*
Packit Service 501009
	 *  If there's an offset, then there was a FATAL error caused
Packit Service 501009
	 *  by the last command executed from the input file.
Packit Service 501009
	 */
Packit Service 501009
	if (pc->ifile_offset)
Packit Service 501009
		fseek(pc->ifile, (long)pc->ifile_offset, SEEK_SET);
Packit Service 501009
Packit Service 501009
        while (fgets(buf, BUFSIZE-1, pc->ifile)) {
Packit Service 501009
                /*
Packit Service 501009
                 *  Restore normal environment.
Packit Service 501009
                 */
Packit Service 501009
                fp = incoming_fp;
Packit Service 501009
		restore_ifile_sanity();
Packit Service 501009
        	BZERO(pc->command_line, BUFSIZE);
Packit Service 501009
        	BZERO(pc->orig_line, BUFSIZE);
Packit Service 501009
		if (this & (RCHOME_IFILE|RCLOCAL_IFILE))
Packit Service 501009
			pc->curcmd_flags |= FROM_RCFILE;
Packit Service 501009
Packit Service 501009
		pc->ifile_offset = ftell(pc->ifile);
Packit Service 501009
Packit Service 501009
		if (STRNEQ(buf, "#") || STREQ(buf, "\n"))
Packit Service 501009
			continue;
Packit Service 501009
Packit Service 501009
                check_special_handling(buf);
Packit Service 501009
                strcpy(pc->command_line, buf);
Packit Service 501009
                clean_line(pc->command_line);
Packit Service 501009
                strcpy(pc->orig_line, pc->command_line);
Packit Service 501009
		strip_linefeeds(pc->orig_line);
Packit Service 501009
		resolve_aliases();
Packit Service 501009
Packit Service 501009
	        switch (setup_redirect(FROM_INPUT_FILE))
Packit Service 501009
	        {
Packit Service 501009
	        case REDIRECT_NOT_DONE:
Packit Service 501009
	        case REDIRECT_TO_PIPE:
Packit Service 501009
	        case REDIRECT_TO_FILE:
Packit Service 501009
	                break;
Packit Service 501009
	
Packit Service 501009
		case REDIRECT_SHELL_ESCAPE:
Packit Service 501009
		case REDIRECT_SHELL_COMMAND:
Packit Service 501009
			continue;
Packit Service 501009
Packit Service 501009
	        case REDIRECT_FAILURE:
Packit Service 501009
	                goto done_input;
Packit Service 501009
	        }
Packit Service 501009
Packit Service 501009
		if (CRASHDEBUG(1))
Packit Service 501009
			console(buf);
Packit Service 501009
Packit Service 501009
		if (!(argcnt = parse_line(pc->command_line, args)))
Packit Service 501009
			continue;
Packit Service 501009
Packit Service 501009
                if (!(pc->flags & SILENT)) {
Packit Service 501009
                        fprintf(fp, "%s%s", pc->prompt, buf);
Packit Service 501009
                        fflush(fp);
Packit Service 501009
                }
Packit Service 501009
Packit Service 501009
                exec_command();
Packit Service 501009
Packit Service 501009
		if (received_SIGINT())
Packit Service 501009
			goto done_input;
Packit Service 501009
        }
Packit Service 501009
Packit Service 501009
done_input:
Packit Service 501009
Packit Service 501009
        fclose(pc->ifile);
Packit Service 501009
        pc->ifile = NULL;
Packit Service 501009
        pc->flags &= ~RUNTIME_IFILE;
Packit Service 501009
	pc->ifile_offset = 0;
Packit Service 501009
	if (pc->runtime_ifile_cmd)
Packit Service 501009
		BZERO(pc->runtime_ifile_cmd, BUFSIZE);
Packit Service 501009
	pc->ifile_in_progress = 0;
Packit Service 501009
}
Packit Service 501009
Packit Service 501009
/*
Packit Service 501009
 *  Prime the alias list with a few built-in's.
Packit Service 501009
 */
Packit Service 501009
void
Packit Service 501009
alias_init(char *inbuf)
Packit Service 501009
{
Packit Service 501009
	char buf[BUFSIZE];
Packit Service 501009
Packit Service 501009
	if (inbuf) {
Packit Service 501009
		strcpy(buf, inbuf);
Packit Service 501009
		argcnt = parse_line(buf, args);
Packit Service 501009
		allocate_alias(ALIAS_BUILTIN);
Packit Service 501009
		return;
Packit Service 501009
	}
Packit Service 501009
Packit Service 501009
	strcpy(buf, "alias man help");
Packit Service 501009
	argcnt = parse_line(buf, args);
Packit Service 501009
	allocate_alias(ALIAS_BUILTIN);
Packit Service 501009
Packit Service 501009
        strcpy(buf, "alias ? help");
Packit Service 501009
        argcnt = parse_line(buf, args);
Packit Service 501009
        allocate_alias(ALIAS_BUILTIN);
Packit Service 501009
Packit Service 501009
        strcpy(buf, "alias quit q");
Packit Service 501009
        argcnt = parse_line(buf, args);
Packit Service 501009
        allocate_alias(ALIAS_BUILTIN);
Packit Service 501009
Packit Service 501009
	strcpy(buf, "alias sf set scroll off");
Packit Service 501009
        argcnt = parse_line(buf, args);
Packit Service 501009
        allocate_alias(ALIAS_BUILTIN);
Packit Service 501009
Packit Service 501009
	strcpy(buf, "alias sn set scroll on");
Packit Service 501009
        argcnt = parse_line(buf, args);
Packit Service 501009
        allocate_alias(ALIAS_BUILTIN);
Packit Service 501009
Packit Service 501009
	strcpy(buf, "alias hex set radix 16");
Packit Service 501009
        argcnt = parse_line(buf, args);
Packit Service 501009
        allocate_alias(ALIAS_BUILTIN);
Packit Service 501009
Packit Service 501009
        strcpy(buf, "alias dec set radix 10");
Packit Service 501009
        argcnt = parse_line(buf, args);
Packit Service 501009
        allocate_alias(ALIAS_BUILTIN);
Packit Service 501009
Packit Service 501009
        strcpy(buf, "alias g gdb");
Packit Service 501009
        argcnt = parse_line(buf, args);
Packit Service 501009
        allocate_alias(ALIAS_BUILTIN);
Packit Service 501009
Packit Service 501009
        strcpy(buf, "alias px p -x");
Packit Service 501009
        argcnt = parse_line(buf, args);
Packit Service 501009
        allocate_alias(ALIAS_BUILTIN);
Packit Service 501009
Packit Service 501009
        strcpy(buf, "alias pd p -d");
Packit Service 501009
        argcnt = parse_line(buf, args);
Packit Service 501009
        allocate_alias(ALIAS_BUILTIN);
Packit Service 501009
Packit Service 501009
	strcpy(buf, "alias for foreach");
Packit Service 501009
        argcnt = parse_line(buf, args);
Packit Service 501009
        allocate_alias(ALIAS_BUILTIN);
Packit Service 501009
Packit Service 501009
	strcpy(buf, "alias size *");
Packit Service 501009
        argcnt = parse_line(buf, args);
Packit Service 501009
        allocate_alias(ALIAS_BUILTIN);
Packit Service 501009
Packit Service 501009
        strcpy(buf, "alias dmesg log");
Packit Service 501009
        argcnt = parse_line(buf, args);
Packit Service 501009
        allocate_alias(ALIAS_BUILTIN);
Packit Service 501009
Packit Service 501009
        strcpy(buf, "alias lsmod mod");
Packit Service 501009
        argcnt = parse_line(buf, args);
Packit Service 501009
        allocate_alias(ALIAS_BUILTIN);
Packit Service 501009
}
Packit Service 501009
Packit Service 501009
/*
Packit Service 501009
 *  Before the command line is parsed, take a snapshot and parse the snapshot.
Packit Service 501009
 *  If args[0] is an known alias, recreate the pc->command_line string with 
Packit Service 501009
 *  the alias substitution.
Packit Service 501009
 */
Packit Service 501009
static void
Packit Service 501009
resolve_aliases(void)
Packit Service 501009
{
Packit Service 501009
	int i;
Packit Service 501009
	struct alias_data *ad;
Packit Service 501009
	int found;
Packit Service 501009
	char *p1, *remainder;
Packit Service 501009
	char buf1[BUFSIZE];
Packit Service 501009
	char buf2[BUFSIZE];
Packit Service 501009
Packit Service 501009
	if (!strlen(pc->command_line))
Packit Service 501009
		return;
Packit Service 501009
Packit Service 501009
	strcpy(buf1, pc->command_line);
Packit Service 501009
	argcnt = parse_line(buf1, args);
Packit Service 501009
Packit Service 501009
	if (argcnt > 1) {
Packit Service 501009
		strcpy(buf2, &pc->command_line[args[1] - buf1]);
Packit Service 501009
		remainder = buf2;
Packit Service 501009
	} else
Packit Service 501009
		remainder = NULL;
Packit Service 501009
Packit Service 501009
	found = FALSE;
Packit Service 501009
	for (ad = alias_head.next; ad; ad = ad->next) {
Packit Service 501009
		if (STREQ(ad->alias, args[0])) {
Packit Service 501009
                        for (i = 0; i < ad->argcnt; i++)
Packit Service 501009
                                args[i] = ad->args[i];
Packit Service 501009
			found = TRUE;
Packit Service 501009
			break;
Packit Service 501009
		}
Packit Service 501009
	}
Packit Service 501009
Packit Service 501009
	if (!found)
Packit Service 501009
		return;
Packit Service 501009
Packit Service 501009
	BZERO(pc->command_line, BUFSIZE);
Packit Service 501009
	p1 = pc->command_line;
Packit Service 501009
Packit Service 501009
	for (i = 0; i < ad->argcnt; i++) {
Packit Service 501009
		snprintf(p1, BUFSIZE - (p1-pc->command_line), "%s ", args[i]);
Packit Service 501009
		while (*p1)
Packit Service 501009
			p1++;
Packit Service 501009
                if ((p1 - pc->command_line) >= BUFSIZE) 
Packit Service 501009
                        break;
Packit Service 501009
	}
Packit Service 501009
        if (remainder) {
Packit Service 501009
                if ((strlen(remainder)+strlen(pc->command_line)) < BUFSIZE) 
Packit Service 501009
                        strcat(pc->command_line, remainder);
Packit Service 501009
                else 
Packit Service 501009
                        error(INFO, "command line overflow.\n");
Packit Service 501009
        } else if (strlen(pc->command_line) >= (BUFSIZE-1)) 
Packit Service 501009
                error(INFO, "command line overflow.\n");
Packit Service 501009
Packit Service 501009
	clean_line(pc->command_line);
Packit Service 501009
}
Packit Service 501009
Packit Service 501009
/*
Packit Service 501009
 *  If input string is an alias, return a pointer to the alias_data struct.
Packit Service 501009
 */
Packit Service 501009
struct alias_data *
Packit Service 501009
is_alias(char *s)
Packit Service 501009
{
Packit Service 501009
        struct alias_data *ad;
Packit Service 501009
Packit Service 501009
        for (ad = alias_head.next; ad; ad = ad->next) {
Packit Service 501009
		if (STREQ(ad->alias, s)) 
Packit Service 501009
			return(ad);
Packit Service 501009
	}
Packit Service 501009
	return NULL;
Packit Service 501009
}
Packit Service 501009
Packit Service 501009
/*
Packit Service 501009
 *  .rc file commands that are "set" commands may be performed prior 
Packit Service 501009
 *  to initialization, so pass them to cmd_set() for consideration.  
Packit Service 501009
 *  All other commands are flagged for execution by exec_input_file()
Packit Service 501009
 *  after session initialization is complete.
Packit Service 501009
 */
Packit Service 501009
void
Packit Service 501009
resolve_rc_cmd(char *s, int origin)
Packit Service 501009
{
Packit Service 501009
	clean_line(s);
Packit Service 501009
Packit Service 501009
	if (*s == '#')
Packit Service 501009
		return;
Packit Service 501009
Packit Service 501009
	if ((argcnt = parse_line(s, args)) == 0)
Packit Service 501009
		return;
Packit Service 501009
Packit Service 501009
	if (STREQ(args[0], "set")) {
Packit Service 501009
		optind = 0;
Packit Service 501009
		cmd_set();
Packit Service 501009
	}
Packit Service 501009
Packit Service 501009
	switch (origin)
Packit Service 501009
	{
Packit Service 501009
	case ALIAS_RCHOME:
Packit Service 501009
		pc->flags |= RCHOME_IFILE;
Packit Service 501009
		break;
Packit Service 501009
	case ALIAS_RCLOCAL:
Packit Service 501009
		pc->flags |= RCLOCAL_IFILE;
Packit Service 501009
		break;
Packit Service 501009
	}
Packit Service 501009
Packit Service 501009
	return;
Packit Service 501009
}
Packit Service 501009
Packit Service 501009
Packit Service 501009
/*
Packit Service 501009
 *  The "alias" command.  With no arguments, list all aliases. With one
Packit Service 501009
 *  argument -- which must be an alias -- display the string it's aliased to.
Packit Service 501009
 *  With two or more arguments, setup a new alias, where the first argument
Packit Service 501009
 *  is the alias, and the remaining arguments make up the alias string.
Packit Service 501009
 *  If the second arg is the NULL string "", delete the alias.
Packit Service 501009
 */   
Packit Service 501009
void
Packit Service 501009
cmd_alias(void)
Packit Service 501009
{
Packit Service 501009
	if (argerrs)
Packit Service 501009
		cmd_usage(pc->curcmd, SYNOPSIS);
Packit Service 501009
Packit Service 501009
	switch (argcnt)
Packit Service 501009
	{
Packit Service 501009
	case 1:
Packit Service 501009
		list_aliases(NULL);
Packit Service 501009
		break;
Packit Service 501009
Packit Service 501009
	case 2:
Packit Service 501009
		list_aliases(args[1]);
Packit Service 501009
		break;
Packit Service 501009
	
Packit Service 501009
	default:
Packit Service 501009
		if (allocate_alias(ALIAS_RUNTIME))
Packit Service 501009
			list_aliases(args[1]);
Packit Service 501009
		break;
Packit Service 501009
	}
Packit Service 501009
}
Packit Service 501009
Packit Service 501009
/*
Packit Service 501009
 *  Dump the current set of aliases.
Packit Service 501009
 */
Packit Service 501009
static void
Packit Service 501009
list_aliases(char *s)
Packit Service 501009
{
Packit Service 501009
	int i;
Packit Service 501009
        struct alias_data *ad;
Packit Service 501009
	int found, precision;
Packit Service 501009
	char buf[BUFSIZE];
Packit Service 501009
Packit Service 501009
	if (!alias_head.next) {
Packit Service 501009
		error(INFO, "alias list is empty\n");
Packit Service 501009
		return;
Packit Service 501009
	}
Packit Service 501009
Packit Service 501009
	BZERO(buf, BUFSIZE);
Packit Service 501009
	found = FALSE;
Packit Service 501009
	precision = 7;
Packit Service 501009
Packit Service 501009
        for (ad = alias_head.next; ad; ad = ad->next) {
Packit Service 501009
                switch (ad->origin)
Packit Service 501009
		{
Packit Service 501009
                case ALIAS_RCLOCAL:
Packit Service 501009
                        sprintf(buf, ".%src", pc->program_name);
Packit Service 501009
			if (strlen(buf) > precision)
Packit Service 501009
				precision = strlen(buf);
Packit Service 501009
                        break;
Packit Service 501009
                case ALIAS_RCHOME:
Packit Service 501009
                        sprintf(buf, "$HOME/.%src", pc->program_name);
Packit Service 501009
			if (strlen(buf) > precision)
Packit Service 501009
				precision = strlen(buf);
Packit Service 501009
			break;
Packit Service 501009
		}
Packit Service 501009
	}
Packit Service 501009
Packit Service 501009
	fprintf(fp, "ORIGIN");
Packit Service 501009
	pad_line(fp, precision-6, ' ');
Packit Service 501009
Packit Service 501009
	BZERO(buf, BUFSIZE);
Packit Service 501009
	fprintf(fp, "  ALIAS    COMMAND\n");
Packit Service 501009
Packit Service 501009
        for (ad = alias_head.next; ad; ad = ad->next) {
Packit Service 501009
		if (s && !STREQ(s, ad->alias))
Packit Service 501009
			continue;
Packit Service 501009
Packit Service 501009
		found = TRUE;
Packit Service 501009
Packit Service 501009
                switch (ad->origin)
Packit Service 501009
                {
Packit Service 501009
                case ALIAS_RUNTIME:
Packit Service 501009
                        sprintf(buf, "runtime");
Packit Service 501009
                        break;
Packit Service 501009
                case ALIAS_RCLOCAL:
Packit Service 501009
                        sprintf(buf, ".%src", pc->program_name);
Packit Service 501009
                        break;
Packit Service 501009
                case ALIAS_RCHOME:
Packit Service 501009
                        sprintf(buf, "$HOME/.%src", pc->program_name);
Packit Service 501009
                        break;
Packit Service 501009
                case ALIAS_BUILTIN:
Packit Service 501009
                        sprintf(buf, "builtin");
Packit Service 501009
                        break;
Packit Service 501009
                }
Packit Service 501009
Packit Service 501009
		fprintf(fp, "%s  ", buf);
Packit Service 501009
		pad_line(fp, precision-strlen(buf), ' ');
Packit Service 501009
Packit Service 501009
                fprintf(fp, "%-7s  ", ad->alias);
Packit Service 501009
Packit Service 501009
		for (i = 0; i < ad->argcnt; i++) {
Packit Service 501009
			fprintf(fp, "%s ", ad->args[i]);
Packit Service 501009
		}
Packit Service 501009
		fprintf(fp, "\n");
Packit Service 501009
	}
Packit Service 501009
Packit Service 501009
	if (s && !found)
Packit Service 501009
		fprintf(fp, "alias does not exist: %s\n", s);
Packit Service 501009
		
Packit Service 501009
}
Packit Service 501009
Packit Service 501009
/*
Packit Service 501009
 *  Verify the alias request set up in the args[] array: 
Packit Service 501009
 *
Packit Service 501009
 *    1. make sure that the alias string starts with a legitimate command.
Packit Service 501009
 *    2. if the already exists, deallocate its current version.
Packit Service 501009
 *   
Packit Service 501009
 *  Then malloc space for the alias string, and link it in to the alias list.
Packit Service 501009
 */
Packit Service 501009
static int
Packit Service 501009
allocate_alias(int origin)
Packit Service 501009
{
Packit Service 501009
	int i;
Packit Service 501009
	int size;
Packit Service 501009
        struct alias_data *ad;
Packit Service 501009
        struct alias_data *newad;
Packit Service 501009
	char *p1, *enclosed_string;
Packit Service 501009
	int found;
Packit Service 501009
Packit Service 501009
	if ((enclosed_string = strstr(args[2], " ")))
Packit Service 501009
		*enclosed_string = NULLCHAR;
Packit Service 501009
Packit Service 501009
	found = FALSE;
Packit Service 501009
Packit Service 501009
	if (get_command_table_entry(args[1])) {
Packit Service 501009
                error(INFO, "cannot alias existing command name: %s\n", 
Packit Service 501009
			args[1]);
Packit Service 501009
                return FALSE;
Packit Service 501009
	}
Packit Service 501009
Packit Service 501009
	if (get_command_table_entry(args[2])) 
Packit Service 501009
		found = TRUE;
Packit Service 501009
Packit Service 501009
	if (!found) {
Packit Service 501009
		if (!strlen(args[2])) {
Packit Service 501009
			if (alias_exists(args[1])) {
Packit Service 501009
				deallocate_alias(args[1]);
Packit Service 501009
				fprintf(fp, "alias deleted: %s\n", args[1]);
Packit Service 501009
			}
Packit Service 501009
		} else {
Packit Service 501009
			error(INFO, 
Packit Service 501009
		          "invalid alias attempt on non-existent command: %s\n",
Packit Service 501009
				args[2]);
Packit Service 501009
		}
Packit Service 501009
		return FALSE;
Packit Service 501009
	} 
Packit Service 501009
Packit Service 501009
	if (alias_exists(args[1]))
Packit Service 501009
		deallocate_alias(args[1]);
Packit Service 501009
Packit Service 501009
	if (enclosed_string)
Packit Service 501009
		*enclosed_string = ' ';
Packit Service 501009
Packit Service 501009
	size = sizeof(struct alias_data) + argcnt;
Packit Service 501009
	for (i = 0; i < argcnt; i++) 
Packit Service 501009
		size += strlen(args[i]);
Packit Service 501009
Packit Service 501009
        if ((newad = (struct alias_data *)malloc(size+1)) == NULL) {
Packit Service 501009
                error(INFO, "alias_data malloc: %s\n", strerror(errno));
Packit Service 501009
                return FALSE;
Packit Service 501009
        }
Packit Service 501009
Packit Service 501009
	BZERO(newad, size);
Packit Service 501009
	newad->next = NULL;
Packit Service 501009
	newad->size = size;
Packit Service 501009
	newad->origin = origin;
Packit Service 501009
Packit Service 501009
	p1 = newad->argbuf;
Packit Service 501009
	for (i = 1; i < argcnt; i++) {
Packit Service 501009
                sprintf(p1, "%s ", args[i]);
Packit Service 501009
		while (*p1)
Packit Service 501009
			p1++;
Packit Service 501009
	}
Packit Service 501009
	p1 = strstr(newad->argbuf, " ");
Packit Service 501009
	*p1 = NULLCHAR;
Packit Service 501009
Packit Service 501009
	newad->alias = newad->argbuf;
Packit Service 501009
	newad->argcnt = parse_line(p1+1, newad->args); 
Packit Service 501009
Packit Service 501009
	for (ad = &alias_head; ad->next; ad = ad->next) 
Packit Service 501009
		;
Packit Service 501009
	ad->next = newad;
Packit Service 501009
Packit Service 501009
	return TRUE;
Packit Service 501009
}
Packit Service 501009
Packit Service 501009
Packit Service 501009
/*
Packit Service 501009
 *  Check whether the passed-in string is a currently-existing alias.
Packit Service 501009
 */
Packit Service 501009
static int
Packit Service 501009
alias_exists(char *s)
Packit Service 501009
{
Packit Service 501009
        struct alias_data *ad;
Packit Service 501009
Packit Service 501009
        if (!alias_head.next) 
Packit Service 501009
                return FALSE;
Packit Service 501009
Packit Service 501009
        for (ad = alias_head.next; ad; ad = ad->next) 
Packit Service 501009
		if (STREQ(ad->alias, s)) 
Packit Service 501009
			return TRUE;
Packit Service 501009
Packit Service 501009
	return FALSE;
Packit Service 501009
}
Packit Service 501009
Packit Service 501009
/*
Packit Service 501009
 *  If the passed-in string is an alias, delink it and free its memory. 
Packit Service 501009
 */
Packit Service 501009
void
Packit Service 501009
deallocate_alias(char *s)
Packit Service 501009
{
Packit Service 501009
        struct alias_data *ad, *lastad;
Packit Service 501009
Packit Service 501009
        for (ad = alias_head.next, lastad = &alias_head; ad; ad = ad->next) {
Packit Service 501009
                if (!STREQ(ad->alias, s)) { 
Packit Service 501009
			lastad = ad;
Packit Service 501009
                        continue;
Packit Service 501009
		}
Packit Service 501009
Packit Service 501009
		lastad->next = ad->next;
Packit Service 501009
		free(ad);
Packit Service 501009
		break;
Packit Service 501009
	}
Packit Service 501009
}
Packit Service 501009
Packit Service 501009
/*
Packit Service 501009
 *  "help -a" output
Packit Service 501009
 */
Packit Service 501009
void
Packit Service 501009
dump_alias_data(void)
Packit Service 501009
{
Packit Service 501009
        int i;
Packit Service 501009
        struct alias_data *ad;
Packit Service 501009
Packit Service 501009
	fprintf(fp, "alias_head.next: %lx\n\n", (ulong)alias_head.next);
Packit Service 501009
Packit Service 501009
        for (ad = alias_head.next; ad; ad = ad->next) {
Packit Service 501009
        	fprintf(fp, "      next: %lx\n", (ulong)ad->next);
Packit Service 501009
        	fprintf(fp, "     alias: %s\n", ad->alias);
Packit Service 501009
        	fprintf(fp, "      size: %d\n", ad->size);
Packit Service 501009
        	fprintf(fp, "    origin: ");
Packit Service 501009
		switch (ad->origin)
Packit Service 501009
		{
Packit Service 501009
		case ALIAS_RUNTIME:
Packit Service 501009
			fprintf(fp, "runtime setting \n");
Packit Service 501009
			break;
Packit Service 501009
		case ALIAS_RCLOCAL:
Packit Service 501009
			fprintf(fp, ".%src \n", pc->program_name);
Packit Service 501009
			break;
Packit Service 501009
		case ALIAS_RCHOME:
Packit Service 501009
			fprintf(fp, "$HOME/.%src \n", pc->program_name);
Packit Service 501009
			break;
Packit Service 501009
		case ALIAS_BUILTIN:
Packit Service 501009
			fprintf(fp, "builtin\n");
Packit Service 501009
			break;
Packit Service 501009
		}
Packit Service 501009
        	fprintf(fp, "    argcnt: %d\n", ad->argcnt);
Packit Service 501009
        	for (i = 0; i < ad->argcnt; i++)
Packit Service 501009
                	fprintf(fp, "   args[%d]: %lx: %s\n", 
Packit Service 501009
				i, (ulong)ad->args[i], ad->args[i]);
Packit Service 501009
                fprintf(fp, "\n");
Packit Service 501009
        }
Packit Service 501009
}
Packit Service 501009
Packit Service 501009
Packit Service 501009
/*
Packit Service 501009
 *  Repeat a command on a live system.
Packit Service 501009
 */
Packit Service 501009
void
Packit Service 501009
cmd_repeat(void)
Packit Service 501009
{
Packit Service 501009
	ulong delay;
Packit Service 501009
	char buf[BUFSIZE]; 
Packit Service 501009
	char bufsave[BUFSIZE];
Packit Service 501009
	FILE *incoming_fp;
Packit Service 501009
Packit Service 501009
	if (argcnt == 1)
Packit Service 501009
		cmd_usage(pc->curcmd, SYNOPSIS);
Packit Service 501009
Packit Service 501009
	delay = 0;
Packit Service 501009
Packit Service 501009
	if (args[1][0] == '-') {
Packit Service 501009
		switch (args[1][1])
Packit Service 501009
		{
Packit Service 501009
		default:
Packit Service 501009
		case NULLCHAR:
Packit Service 501009
			cmd_usage(pc->curcmd, SYNOPSIS);
Packit Service 501009
Packit Service 501009
		case '1':
Packit Service 501009
		case '2':
Packit Service 501009
		case '3':
Packit Service 501009
		case '4':
Packit Service 501009
		case '5':
Packit Service 501009
		case '6':
Packit Service 501009
		case '7':
Packit Service 501009
		case '8':
Packit Service 501009
		case '9':
Packit Service 501009
		case '0':
Packit Service 501009
			delay = dtol(&args[1][1], FAULT_ON_ERROR, NULL);
Packit Service 501009
			concat_args(buf, 2, FALSE);
Packit Service 501009
			break;
Packit Service 501009
		}
Packit Service 501009
	} else 
Packit Service 501009
		concat_args(buf, 1, FALSE);
Packit Service 501009
Packit Service 501009
	check_special_handling(buf);
Packit Service 501009
Packit Service 501009
	strcpy(pc->command_line, buf);
Packit Service 501009
	resolve_aliases();
Packit Service 501009
	if (!argcnt)
Packit Service 501009
		return;
Packit Service 501009
	strcpy(buf, pc->command_line);
Packit Service 501009
Packit Service 501009
	strcpy(bufsave, buf);
Packit Service 501009
	argcnt = parse_line(buf, args);
Packit Service 501009
	if (!argcnt)
Packit Service 501009
		return;
Packit Service 501009
Packit Service 501009
	if (STREQ(args[0], "<") && (pc->flags & TTY) &&
Packit Service 501009
            (pc->flags & SCROLL) && pc->scroll_command) 
Packit Service 501009
		error(FATAL, 
Packit Service 501009
		"scrolling must be turned off when repeating an input file\n");
Packit Service 501009
Packit Service 501009
	pc->curcmd_flags |= REPEAT;
Packit Service 501009
	incoming_fp = fp;
Packit Service 501009
Packit Service 501009
	while (TRUE) {
Packit Service 501009
		optind = 0;
Packit Service 501009
		fp = incoming_fp;
Packit Service 501009
		exec_command();
Packit Service 501009
		free_all_bufs();
Packit Service 501009
		wait_for_children(ZOMBIES_ONLY);
Packit Service 501009
Packit Service 501009
		if (received_SIGINT() || !output_open())
Packit Service 501009
			break;
Packit Service 501009
Packit Service 501009
		if ((pc->flags & TTY) && !is_a_tty("/dev/tty"))
Packit Service 501009
			break;
Packit Service 501009
Packit Service 501009
		if (!(pc->curcmd_flags & REPEAT))
Packit Service 501009
			break;
Packit Service 501009
Packit Service 501009
		if (delay)
Packit Service 501009
			sleep(delay);
Packit Service 501009
Packit Service 501009
		strcpy(buf, bufsave);
Packit Service 501009
		argcnt = parse_line(buf, args);
Packit Service 501009
	}
Packit Service 501009
}
Packit Service 501009
Packit Service 501009
/*
Packit Service 501009
 *  Initialize readline, set the editing mode, and then perform any 
Packit Service 501009
 *  crash-specific bindings, etc.
Packit Service 501009
 */
Packit Service 501009
static void
Packit Service 501009
readline_init(void)
Packit Service 501009
{               
Packit Service 501009
        rl_initialize();
Packit Service 501009
Packit Service 501009
	if (STREQ(pc->editing_mode, "vi")) {
Packit Service 501009
		rl_editing_mode = vi_mode;
Packit Service 501009
Packit Service 501009
		rl_bind_key(CTRL('N'), rl_get_next_history);
Packit Service 501009
		rl_bind_key(CTRL('P'), rl_get_previous_history);
Packit Service 501009
Packit Service 501009
		rl_bind_key_in_map(CTRL('P'), rl_get_previous_history,
Packit Service 501009
			vi_insertion_keymap);
Packit Service 501009
		rl_bind_key_in_map(CTRL('N'), rl_get_next_history,
Packit Service 501009
			vi_insertion_keymap);
Packit Service 501009
		rl_bind_key_in_map(CTRL('l'), rl_clear_screen,
Packit Service 501009
			vi_insertion_keymap);
Packit Service 501009
Packit Service 501009
		rl_generic_bind(ISFUNC, "[A", (char *)rl_get_previous_history, 
Packit Service 501009
			vi_movement_keymap);
Packit Service 501009
		rl_generic_bind(ISFUNC, "[B", (char *)rl_get_next_history, 
Packit Service 501009
			vi_movement_keymap);
Packit Service 501009
	}
Packit Service 501009
Packit Service 501009
	if (STREQ(pc->editing_mode, "emacs")) {
Packit Service 501009
        	rl_editing_mode = emacs_mode;
Packit Service 501009
	}
Packit Service 501009
Packit Service 501009
	rl_attempted_completion_function = crash_readline_completer;
Packit Service 501009
	rl_attempted_completion_over = 1;
Packit Service 501009
}
Packit Service 501009
Packit Service 501009
/*
Packit Service 501009
 *  Find and set the tty string of this session as seen in "ps -ef" output. 
Packit Service 501009
 */
Packit Service 501009
static void
Packit Service 501009
set_my_tty(void)
Packit Service 501009
{
Packit Service 501009
        char buf[BUFSIZE];
Packit Service 501009
        char *arglist[MAXARGS];
Packit Service 501009
        int argc;
Packit Service 501009
        FILE *pipe;
Packit Service 501009
Packit Service 501009
        strcpy(pc->my_tty, "?");
Packit Service 501009
Packit Service 501009
	if (file_exists("/usr/bin/tty", NULL)) {
Packit Service 501009
	        sprintf(buf, "/usr/bin/tty");
Packit Service 501009
	        if ((pipe = popen(buf, "r")) == NULL) 
Packit Service 501009
	                return;
Packit Service 501009
	
Packit Service 501009
	        while (fgets(buf, BUFSIZE, pipe)) {
Packit Service 501009
			if (STRNEQ(buf, "/dev/")) {
Packit Service 501009
				strcpy(pc->my_tty, strip_line_end(&buf[strlen("/dev/")]));
Packit Service 501009
				break;
Packit Service 501009
			}
Packit Service 501009
		}
Packit Service 501009
		pclose(pipe);
Packit Service 501009
		return;
Packit Service 501009
	}
Packit Service 501009
Packit Service 501009
        sprintf(buf, "ps -ef | grep ' %d '", getpid());
Packit Service 501009
Packit Service 501009
	if (CRASHDEBUG(1))
Packit Service 501009
		fprintf(fp, "popen(%s)\n", buf);
Packit Service 501009
Packit Service 501009
        if ((pipe = popen(buf, "r")) == NULL) 
Packit Service 501009
                return;
Packit Service 501009
Packit Service 501009
        while (fgets(buf, BUFSIZE, pipe)) {
Packit Service 501009
                argc = parse_line(buf, arglist);
Packit Service 501009
                if ((argc >= 8) && (atoi(arglist[1]) == getpid())) {
Packit Service 501009
			if (strlen(arglist[5]) < 9)
Packit Service 501009
				strcpy(pc->my_tty, arglist[5]);
Packit Service 501009
			else
Packit Service 501009
				strncpy(pc->my_tty, arglist[5], 9); 
Packit Service 501009
                }
Packit Service 501009
        }
Packit Service 501009
        pclose(pipe);
Packit Service 501009
}
Packit Service 501009
Packit Service 501009
/*
Packit Service 501009
 *  Check whether SIGINT's are allowed before shipping a request off to gdb.
Packit Service 501009
 */
Packit Service 501009
int
Packit Service 501009
interruptible(void)
Packit Service 501009
{
Packit Service 501009
	if (!(pc->flags & RUNTIME))
Packit Service 501009
		return FALSE;
Packit Service 501009
Packit Service 501009
	if (!(pc->flags & TTY))
Packit Service 501009
		return FALSE;
Packit Service 501009
Packit Service 501009
	if ((pc->redirect & (FROM_INPUT_FILE|REDIRECT_NOT_DONE)) ==
Packit Service 501009
	    (FROM_INPUT_FILE|REDIRECT_NOT_DONE)) 
Packit Service 501009
		return TRUE;
Packit Service 501009
Packit Service 501009
	if (strlen(pc->pipe_command))
Packit Service 501009
		return FALSE;
Packit Service 501009
		
Packit Service 501009
	return TRUE;
Packit Service 501009
}
Packit Service 501009
Packit Service 501009
Packit Service 501009
/*
Packit Service 501009
 *  Set up the standard output pipe using whichever was selected during init.
Packit Service 501009
 */
Packit Service 501009
Packit Service 501009
static int
Packit Service 501009
setup_stdpipe(void)
Packit Service 501009
{
Packit Service 501009
	char *path;
Packit Service 501009
Packit Service 501009
	if (pipe(pc->pipefd) < 0) {
Packit Service 501009
		error(INFO, "pipe system call failed: %s", strerror(errno));
Packit Service 501009
		return FALSE;
Packit Service 501009
	}
Packit Service 501009
Packit Service 501009
	if ((pc->stdpipe_pid = fork()) < 0) {
Packit Service 501009
		error(INFO, "fork system call failed: %s", strerror(errno));
Packit Service 501009
		return FALSE;
Packit Service 501009
	}
Packit Service 501009
Packit Service 501009
	path = NULL;
Packit Service 501009
Packit Service 501009
	if (pc->stdpipe_pid > 0) {               
Packit Service 501009
		pc->redirect |= REDIRECT_PID_KNOWN;
Packit Service 501009
Packit Service 501009
		close(pc->pipefd[0]);    /* parent closes read end */
Packit Service 501009
Packit Service 501009
		if ((pc->stdpipe = fdopen(pc->pipefd[1], "w")) == NULL) {
Packit Service 501009
			error(INFO, "fdopen system call failed: %s", 
Packit Service 501009
				strerror(errno));
Packit Service 501009
			return FALSE;
Packit Service 501009
		}
Packit Service 501009
		setbuf(pc->stdpipe, NULL);
Packit Service 501009
Packit Service 501009
                switch (pc->scroll_command)
Packit Service 501009
                {
Packit Service 501009
                case SCROLL_LESS:
Packit Service 501009
                        strcpy(pc->pipe_command, less_argv[0]);
Packit Service 501009
                        break;
Packit Service 501009
                case SCROLL_MORE:
Packit Service 501009
                        strcpy(pc->pipe_command, more_argv[0]);
Packit Service 501009
                        break;
Packit Service 501009
		case SCROLL_CRASHPAGER:
Packit Service 501009
                        strcpy(pc->pipe_command, CRASHPAGER_argv[0]);
Packit Service 501009
                        break;
Packit Service 501009
                }
Packit Service 501009
Packit Service 501009
		if (CRASHDEBUG(2))
Packit Service 501009
			console("pipe: %lx\n", pc->stdpipe);
Packit Service 501009
		return TRUE;;
Packit Service 501009
Packit Service 501009
	} else {                        
Packit Service 501009
		close(pc->pipefd[1]);    /* child closes write end */
Packit Service 501009
Packit Service 501009
		if (dup2(pc->pipefd[0], 0) != 0) {
Packit Service 501009
			perror("child dup2 failed");
Packit Service 501009
			clean_exit(1);
Packit Service 501009
		}
Packit Service 501009
Packit Service 501009
		if (CRASHDEBUG(2))
Packit Service 501009
			console("execv: %d\n", getpid());
Packit Service 501009
Packit Service 501009
                switch (pc->scroll_command)
Packit Service 501009
		{
Packit Service 501009
		case SCROLL_LESS:
Packit Service 501009
			path = less_argv[0];
Packit Service 501009
			execv(path, less_argv);
Packit Service 501009
			break;
Packit Service 501009
Packit Service 501009
                case SCROLL_MORE:
Packit Service 501009
			path = more_argv[0];
Packit Service 501009
			execv(path, more_argv);
Packit Service 501009
			break;
Packit Service 501009
Packit Service 501009
		case SCROLL_CRASHPAGER:
Packit Service 501009
			path = CRASHPAGER_argv[0];
Packit Service 501009
			execv(path, CRASHPAGER_argv);
Packit Service 501009
			break;
Packit Service 501009
		}
Packit Service 501009
Packit Service 501009
		perror(path); 
Packit Service 501009
		fprintf(stderr, "execv of scroll command failed\n");
Packit Service 501009
		exit(1);
Packit Service 501009
	}
Packit Service 501009
}
Packit Service 501009
Packit Service 501009
static void 
Packit Service 501009
wait_for_children(ulong waitflag)
Packit Service 501009
{
Packit Service 501009
        int status, pid;
Packit Service 501009
Packit Service 501009
	while (TRUE) {
Packit Service 501009
        	switch (pid = waitpid(-1, &status, WNOHANG))
Packit Service 501009
        	{
Packit Service 501009
        	case  0:
Packit Service 501009
			if (CRASHDEBUG(2))
Packit Service 501009
			    console("wait_for_children: child running...\n");
Packit Service 501009
			if (waitflag == ZOMBIES_ONLY)
Packit Service 501009
				return;
Packit Service 501009
			break;
Packit Service 501009
Packit Service 501009
        	case -1:
Packit Service 501009
			if (CRASHDEBUG(2))
Packit Service 501009
			    console("wait_for_children: no children alive\n");
Packit Service 501009
                	return;
Packit Service 501009
Packit Service 501009
        	default:
Packit Service 501009
			console("wait_for_children(%d): reaped %d\n", 
Packit Service 501009
				waitflag, pid);
Packit Service 501009
			if (CRASHDEBUG(2))
Packit Service 501009
			    fprintf(fp, "wait_for_children: reaped %d\n", pid);
Packit Service 501009
                	break;
Packit Service 501009
        	}
Packit Service 501009
		stall(1000);
Packit Service 501009
	}
Packit Service 501009
}
Packit Service 501009
Packit Service 501009
/*
Packit Service 501009
 *  Run an escaped shell command, redirecting the output to
Packit Service 501009
 *  the current output file.
Packit Service 501009
 */
Packit Service 501009
int
Packit Service 501009
shell_command(char *cmd)
Packit Service 501009
{
Packit Service 501009
	FILE *pipe;
Packit Service 501009
	char buf[BUFSIZE];
Packit Service 501009
Packit Service 501009
	if ((pipe = popen(cmd, "r")) == NULL) {
Packit Service 501009
		error(INFO, "cannot open pipe: %s\n", cmd);
Packit Service 501009
		pc->redirect &= ~REDIRECT_SHELL_COMMAND;
Packit Service 501009
                pc->redirect |= REDIRECT_FAILURE;
Packit Service 501009
                return REDIRECT_FAILURE;
Packit Service 501009
        }
Packit Service 501009
Packit Service 501009
        while (fgets(buf, BUFSIZE, pipe))
Packit Service 501009
		fputs(buf, fp);
Packit Service 501009
        pclose(pipe);
Packit Service 501009
Packit Service 501009
	return REDIRECT_SHELL_COMMAND;
Packit Service 501009
}
Packit Service 501009
Packit Service 501009
static int 
Packit Service 501009
verify_args_input_file(char *fileptr)
Packit Service 501009
{
Packit Service 501009
	struct stat stat;
Packit Service 501009
Packit Service 501009
	if (!file_exists(fileptr, &stat)) {
Packit Service 501009
		if (CRASHDEBUG(1))
Packit Service 501009
			error(INFO, "%s: no such file\n", fileptr);
Packit Service 501009
	} else if (!S_ISREG(stat.st_mode)) {
Packit Service 501009
		if (CRASHDEBUG(1))
Packit Service 501009
			error(INFO, "%s: not a regular file\n", fileptr);
Packit Service 501009
	} else if (!stat.st_size) {
Packit Service 501009
		if (CRASHDEBUG(1))
Packit Service 501009
			error(INFO, "%s: file is empty\n", fileptr);
Packit Service 501009
	} else if (!file_readable(fileptr)) {
Packit Service 501009
		if (CRASHDEBUG(1))
Packit Service 501009
			error(INFO, "%s: permission denied\n", fileptr);
Packit Service 501009
	} else
Packit Service 501009
		return TRUE;
Packit Service 501009
Packit Service 501009
	return FALSE;
Packit Service 501009
}
Packit Service 501009
Packit Service 501009
/*
Packit Service 501009
 * Verify a command line argument input file.
Packit Service 501009
 */
Packit Service 501009
Packit Service 501009
#define NON_FILENAME_CHARS "*?!|\'\"{}<>;,^()$~"
Packit Service 501009
Packit Service 501009
int 
Packit Service 501009
is_args_input_file(struct command_table_entry *ct, struct args_input_file *aif)
Packit Service 501009
{
Packit Service 501009
	int c, start, whites, args_used;
Packit Service 501009
	char *p1, *p2, *curptr, *fileptr;
Packit Service 501009
	char buf[BUFSIZE];
Packit Service 501009
	int retval;
Packit Service 501009
Packit Service 501009
	if (pc->curcmd_flags & NO_MODIFY)
Packit Service 501009
		return FALSE;
Packit Service 501009
Packit Service 501009
	if (STREQ(ct->name, "repeat"))
Packit Service 501009
		return FALSE;
Packit Service 501009
Packit Service 501009
	BZERO(aif, sizeof(struct args_input_file));
Packit Service 501009
	retval = FALSE;
Packit Service 501009
Packit Service 501009
	if (STREQ(ct->name, "gdb")) {
Packit Service 501009
		curptr = pc->orig_line;
Packit Service 501009
next_gdb:
Packit Service 501009
		if ((p1 = strstr(curptr, "<"))) {
Packit Service 501009
			while (STRNEQ(p1, "<<")) {
Packit Service 501009
				p2 = p1+2;
Packit Service 501009
			        if (!(p1 = strstr(p2, "<")))
Packit Service 501009
					return retval;
Packit Service 501009
			}
Packit Service 501009
		}
Packit Service 501009
Packit Service 501009
		if (!p1)
Packit Service 501009
			return retval;
Packit Service 501009
Packit Service 501009
		start = p1 - curptr;
Packit Service 501009
		p2 = p1+1;
Packit Service 501009
Packit Service 501009
		for (whites = 0; whitespace(*p2); whites++)
Packit Service 501009
			p2++;
Packit Service 501009
Packit Service 501009
		if (*p2 == NULLCHAR)
Packit Service 501009
			return retval;
Packit Service 501009
Packit Service 501009
		strcpy(buf, p2);
Packit Service 501009
		p2 = buf;
Packit Service 501009
Packit Service 501009
		if (*p2) {
Packit Service 501009
			fileptr = p2;
Packit Service 501009
			while (*p2 && !whitespace(*p2) && 
Packit Service 501009
				(strpbrk(p2, NON_FILENAME_CHARS) != p2))
Packit Service 501009
				p2++;
Packit Service 501009
			*p2 = NULLCHAR;
Packit Service 501009
			if (verify_args_input_file(fileptr)) {
Packit Service 501009
				if (retval == TRUE) {
Packit Service 501009
					error(INFO, 
Packit Service 501009
					    "ignoring multiple argument input files: "
Packit Service 501009
					    "%s and %s\n",
Packit Service 501009
						aif->fileptr, fileptr);
Packit Service 501009
					return FALSE;
Packit Service 501009
				}
Packit Service 501009
				aif->start = start;
Packit Service 501009
				aif->resume = start + (p2-buf) + whites + 1;
Packit Service 501009
				aif->fileptr = GETBUF(strlen(fileptr)+1);
Packit Service 501009
				strcpy(aif->fileptr, fileptr);
Packit Service 501009
				aif->is_gdb_cmd = TRUE;
Packit Service 501009
				retval = TRUE;
Packit Service 501009
			}
Packit Service 501009
		}
Packit Service 501009
Packit Service 501009
		curptr = p1+1;
Packit Service 501009
		goto next_gdb;
Packit Service 501009
	}
Packit Service 501009
Packit Service 501009
	for (c = 0; c < argcnt; c++) {
Packit Service 501009
		if (STRNEQ(args[c], "<") && !STRNEQ(args[c], "<<")) { 
Packit Service 501009
			if (strlen(args[c]) > 1) {
Packit Service 501009
				fileptr = &args[c][1];
Packit Service 501009
				args_used = 1;
Packit Service 501009
			} else {
Packit Service 501009
		    		if ((c+1) == argcnt)
Packit Service 501009
					error(FATAL, 
Packit Service 501009
					    "< requires a file argument\n");
Packit Service 501009
				fileptr = args[c+1];
Packit Service 501009
				args_used = 2;
Packit Service 501009
			}
Packit Service 501009
Packit Service 501009
			if (!verify_args_input_file(fileptr))
Packit Service 501009
				continue;
Packit Service 501009
Packit Service 501009
			if (retval == TRUE)
Packit Service 501009
				error(FATAL, 
Packit Service 501009
				    "multiple input files are not supported\n");
Packit Service 501009
Packit Service 501009
			aif->index = c;
Packit Service 501009
			aif->fileptr = GETBUF(strlen(fileptr)+1);
Packit Service 501009
			strcpy(aif->fileptr, fileptr);
Packit Service 501009
			aif->args_used = args_used;
Packit Service 501009
			retval = TRUE;
Packit Service 501009
			continue;
Packit Service 501009
		} 
Packit Service 501009
Packit Service 501009
		if (STRNEQ(args[c], "(")) {
Packit Service 501009
			curptr = args[c];
Packit Service 501009
next_expr:
Packit Service 501009
			if ((p1 = strstr(curptr, "<"))) {
Packit Service 501009
				while (STRNEQ(p1, "<<")) {
Packit Service 501009
					p2 = p1+2;
Packit Service 501009
					if (!(p1 = strstr(p2, "<")))
Packit Service 501009
						continue;
Packit Service 501009
				}
Packit Service 501009
			}
Packit Service 501009
Packit Service 501009
			if (!p1)
Packit Service 501009
				continue;
Packit Service 501009
Packit Service 501009
			start = p1 - curptr;
Packit Service 501009
			p2 = p1+1;
Packit Service 501009
Packit Service 501009
			for (whites = 0; whitespace(*p2); whites++)
Packit Service 501009
				p2++;
Packit Service 501009
Packit Service 501009
			if (*p2 == NULLCHAR)
Packit Service 501009
				continue;
Packit Service 501009
Packit Service 501009
			strcpy(buf, p2);
Packit Service 501009
			p2 = buf;
Packit Service 501009
Packit Service 501009
			if (*p2) {
Packit Service 501009
				fileptr = p2;
Packit Service 501009
				while (*p2 && !whitespace(*p2) && 
Packit Service 501009
					(strpbrk(p2, NON_FILENAME_CHARS) != p2))
Packit Service 501009
					p2++;
Packit Service 501009
				*p2 = NULLCHAR;
Packit Service 501009
Packit Service 501009
				if (!verify_args_input_file(fileptr))
Packit Service 501009
					continue;
Packit Service 501009
Packit Service 501009
				if (retval == TRUE) {
Packit Service 501009
					error(INFO, 
Packit Service 501009
					    "ignoring multiple argument input files: "
Packit Service 501009
					    "%s and %s\n",
Packit Service 501009
						aif->fileptr, fileptr);
Packit Service 501009
					return FALSE;
Packit Service 501009
				}
Packit Service 501009
		
Packit Service 501009
				retval = TRUE;
Packit Service 501009
Packit Service 501009
				aif->in_expression = TRUE;
Packit Service 501009
				aif->args_used = 1;
Packit Service 501009
				aif->index = c;
Packit Service 501009
				aif->start = start;
Packit Service 501009
				aif->resume = start + (p2-buf) + whites + 1;
Packit Service 501009
				aif->fileptr = GETBUF(strlen(fileptr)+1);
Packit Service 501009
				strcpy(aif->fileptr, fileptr);
Packit Service 501009
			}
Packit Service 501009
Packit Service 501009
			curptr = p1+1; 
Packit Service 501009
			goto next_expr;
Packit Service 501009
		}
Packit Service 501009
	}
Packit Service 501009
Packit Service 501009
	return retval;
Packit Service 501009
}
Packit Service 501009
Packit Service 501009
static void
Packit Service 501009
modify_orig_line(char *inbuf, struct args_input_file *aif)
Packit Service 501009
{
Packit Service 501009
	char buf[BUFSIZE];
Packit Service 501009
Packit Service 501009
	strcpy(buf, pc->orig_line);
Packit Service 501009
	strcpy(&buf[aif->start], inbuf);
Packit Service 501009
	strcat(buf, &pc->orig_line[aif->resume]);
Packit Service 501009
	strcpy(pc->orig_line, buf);
Packit Service 501009
}
Packit Service 501009
Packit Service 501009
static void
Packit Service 501009
modify_expression_arg(char *inbuf, char **aif_args, struct args_input_file *aif)
Packit Service 501009
{
Packit Service 501009
	char *old, *new;
Packit Service 501009
Packit Service 501009
	old = aif_args[aif->index];
Packit Service 501009
	new = GETBUF(strlen(aif_args[aif->index]) + strlen(inbuf));
Packit Service 501009
Packit Service 501009
	strcpy(new, old);
Packit Service 501009
	strcpy(&new[aif->start], inbuf);
Packit Service 501009
	strcat(new, &old[aif->resume]);
Packit Service 501009
Packit Service 501009
	aif_args[aif->index] = new;
Packit Service 501009
}
Packit Service 501009
Packit Service 501009
/*
Packit Service 501009
 *  Sequence through an args input file, and for each line,
Packit Service 501009
 *  reinitialize the global args[] and argcnt, and issue the command.
Packit Service 501009
 */
Packit Service 501009
void
Packit Service 501009
exec_args_input_file(struct command_table_entry *ct, struct args_input_file *aif)
Packit Service 501009
{
Packit Service 501009
	char buf[BUFSIZE];
Packit Service 501009
	int i, c, aif_cnt;
Packit Service 501009
	int orig_argcnt;
Packit Service 501009
	char *aif_args[MAXARGS];
Packit Service 501009
	char *new_args[MAXARGS];
Packit Service 501009
	char *orig_args[MAXARGS];
Packit Service 501009
	char orig_line[BUFSIZE];
Packit Service 501009
	char *save_args[MAXARGS];
Packit Service 501009
	char save_line[BUFSIZE];
Packit Service 501009
Packit Service 501009
	if ((pc->args_ifile = fopen(aif->fileptr, "r")) == NULL)
Packit Service 501009
		error(FATAL, "%s: %s\n", aif->fileptr, strerror(errno));
Packit Service 501009
Packit Service 501009
	if (aif->is_gdb_cmd)
Packit Service 501009
		strcpy(orig_line, pc->orig_line);
Packit Service 501009
Packit Service 501009
	BCOPY(args, orig_args, sizeof(args));
Packit Service 501009
	orig_argcnt = argcnt;
Packit Service 501009
Packit Service 501009
	/*
Packit Service 501009
	 *  Commands cannot be trusted to leave the arguments intact.
Packit Service 501009
	 *  Stash them here and restore them each time through the loop.
Packit Service 501009
	 */
Packit Service 501009
	save_args[0] = save_line;
Packit Service 501009
	for (i = 0; i < orig_argcnt; i++) {
Packit Service 501009
		strcpy(save_args[i], orig_args[i]);
Packit Service 501009
		save_args[i+1] = save_args[i] + strlen(save_args[i]) + 2;
Packit Service 501009
	}
Packit Service 501009
Packit Service 501009
	while (fgets(buf, BUFSIZE-1, pc->args_ifile)) {
Packit Service 501009
		clean_line(buf);
Packit Service 501009
		if ((strlen(buf) == 0) || (buf[0] == '#'))
Packit Service 501009
			continue;		
Packit Service 501009
Packit Service 501009
		for (i = 1; i < orig_argcnt; i++)
Packit Service 501009
			strcpy(orig_args[i], save_args[i]);
Packit Service 501009
Packit Service 501009
		if (aif->is_gdb_cmd) {
Packit Service 501009
			console("(gdb) before: [%s]\n", orig_line);
Packit Service 501009
			strcpy(pc->orig_line, orig_line);
Packit Service 501009
			modify_orig_line(buf, aif);
Packit Service 501009
			console("(gdb)  after: [%s]\n", pc->orig_line);
Packit Service 501009
		} else if (aif->in_expression) {
Packit Service 501009
			console("expr before: [%s]\n", orig_args[aif->index]);
Packit Service 501009
			BCOPY(orig_args, aif_args, sizeof(aif_args));
Packit Service 501009
			modify_expression_arg(buf, aif_args, aif);
Packit Service 501009
			BCOPY(aif_args, args, sizeof(aif_args));
Packit Service 501009
			console("expr  after: [%s]\n", args[aif->index]);
Packit Service 501009
		} else {
Packit Service 501009
			if (!(aif_cnt = parse_line(buf, aif_args)))
Packit Service 501009
				continue;
Packit Service 501009
Packit Service 501009
			for (i = 0; i < orig_argcnt; i++)
Packit Service 501009
				console("%s[%d]:%s %s", 
Packit Service 501009
					(i == 0) ? "before: " : "", 
Packit Service 501009
					i, orig_args[i],
Packit Service 501009
					(i+1) == orig_argcnt ? "\n" : "");
Packit Service 501009
	
Packit Service 501009
			for (i = 0; i < aif->index; i++)
Packit Service 501009
				new_args[i] = orig_args[i];
Packit Service 501009
			for (i = aif->index, c = 0; c < aif_cnt; c++, i++)
Packit Service 501009
				new_args[i] = aif_args[c];
Packit Service 501009
			for (i = aif->index + aif_cnt, 
Packit Service 501009
			     c = aif->index + aif->args_used;
Packit Service 501009
			     c < orig_argcnt; c++, i++)
Packit Service 501009
				new_args[i] = orig_args[c];
Packit Service 501009
	
Packit Service 501009
			argcnt = orig_argcnt - aif->args_used + aif_cnt;
Packit Service 501009
			new_args[argcnt] = NULL;
Packit Service 501009
			BCOPY(new_args, args, sizeof(args));
Packit Service 501009
Packit Service 501009
			for (i = 0; i < argcnt; i++)
Packit Service 501009
				console("%s[%d]:%s %s", 
Packit Service 501009
					(i == 0) ? " after: " : "", 
Packit Service 501009
					i, args[i],
Packit Service 501009
					(i+1) == argcnt ? "\n" : "");
Packit Service 501009
		}
Packit Service 501009
Packit Service 501009
		optind = argerrs = 0;
Packit Service 501009
		pc->cmdgencur++;
Packit Service 501009
Packit Service 501009
		if (setjmp(pc->foreach_loop_env))
Packit Service 501009
			pc->flags &= ~IN_FOREACH;
Packit Service 501009
		else {
Packit Service 501009
			pc->flags |= IN_FOREACH;
Packit Service 501009
			(*ct->func)();
Packit Service 501009
			pc->flags &= ~IN_FOREACH;
Packit Service 501009
		}
Packit Service 501009
Packit Service 501009
		if (pc->cmd_cleanup)
Packit Service 501009
			pc->cmd_cleanup(pc->cmd_cleanup_arg);
Packit Service 501009
Packit Service 501009
		free_all_bufs();
Packit Service 501009
Packit Service 501009
		if (received_SIGINT())
Packit Service 501009
			break;		
Packit Service 501009
	}
Packit Service 501009
Packit Service 501009
	fclose(pc->args_ifile);
Packit Service 501009
	pc->args_ifile = NULL;
Packit Service 501009
}
Packit Service 501009
Packit Service 501009
static char *
Packit Service 501009
crash_readline_completion_generator(const char *match, int state)
Packit Service 501009
{
Packit Service 501009
	static struct syment *sp_match;
Packit Service 501009
Packit Service 501009
	if (state == 0)
Packit Service 501009
		sp_match = NULL;
Packit Service 501009
Packit Service 501009
	sp_match = symbol_complete_match(match, sp_match);
Packit Service 501009
Packit Service 501009
	if (sp_match)
Packit Service 501009
		return(strdup(sp_match->name));
Packit Service 501009
	else
Packit Service 501009
		return NULL;
Packit Service 501009
}
Packit Service 501009
Packit Service 501009
static char **
Packit Service 501009
crash_readline_completer(const char *match, int start, int end)
Packit Service 501009
{
Packit Service 501009
	rl_attempted_completion_over = 1;
Packit Service 501009
	return rl_completion_matches(match, crash_readline_completion_generator);
Packit Service 501009
}
Packit Service 501009