Merge "Dispose of ash."
This commit is contained in:
commit
c8626ba480
85 changed files with 2 additions and 25738 deletions
|
|
@ -1,12 +0,0 @@
|
|||
LOCAL_PATH:= $(call my-dir)
|
||||
include $(CLEAR_VARS)
|
||||
|
||||
# Static library
|
||||
# ========================================================
|
||||
|
||||
include $(CLEAR_VARS)
|
||||
LOCAL_MODULE:= liblinenoise
|
||||
LOCAL_SRC_FILES := linenoise.c
|
||||
|
||||
|
||||
include $(BUILD_STATIC_LIBRARY)
|
||||
|
|
@ -1,28 +0,0 @@
|
|||
Copyright (c) 2010, Salvatore Sanfilippo <antirez at gmail dot com>
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
|
||||
* Neither the name of Redis nor the names of its contributors may be used
|
||||
to endorse or promote products derived from this software without
|
||||
specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
|
|
@ -1,449 +0,0 @@
|
|||
/* linenoise.c -- guerrilla line editing library against the idea that a
|
||||
* line editing lib needs to be 20,000 lines of C code.
|
||||
*
|
||||
* You can find the latest source code at:
|
||||
*
|
||||
* http://github.com/antirez/linenoise
|
||||
*
|
||||
* Does a number of crazy assumptions that happen to be true in 99.9999% of
|
||||
* the 2010 UNIX computers around.
|
||||
*
|
||||
* Copyright (c) 2010, Salvatore Sanfilippo <antirez at gmail dot com>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* * Neither the name of Redis nor the names of its contributors may be used
|
||||
* to endorse or promote products derived from this software without
|
||||
* specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* References:
|
||||
* - http://invisible-island.net/xterm/ctlseqs/ctlseqs.html
|
||||
* - http://www.3waylabs.com/nw/WWW/products/wizcon/vt220.html
|
||||
*
|
||||
* Todo list:
|
||||
* - Switch to gets() if $TERM is something we can't support.
|
||||
* - Filter bogus Ctrl+<char> combinations.
|
||||
* - Win32 support
|
||||
*
|
||||
* Bloat:
|
||||
* - Completion?
|
||||
* - History search like Ctrl+r in readline?
|
||||
*
|
||||
* List of escape sequences used by this program, we do everything just
|
||||
* with three sequences. In order to be so cheap we may have some
|
||||
* flickering effect with some slow terminal, but the lesser sequences
|
||||
* the more compatible.
|
||||
*
|
||||
* CHA (Cursor Horizontal Absolute)
|
||||
* Sequence: ESC [ n G
|
||||
* Effect: moves cursor to column n
|
||||
*
|
||||
* EL (Erase Line)
|
||||
* Sequence: ESC [ n K
|
||||
* Effect: if n is 0 or missing, clear from cursor to end of line
|
||||
* Effect: if n is 1, clear from beginning of line to cursor
|
||||
* Effect: if n is 2, clear entire line
|
||||
*
|
||||
* CUF (CUrsor Forward)
|
||||
* Sequence: ESC [ n C
|
||||
* Effect: moves cursor forward of n chars
|
||||
*
|
||||
*/
|
||||
|
||||
#include <termios.h>
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#define LINENOISE_MAX_LINE 4096
|
||||
static char *unsupported_term[] = {"dumb","cons25",NULL};
|
||||
|
||||
static struct termios orig_termios; /* in order to restore at exit */
|
||||
static int rawmode = 0; /* for atexit() function to check if restore is needed*/
|
||||
static int atexit_registered = 0; /* register atexit just 1 time */
|
||||
static int history_max_len = 100;
|
||||
static int history_len = 0;
|
||||
char **history = NULL;
|
||||
|
||||
static void linenoiseAtExit(void);
|
||||
int linenoiseHistoryAdd(const char *line);
|
||||
|
||||
static int isUnsupportedTerm(void) {
|
||||
char *term = getenv("TERM");
|
||||
int j;
|
||||
|
||||
if (term == NULL) return 0;
|
||||
for (j = 0; unsupported_term[j]; j++)
|
||||
if (!strcasecmp(term,unsupported_term[j])) return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void freeHistory(void) {
|
||||
if (history) {
|
||||
int j;
|
||||
|
||||
for (j = 0; j < history_len; j++)
|
||||
free(history[j]);
|
||||
free(history);
|
||||
}
|
||||
}
|
||||
|
||||
static int enableRawMode(int fd) {
|
||||
struct termios raw;
|
||||
|
||||
if (!isatty(STDIN_FILENO)) goto fatal;
|
||||
if (!atexit_registered) {
|
||||
atexit(linenoiseAtExit);
|
||||
atexit_registered = 1;
|
||||
}
|
||||
if (tcgetattr(fd,&orig_termios) == -1) goto fatal;
|
||||
|
||||
raw = orig_termios; /* modify the original mode */
|
||||
/* input modes: no break, no CR to NL, no parity check, no strip char,
|
||||
* no start/stop output control. */
|
||||
raw.c_iflag &= ~(BRKINT | ICRNL | INPCK | ISTRIP | IXON);
|
||||
/* output modes - disable post processing */
|
||||
raw.c_oflag &= ~(OPOST);
|
||||
/* control modes - set 8 bit chars */
|
||||
raw.c_cflag |= (CS8);
|
||||
/* local modes - choing off, canonical off, no extended functions,
|
||||
* no signal chars (^Z,^C) */
|
||||
raw.c_lflag &= ~(ECHO | ICANON | IEXTEN | ISIG);
|
||||
/* control chars - set return condition: min number of bytes and timer.
|
||||
* We want read to return every single byte, without timeout. */
|
||||
raw.c_cc[VMIN] = 1; raw.c_cc[VTIME] = 0; /* 1 byte, no timer */
|
||||
|
||||
/* put terminal in raw mode */
|
||||
if (tcsetattr(fd,TCSADRAIN,&raw) < 0) goto fatal;
|
||||
rawmode = 1;
|
||||
return 0;
|
||||
|
||||
fatal:
|
||||
errno = ENOTTY;
|
||||
return -1;
|
||||
}
|
||||
|
||||
static void disableRawMode(int fd) {
|
||||
/* Don't even check the return value as it's too late. */
|
||||
if (rawmode && tcsetattr(fd,TCSADRAIN,&orig_termios) != -1)
|
||||
rawmode = 0;
|
||||
}
|
||||
|
||||
/* At exit we'll try to fix the terminal to the initial conditions. */
|
||||
static void linenoiseAtExit(void) {
|
||||
disableRawMode(STDIN_FILENO);
|
||||
freeHistory();
|
||||
}
|
||||
|
||||
static int getColumns(void) {
|
||||
struct winsize ws;
|
||||
|
||||
if (ioctl(1, TIOCGWINSZ, &ws) == -1) return 4096;
|
||||
if (ws.ws_col == 0) {
|
||||
return 4096;
|
||||
}
|
||||
return ws.ws_col;
|
||||
}
|
||||
|
||||
static int effectiveLen(const char* prompt) {
|
||||
int col = 0;
|
||||
char c;
|
||||
// TODO: Handle escape sequences.
|
||||
while ( (c = *prompt++) != 0 ) {
|
||||
if (c == '\n') {
|
||||
col = 0;
|
||||
} else {
|
||||
col++;
|
||||
}
|
||||
}
|
||||
return col;
|
||||
}
|
||||
|
||||
static void refreshLine(int fd, const char *prompt, char *buf, size_t len, size_t pos, size_t cols) {
|
||||
char seq[64];
|
||||
size_t plen = effectiveLen(prompt);
|
||||
|
||||
while((plen+pos) >= cols) {
|
||||
buf++;
|
||||
len--;
|
||||
pos--;
|
||||
}
|
||||
while (plen+len > cols) {
|
||||
len--;
|
||||
}
|
||||
|
||||
/* Cursor to left edge */
|
||||
snprintf(seq,64,"\x1b[0G");
|
||||
if (write(fd,seq,strlen(seq)) == -1) return;
|
||||
/* Write the prompt and the current buffer content */
|
||||
if (write(fd,prompt,strlen(prompt)) == -1) return;
|
||||
if (write(fd,buf,len) == -1) return;
|
||||
/* Erase to right */
|
||||
snprintf(seq,64,"\x1b[0K");
|
||||
if (write(fd,seq,strlen(seq)) == -1) return;
|
||||
/* Move cursor to original position. */
|
||||
snprintf(seq,64,"\x1b[0G\x1b[%dC", (int)(pos+plen));
|
||||
if (write(fd,seq,strlen(seq)) == -1) return;
|
||||
}
|
||||
|
||||
static int linenoisePrompt(int fd, char *buf, size_t buflen, const char *prompt) {
|
||||
size_t plen = strlen(prompt);
|
||||
size_t pos = 0;
|
||||
size_t len = 0;
|
||||
size_t cols = getColumns();
|
||||
int history_index = 0;
|
||||
|
||||
buf[0] = '\0';
|
||||
buflen--; /* Make sure there is always space for the nulterm */
|
||||
|
||||
/* The latest history entry is always our current buffer, that
|
||||
* initially is just an empty string. */
|
||||
linenoiseHistoryAdd("");
|
||||
|
||||
if (write(fd,prompt,plen) == -1) return -1;
|
||||
while(1) {
|
||||
char c;
|
||||
int nread;
|
||||
char seq[2];
|
||||
|
||||
nread = read(fd,&c,1);
|
||||
if (nread <= 0) return len;
|
||||
switch(c) {
|
||||
case 10: /* line feed. */
|
||||
case 13: /* enter */
|
||||
history_len--;
|
||||
return len;
|
||||
case 4: /* ctrl-d */
|
||||
history_len--;
|
||||
return (len == 0) ? -1 : (int)len;
|
||||
case 3: /* ctrl-c */
|
||||
errno = EAGAIN;
|
||||
return -1;
|
||||
case 127: /* backspace */
|
||||
case 8: /* ctrl-h */
|
||||
if (pos > 0 && len > 0) {
|
||||
memmove(buf+pos-1,buf+pos,len-pos);
|
||||
pos--;
|
||||
len--;
|
||||
buf[len] = '\0';
|
||||
refreshLine(fd,prompt,buf,len,pos,cols);
|
||||
}
|
||||
break;
|
||||
case 20: /* ctrl-t */
|
||||
if (pos > 0 && pos < len) {
|
||||
int aux = buf[pos-1];
|
||||
buf[pos-1] = buf[pos];
|
||||
buf[pos] = aux;
|
||||
if (pos != len-1) pos++;
|
||||
refreshLine(fd,prompt,buf,len,pos,cols);
|
||||
}
|
||||
break;
|
||||
case 2: /* ctrl-b */
|
||||
goto left_arrow;
|
||||
case 6: /* ctrl-f */
|
||||
goto right_arrow;
|
||||
case 16: /* ctrl-p */
|
||||
seq[1] = 65;
|
||||
goto up_down_arrow;
|
||||
case 14: /* ctrl-n */
|
||||
seq[1] = 66;
|
||||
goto up_down_arrow;
|
||||
break;
|
||||
case 27: /* escape sequence */
|
||||
if (read(fd,seq,2) == -1) break;
|
||||
if (seq[0] == 91 && seq[1] == 68) {
|
||||
left_arrow:
|
||||
/* left arrow */
|
||||
if (pos > 0) {
|
||||
pos--;
|
||||
refreshLine(fd,prompt,buf,len,pos,cols);
|
||||
}
|
||||
} else if (seq[0] == 91 && seq[1] == 67) {
|
||||
right_arrow:
|
||||
/* right arrow */
|
||||
if (pos != len) {
|
||||
pos++;
|
||||
refreshLine(fd,prompt,buf,len,pos,cols);
|
||||
}
|
||||
} else if (seq[0] == 91 && (seq[1] == 65 || seq[1] == 66)) {
|
||||
up_down_arrow:
|
||||
/* up and down arrow: history */
|
||||
if (history_len > 1) {
|
||||
/* Update the current history entry before to
|
||||
* overwrite it with tne next one. */
|
||||
free(history[history_len-1-history_index]);
|
||||
history[history_len-1-history_index] = strdup(buf);
|
||||
/* Show the new entry */
|
||||
history_index += (seq[1] == 65) ? 1 : -1;
|
||||
if (history_index < 0) {
|
||||
history_index = 0;
|
||||
break;
|
||||
} else if (history_index >= history_len) {
|
||||
history_index = history_len-1;
|
||||
break;
|
||||
}
|
||||
strncpy(buf,history[history_len-1-history_index],buflen);
|
||||
buf[buflen] = '\0';
|
||||
len = pos = strlen(buf);
|
||||
refreshLine(fd,prompt,buf,len,pos,cols);
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
if (len < buflen) {
|
||||
if (len == pos) {
|
||||
buf[pos] = c;
|
||||
pos++;
|
||||
len++;
|
||||
buf[len] = '\0';
|
||||
if (plen+len < cols) {
|
||||
/* Avoid a full update of the line in the
|
||||
* trivial case. */
|
||||
if (write(fd,&c,1) == -1) return -1;
|
||||
} else {
|
||||
refreshLine(fd,prompt,buf,len,pos,cols);
|
||||
}
|
||||
} else {
|
||||
memmove(buf+pos+1,buf+pos,len-pos);
|
||||
buf[pos] = c;
|
||||
len++;
|
||||
pos++;
|
||||
buf[len] = '\0';
|
||||
refreshLine(fd,prompt,buf,len,pos,cols);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 21: /* Ctrl+u, delete the whole line. */
|
||||
buf[0] = '\0';
|
||||
pos = len = 0;
|
||||
refreshLine(fd,prompt,buf,len,pos,cols);
|
||||
break;
|
||||
case 11: /* Ctrl+k, delete from current to end of line. */
|
||||
buf[pos] = '\0';
|
||||
len = pos;
|
||||
refreshLine(fd,prompt,buf,len,pos,cols);
|
||||
break;
|
||||
case 1: /* Ctrl+a, go to the start of the line */
|
||||
pos = 0;
|
||||
refreshLine(fd,prompt,buf,len,pos,cols);
|
||||
break;
|
||||
case 5: /* ctrl+e, go to the end of the line */
|
||||
pos = len;
|
||||
refreshLine(fd,prompt,buf,len,pos,cols);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return len;
|
||||
}
|
||||
|
||||
static int linenoiseRaw(char *buf, size_t buflen, const char *prompt) {
|
||||
int fd = STDIN_FILENO;
|
||||
int count;
|
||||
|
||||
if (buflen == 0) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
if (!isatty(STDIN_FILENO)) {
|
||||
if (fgets(buf, buflen, stdin) == NULL) return -1;
|
||||
count = strlen(buf);
|
||||
if (count && buf[count-1] == '\n') {
|
||||
count--;
|
||||
buf[count] = '\0';
|
||||
}
|
||||
} else {
|
||||
if (enableRawMode(fd) == -1) return -1;
|
||||
count = linenoisePrompt(fd, buf, buflen, prompt);
|
||||
disableRawMode(fd);
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
char *linenoise(const char *prompt) {
|
||||
char buf[LINENOISE_MAX_LINE];
|
||||
int count;
|
||||
|
||||
if (isUnsupportedTerm()) {
|
||||
size_t len;
|
||||
|
||||
printf("%s",prompt);
|
||||
fflush(stdout);
|
||||
if (fgets(buf,LINENOISE_MAX_LINE,stdin) == NULL) return NULL;
|
||||
len = strlen(buf);
|
||||
while(len && (buf[len-1] == '\n' || buf[len-1] == '\r')) {
|
||||
len--;
|
||||
buf[len] = '\0';
|
||||
}
|
||||
return strdup(buf);
|
||||
} else {
|
||||
count = linenoiseRaw(buf,LINENOISE_MAX_LINE,prompt);
|
||||
if (count == -1) return NULL;
|
||||
return strdup(buf);
|
||||
}
|
||||
}
|
||||
|
||||
/* Using a circular buffer is smarter, but a bit more complex to handle. */
|
||||
int linenoiseHistoryAdd(const char *line) {
|
||||
char *linecopy;
|
||||
|
||||
if (history_max_len == 0) return 0;
|
||||
if (history == 0) {
|
||||
history = malloc(sizeof(char*)*history_max_len);
|
||||
if (history == NULL) return 0;
|
||||
memset(history,0,(sizeof(char*)*history_max_len));
|
||||
}
|
||||
linecopy = strdup(line);
|
||||
if (!linecopy) return 0;
|
||||
if (history_len == history_max_len) {
|
||||
memmove(history,history+1,sizeof(char*)*(history_max_len-1));
|
||||
history_len--;
|
||||
}
|
||||
history[history_len] = linecopy;
|
||||
history_len++;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int linenoiseHistorySetMaxLen(int len) {
|
||||
char **new;
|
||||
|
||||
if (len < 1) return 0;
|
||||
if (history) {
|
||||
int tocopy = history_len;
|
||||
|
||||
new = malloc(sizeof(char*)*len);
|
||||
if (new == NULL) return 0;
|
||||
if (len < tocopy) tocopy = len;
|
||||
memcpy(new,history+(history_max_len-tocopy), sizeof(char*)*tocopy);
|
||||
free(history);
|
||||
history = new;
|
||||
}
|
||||
history_max_len = len;
|
||||
if (history_len > history_max_len)
|
||||
history_len = history_max_len;
|
||||
return 1;
|
||||
}
|
||||
|
|
@ -1,41 +0,0 @@
|
|||
/* linenoise.h -- guerrilla line editing library against the idea that a
|
||||
* line editing lib needs to be 20,000 lines of C code.
|
||||
*
|
||||
* See linenoise.c for more information.
|
||||
*
|
||||
* Copyright (c) 2010, Salvatore Sanfilippo <antirez at gmail dot com>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* * Neither the name of Redis nor the names of its contributors may be used
|
||||
* to endorse or promote products derived from this software without
|
||||
* specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef __LINENOISE_H
|
||||
#define __LINENOISE_H
|
||||
|
||||
char *linenoise(const char *prompt);
|
||||
int linenoiseHistoryAdd(const char *line);
|
||||
int linenoiseHistorySetMaxLen(int len);
|
||||
|
||||
#endif /* __LINENOISE_H */
|
||||
|
|
@ -1,61 +1,5 @@
|
|||
LOCAL_PATH:= $(call my-dir)
|
||||
include $(CLEAR_VARS)
|
||||
|
||||
LOCAL_SRC_FILES:= \
|
||||
alias.c \
|
||||
arith.c \
|
||||
arith_lex.c \
|
||||
builtins.c \
|
||||
cd.c \
|
||||
error.c \
|
||||
eval.c \
|
||||
exec.c \
|
||||
expand.c \
|
||||
input.c \
|
||||
jobs.c \
|
||||
main.c \
|
||||
memalloc.c \
|
||||
miscbltin.c \
|
||||
mystring.c \
|
||||
nodes.c \
|
||||
options.c \
|
||||
parser.c \
|
||||
redir.c \
|
||||
show.c \
|
||||
syntax.c \
|
||||
trap.c \
|
||||
output.c \
|
||||
var.c \
|
||||
bltin/echo.c \
|
||||
init.c
|
||||
|
||||
LOCAL_MODULE:= ash
|
||||
LOCAL_MODULE_TAGS:= shell_ash
|
||||
|
||||
LOCAL_CFLAGS += -DSHELL -DWITH_LINENOISE
|
||||
|
||||
LOCAL_STATIC_LIBRARIES := liblinenoise
|
||||
|
||||
LOCAL_C_INCLUDES += system/core/liblinenoise
|
||||
|
||||
make_ash_files: PRIVATE_SRC_FILES := $(SRC_FILES)
|
||||
make_ash_files: PRIVATE_CFLAGS := $(LOCAL_CFLAGS)
|
||||
make_ash_files:
|
||||
p4 edit arith.c arith_lex.c arith.h builtins.h builtins.c
|
||||
p4 edit init.c nodes.c nodes.h token.h
|
||||
sh ./mktokens
|
||||
bison -o arith.c arith.y
|
||||
flex -o arith_lex.c arith_lex.l
|
||||
perl -ne 'print if ( /^\#\s*define\s+ARITH/ );' < arith.c > arith.h
|
||||
sh ./mkbuiltins shell.h builtins.def . -Wall -O2
|
||||
sh ./mknodes.sh nodetypes nodes.c.pat .
|
||||
sh ./mkinit.sh $(PRIVATE_SRC_FILES)
|
||||
|
||||
include $(BUILD_EXECUTABLE)
|
||||
|
||||
|
||||
# create /system/bin/sh symlink to $(TARGET_SHELL)
|
||||
# not the optimal place for this, but a fitting one
|
||||
# Create the /system/bin/sh symlink to $(TARGET_SHELL).
|
||||
# Currently, Android's shell is external/mksh.
|
||||
|
||||
OUTSYSTEMBINSH := $(TARGET_OUT)/bin/sh
|
||||
LOCAL_MODULE := systembinsh
|
||||
|
|
|
|||
31
sh/NOTICE
31
sh/NOTICE
|
|
@ -1,31 +0,0 @@
|
|||
Copyright (c) 1991, 1993
|
||||
The Regents of the University of California. All rights reserved.
|
||||
|
||||
This code is derived from software contributed to Berkeley by
|
||||
Kenneth Almquist.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
1. Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
3. Neither the name of the University nor the names of its contributors
|
||||
may be used to endorse or promote products derived from this software
|
||||
without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
SUCH DAMAGE.
|
||||
|
||||
|
||||
357
sh/TOUR
357
sh/TOUR
|
|
@ -1,357 +0,0 @@
|
|||
# $NetBSD: TOUR,v 1.8 1996/10/16 14:24:56 christos Exp $
|
||||
# @(#)TOUR 8.1 (Berkeley) 5/31/93
|
||||
|
||||
NOTE -- This is the original TOUR paper distributed with ash and
|
||||
does not represent the current state of the shell. It is provided anyway
|
||||
since it provides helpful information for how the shell is structured,
|
||||
but be warned that things have changed -- the current shell is
|
||||
still under development.
|
||||
|
||||
================================================================
|
||||
|
||||
A Tour through Ash
|
||||
|
||||
Copyright 1989 by Kenneth Almquist.
|
||||
|
||||
|
||||
DIRECTORIES: The subdirectory bltin contains commands which can
|
||||
be compiled stand-alone. The rest of the source is in the main
|
||||
ash directory.
|
||||
|
||||
SOURCE CODE GENERATORS: Files whose names begin with "mk" are
|
||||
programs that generate source code. A complete list of these
|
||||
programs is:
|
||||
|
||||
program intput files generates
|
||||
------- ------------ ---------
|
||||
mkbuiltins builtins builtins.h builtins.c
|
||||
mkinit *.c init.c
|
||||
mknodes nodetypes nodes.h nodes.c
|
||||
mksignames - signames.h signames.c
|
||||
mksyntax - syntax.h syntax.c
|
||||
mktokens - token.h
|
||||
bltin/mkexpr unary_op binary_op operators.h operators.c
|
||||
|
||||
There are undoubtedly too many of these. Mkinit searches all the
|
||||
C source files for entries looking like:
|
||||
|
||||
INIT {
|
||||
x = 1; /* executed during initialization */
|
||||
}
|
||||
|
||||
RESET {
|
||||
x = 2; /* executed when the shell does a longjmp
|
||||
back to the main command loop */
|
||||
}
|
||||
|
||||
SHELLPROC {
|
||||
x = 3; /* executed when the shell runs a shell procedure */
|
||||
}
|
||||
|
||||
It pulls this code out into routines which are when particular
|
||||
events occur. The intent is to improve modularity by isolating
|
||||
the information about which modules need to be explicitly
|
||||
initialized/reset within the modules themselves.
|
||||
|
||||
Mkinit recognizes several constructs for placing declarations in
|
||||
the init.c file.
|
||||
INCLUDE "file.h"
|
||||
includes a file. The storage class MKINIT makes a declaration
|
||||
available in the init.c file, for example:
|
||||
MKINIT int funcnest; /* depth of function calls */
|
||||
MKINIT alone on a line introduces a structure or union declara-
|
||||
tion:
|
||||
MKINIT
|
||||
struct redirtab {
|
||||
short renamed[10];
|
||||
};
|
||||
Preprocessor #define statements are copied to init.c without any
|
||||
special action to request this.
|
||||
|
||||
INDENTATION: The ash source is indented in multiples of six
|
||||
spaces. The only study that I have heard of on the subject con-
|
||||
cluded that the optimal amount to indent is in the range of four
|
||||
to six spaces. I use six spaces since it is not too big a jump
|
||||
from the widely used eight spaces. If you really hate six space
|
||||
indentation, use the adjind (source included) program to change
|
||||
it to something else.
|
||||
|
||||
EXCEPTIONS: Code for dealing with exceptions appears in
|
||||
exceptions.c. The C language doesn't include exception handling,
|
||||
so I implement it using setjmp and longjmp. The global variable
|
||||
exception contains the type of exception. EXERROR is raised by
|
||||
calling error. EXINT is an interrupt. EXSHELLPROC is an excep-
|
||||
tion which is raised when a shell procedure is invoked. The pur-
|
||||
pose of EXSHELLPROC is to perform the cleanup actions associated
|
||||
with other exceptions. After these cleanup actions, the shell
|
||||
can interpret a shell procedure itself without exec'ing a new
|
||||
copy of the shell.
|
||||
|
||||
INTERRUPTS: In an interactive shell, an interrupt will cause an
|
||||
EXINT exception to return to the main command loop. (Exception:
|
||||
EXINT is not raised if the user traps interrupts using the trap
|
||||
command.) The INTOFF and INTON macros (defined in exception.h)
|
||||
provide uninterruptable critical sections. Between the execution
|
||||
of INTOFF and the execution of INTON, interrupt signals will be
|
||||
held for later delivery. INTOFF and INTON can be nested.
|
||||
|
||||
MEMALLOC.C: Memalloc.c defines versions of malloc and realloc
|
||||
which call error when there is no memory left. It also defines a
|
||||
stack oriented memory allocation scheme. Allocating off a stack
|
||||
is probably more efficient than allocation using malloc, but the
|
||||
big advantage is that when an exception occurs all we have to do
|
||||
to free up the memory in use at the time of the exception is to
|
||||
restore the stack pointer. The stack is implemented using a
|
||||
linked list of blocks.
|
||||
|
||||
STPUTC: If the stack were contiguous, it would be easy to store
|
||||
strings on the stack without knowing in advance how long the
|
||||
string was going to be:
|
||||
p = stackptr;
|
||||
*p++ = c; /* repeated as many times as needed */
|
||||
stackptr = p;
|
||||
The folloing three macros (defined in memalloc.h) perform these
|
||||
operations, but grow the stack if you run off the end:
|
||||
STARTSTACKSTR(p);
|
||||
STPUTC(c, p); /* repeated as many times as needed */
|
||||
grabstackstr(p);
|
||||
|
||||
We now start a top-down look at the code:
|
||||
|
||||
MAIN.C: The main routine performs some initialization, executes
|
||||
the user's profile if necessary, and calls cmdloop. Cmdloop is
|
||||
repeatedly parses and executes commands.
|
||||
|
||||
OPTIONS.C: This file contains the option processing code. It is
|
||||
called from main to parse the shell arguments when the shell is
|
||||
invoked, and it also contains the set builtin. The -i and -j op-
|
||||
tions (the latter turns on job control) require changes in signal
|
||||
handling. The routines setjobctl (in jobs.c) and setinteractive
|
||||
(in trap.c) are called to handle changes to these options.
|
||||
|
||||
PARSING: The parser code is all in parser.c. A recursive des-
|
||||
cent parser is used. Syntax tables (generated by mksyntax) are
|
||||
used to classify characters during lexical analysis. There are
|
||||
three tables: one for normal use, one for use when inside single
|
||||
quotes, and one for use when inside double quotes. The tables
|
||||
are machine dependent because they are indexed by character vari-
|
||||
ables and the range of a char varies from machine to machine.
|
||||
|
||||
PARSE OUTPUT: The output of the parser consists of a tree of
|
||||
nodes. The various types of nodes are defined in the file node-
|
||||
types.
|
||||
|
||||
Nodes of type NARG are used to represent both words and the con-
|
||||
tents of here documents. An early version of ash kept the con-
|
||||
tents of here documents in temporary files, but keeping here do-
|
||||
cuments in memory typically results in significantly better per-
|
||||
formance. It would have been nice to make it an option to use
|
||||
temporary files for here documents, for the benefit of small
|
||||
machines, but the code to keep track of when to delete the tem-
|
||||
porary files was complex and I never fixed all the bugs in it.
|
||||
(AT&T has been maintaining the Bourne shell for more than ten
|
||||
years, and to the best of my knowledge they still haven't gotten
|
||||
it to handle temporary files correctly in obscure cases.)
|
||||
|
||||
The text field of a NARG structure points to the text of the
|
||||
word. The text consists of ordinary characters and a number of
|
||||
special codes defined in parser.h. The special codes are:
|
||||
|
||||
CTLVAR Variable substitution
|
||||
CTLENDVAR End of variable substitution
|
||||
CTLBACKQ Command substitution
|
||||
CTLBACKQ|CTLQUOTE Command substitution inside double quotes
|
||||
CTLESC Escape next character
|
||||
|
||||
A variable substitution contains the following elements:
|
||||
|
||||
CTLVAR type name '=' [ alternative-text CTLENDVAR ]
|
||||
|
||||
The type field is a single character specifying the type of sub-
|
||||
stitution. The possible types are:
|
||||
|
||||
VSNORMAL $var
|
||||
VSMINUS ${var-text}
|
||||
VSMINUS|VSNUL ${var:-text}
|
||||
VSPLUS ${var+text}
|
||||
VSPLUS|VSNUL ${var:+text}
|
||||
VSQUESTION ${var?text}
|
||||
VSQUESTION|VSNUL ${var:?text}
|
||||
VSASSIGN ${var=text}
|
||||
VSASSIGN|VSNUL ${var=text}
|
||||
|
||||
In addition, the type field will have the VSQUOTE flag set if the
|
||||
variable is enclosed in double quotes. The name of the variable
|
||||
comes next, terminated by an equals sign. If the type is not
|
||||
VSNORMAL, then the text field in the substitution follows, ter-
|
||||
minated by a CTLENDVAR byte.
|
||||
|
||||
Commands in back quotes are parsed and stored in a linked list.
|
||||
The locations of these commands in the string are indicated by
|
||||
CTLBACKQ and CTLBACKQ+CTLQUOTE characters, depending upon whether
|
||||
the back quotes were enclosed in double quotes.
|
||||
|
||||
The character CTLESC escapes the next character, so that in case
|
||||
any of the CTL characters mentioned above appear in the input,
|
||||
they can be passed through transparently. CTLESC is also used to
|
||||
escape '*', '?', '[', and '!' characters which were quoted by the
|
||||
user and thus should not be used for file name generation.
|
||||
|
||||
CTLESC characters have proved to be particularly tricky to get
|
||||
right. In the case of here documents which are not subject to
|
||||
variable and command substitution, the parser doesn't insert any
|
||||
CTLESC characters to begin with (so the contents of the text
|
||||
field can be written without any processing). Other here docu-
|
||||
ments, and words which are not subject to splitting and file name
|
||||
generation, have the CTLESC characters removed during the vari-
|
||||
able and command substitution phase. Words which are subject
|
||||
splitting and file name generation have the CTLESC characters re-
|
||||
moved as part of the file name phase.
|
||||
|
||||
EXECUTION: Command execution is handled by the following files:
|
||||
eval.c The top level routines.
|
||||
redir.c Code to handle redirection of input and output.
|
||||
jobs.c Code to handle forking, waiting, and job control.
|
||||
exec.c Code to to path searches and the actual exec sys call.
|
||||
expand.c Code to evaluate arguments.
|
||||
var.c Maintains the variable symbol table. Called from expand.c.
|
||||
|
||||
EVAL.C: Evaltree recursively executes a parse tree. The exit
|
||||
status is returned in the global variable exitstatus. The alter-
|
||||
native entry evalbackcmd is called to evaluate commands in back
|
||||
quotes. It saves the result in memory if the command is a buil-
|
||||
tin; otherwise it forks off a child to execute the command and
|
||||
connects the standard output of the child to a pipe.
|
||||
|
||||
JOBS.C: To create a process, you call makejob to return a job
|
||||
structure, and then call forkshell (passing the job structure as
|
||||
an argument) to create the process. Waitforjob waits for a job
|
||||
to complete. These routines take care of process groups if job
|
||||
control is defined.
|
||||
|
||||
REDIR.C: Ash allows file descriptors to be redirected and then
|
||||
restored without forking off a child process. This is accom-
|
||||
plished by duplicating the original file descriptors. The redir-
|
||||
tab structure records where the file descriptors have be dupli-
|
||||
cated to.
|
||||
|
||||
EXEC.C: The routine find_command locates a command, and enters
|
||||
the command in the hash table if it is not already there. The
|
||||
third argument specifies whether it is to print an error message
|
||||
if the command is not found. (When a pipeline is set up,
|
||||
find_command is called for all the commands in the pipeline be-
|
||||
fore any forking is done, so to get the commands into the hash
|
||||
table of the parent process. But to make command hashing as
|
||||
transparent as possible, we silently ignore errors at that point
|
||||
and only print error messages if the command cannot be found
|
||||
later.)
|
||||
|
||||
The routine shellexec is the interface to the exec system call.
|
||||
|
||||
EXPAND.C: Arguments are processed in three passes. The first
|
||||
(performed by the routine argstr) performs variable and command
|
||||
substitution. The second (ifsbreakup) performs word splitting
|
||||
and the third (expandmeta) performs file name generation. If the
|
||||
"/u" directory is simulated, then when "/u/username" is replaced
|
||||
by the user's home directory, the flag "didudir" is set. This
|
||||
tells the cd command that it should print out the directory name,
|
||||
just as it would if the "/u" directory were implemented using
|
||||
symbolic links.
|
||||
|
||||
VAR.C: Variables are stored in a hash table. Probably we should
|
||||
switch to extensible hashing. The variable name is stored in the
|
||||
same string as the value (using the format "name=value") so that
|
||||
no string copying is needed to create the environment of a com-
|
||||
mand. Variables which the shell references internally are preal-
|
||||
located so that the shell can reference the values of these vari-
|
||||
ables without doing a lookup.
|
||||
|
||||
When a program is run, the code in eval.c sticks any environment
|
||||
variables which precede the command (as in "PATH=xxx command") in
|
||||
the variable table as the simplest way to strip duplicates, and
|
||||
then calls "environment" to get the value of the environment.
|
||||
There are two consequences of this. First, if an assignment to
|
||||
PATH precedes the command, the value of PATH before the assign-
|
||||
ment must be remembered and passed to shellexec. Second, if the
|
||||
program turns out to be a shell procedure, the strings from the
|
||||
environment variables which preceded the command must be pulled
|
||||
out of the table and replaced with strings obtained from malloc,
|
||||
since the former will automatically be freed when the stack (see
|
||||
the entry on memalloc.c) is emptied.
|
||||
|
||||
BUILTIN COMMANDS: The procedures for handling these are scat-
|
||||
tered throughout the code, depending on which location appears
|
||||
most appropriate. They can be recognized because their names al-
|
||||
ways end in "cmd". The mapping from names to procedures is
|
||||
specified in the file builtins, which is processed by the mkbuil-
|
||||
tins command.
|
||||
|
||||
A builtin command is invoked with argc and argv set up like a
|
||||
normal program. A builtin command is allowed to overwrite its
|
||||
arguments. Builtin routines can call nextopt to do option pars-
|
||||
ing. This is kind of like getopt, but you don't pass argc and
|
||||
argv to it. Builtin routines can also call error. This routine
|
||||
normally terminates the shell (or returns to the main command
|
||||
loop if the shell is interactive), but when called from a builtin
|
||||
command it causes the builtin command to terminate with an exit
|
||||
status of 2.
|
||||
|
||||
The directory bltins contains commands which can be compiled in-
|
||||
dependently but can also be built into the shell for efficiency
|
||||
reasons. The makefile in this directory compiles these programs
|
||||
in the normal fashion (so that they can be run regardless of
|
||||
whether the invoker is ash), but also creates a library named
|
||||
bltinlib.a which can be linked with ash. The header file bltin.h
|
||||
takes care of most of the differences between the ash and the
|
||||
stand-alone environment. The user should call the main routine
|
||||
"main", and #define main to be the name of the routine to use
|
||||
when the program is linked into ash. This #define should appear
|
||||
before bltin.h is included; bltin.h will #undef main if the pro-
|
||||
gram is to be compiled stand-alone.
|
||||
|
||||
CD.C: This file defines the cd and pwd builtins. The pwd com-
|
||||
mand runs /bin/pwd the first time it is invoked (unless the user
|
||||
has already done a cd to an absolute pathname), but then
|
||||
remembers the current directory and updates it when the cd com-
|
||||
mand is run, so subsequent pwd commands run very fast. The main
|
||||
complication in the cd command is in the docd command, which
|
||||
resolves symbolic links into actual names and informs the user
|
||||
where the user ended up if he crossed a symbolic link.
|
||||
|
||||
SIGNALS: Trap.c implements the trap command. The routine set-
|
||||
signal figures out what action should be taken when a signal is
|
||||
received and invokes the signal system call to set the signal ac-
|
||||
tion appropriately. When a signal that a user has set a trap for
|
||||
is caught, the routine "onsig" sets a flag. The routine dotrap
|
||||
is called at appropriate points to actually handle the signal.
|
||||
When an interrupt is caught and no trap has been set for that
|
||||
signal, the routine "onint" in error.c is called.
|
||||
|
||||
OUTPUT: Ash uses it's own output routines. There are three out-
|
||||
put structures allocated. "Output" represents the standard out-
|
||||
put, "errout" the standard error, and "memout" contains output
|
||||
which is to be stored in memory. This last is used when a buil-
|
||||
tin command appears in backquotes, to allow its output to be col-
|
||||
lected without doing any I/O through the UNIX operating system.
|
||||
The variables out1 and out2 normally point to output and errout,
|
||||
respectively, but they are set to point to memout when appropri-
|
||||
ate inside backquotes.
|
||||
|
||||
INPUT: The basic input routine is pgetc, which reads from the
|
||||
current input file. There is a stack of input files; the current
|
||||
input file is the top file on this stack. The code allows the
|
||||
input to come from a string rather than a file. (This is for the
|
||||
-c option and the "." and eval builtin commands.) The global
|
||||
variable plinno is saved and restored when files are pushed and
|
||||
popped from the stack. The parser routines store the number of
|
||||
the current line in this variable.
|
||||
|
||||
DEBUGGING: If DEBUG is defined in shell.h, then the shell will
|
||||
write debugging information to the file $HOME/trace. Most of
|
||||
this is done using the TRACE macro, which takes a set of printf
|
||||
arguments inside two sets of parenthesis. Example:
|
||||
"TRACE(("n=%d0, n))". The double parenthesis are necessary be-
|
||||
cause the preprocessor can't handle functions with a variable
|
||||
number of arguments. Defining DEBUG also causes the shell to
|
||||
generate a core dump if it is sent a quit signal. The tracing
|
||||
code is in show.c.
|
||||
|
|
@ -1,9 +0,0 @@
|
|||
# Copyright 2010 Google Inc. All Rights Reserved.
|
||||
#Fri Jul 16 10:03:08 PDT 2010
|
||||
currentVersion=Unknown
|
||||
version=1.17
|
||||
isNative=true
|
||||
name=ash
|
||||
keywords=ash
|
||||
onDevice=true
|
||||
homepage=http\://www.in-ulm.de/~mascheck/various/ash/
|
||||
273
sh/alias.c
273
sh/alias.c
|
|
@ -1,273 +0,0 @@
|
|||
/* $NetBSD: alias.c,v 1.12 2003/08/07 09:05:29 agc Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to Berkeley by
|
||||
* Kenneth Almquist.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
#ifndef lint
|
||||
#if 0
|
||||
static char sccsid[] = "@(#)alias.c 8.3 (Berkeley) 5/4/95";
|
||||
#else
|
||||
__RCSID("$NetBSD: alias.c,v 1.12 2003/08/07 09:05:29 agc Exp $");
|
||||
#endif
|
||||
#endif /* not lint */
|
||||
|
||||
#include <stdlib.h>
|
||||
#include "shell.h"
|
||||
#include "input.h"
|
||||
#include "output.h"
|
||||
#include "error.h"
|
||||
#include "memalloc.h"
|
||||
#include "mystring.h"
|
||||
#include "alias.h"
|
||||
#include "options.h" /* XXX for argptr (should remove?) */
|
||||
#include "var.h"
|
||||
|
||||
#define ATABSIZE 39
|
||||
|
||||
struct alias *atab[ATABSIZE];
|
||||
|
||||
STATIC void setalias(char *, char *);
|
||||
STATIC int unalias(char *);
|
||||
STATIC struct alias **hashalias(char *);
|
||||
|
||||
STATIC
|
||||
void
|
||||
setalias(char *name, char *val)
|
||||
{
|
||||
struct alias *ap, **app;
|
||||
|
||||
app = hashalias(name);
|
||||
for (ap = *app; ap; ap = ap->next) {
|
||||
if (equal(name, ap->name)) {
|
||||
INTOFF;
|
||||
ckfree(ap->val);
|
||||
ap->val = savestr(val);
|
||||
INTON;
|
||||
return;
|
||||
}
|
||||
}
|
||||
/* not found */
|
||||
INTOFF;
|
||||
ap = ckmalloc(sizeof (struct alias));
|
||||
ap->name = savestr(name);
|
||||
/*
|
||||
* XXX - HACK: in order that the parser will not finish reading the
|
||||
* alias value off the input before processing the next alias, we
|
||||
* dummy up an extra space at the end of the alias. This is a crock
|
||||
* and should be re-thought. The idea (if you feel inclined to help)
|
||||
* is to avoid alias recursions. The mechanism used is: when
|
||||
* expanding an alias, the value of the alias is pushed back on the
|
||||
* input as a string and a pointer to the alias is stored with the
|
||||
* string. The alias is marked as being in use. When the input
|
||||
* routine finishes reading the string, it markes the alias not
|
||||
* in use. The problem is synchronization with the parser. Since
|
||||
* it reads ahead, the alias is marked not in use before the
|
||||
* resulting token(s) is next checked for further alias sub. The
|
||||
* H A C K is that we add a little fluff after the alias value
|
||||
* so that the string will not be exhausted. This is a good
|
||||
* idea ------- ***NOT***
|
||||
*/
|
||||
#ifdef notyet
|
||||
ap->val = savestr(val);
|
||||
#else /* hack */
|
||||
{
|
||||
int len = strlen(val);
|
||||
ap->val = ckmalloc(len + 2);
|
||||
memcpy(ap->val, val, len);
|
||||
ap->val[len] = ' '; /* fluff */
|
||||
ap->val[len+1] = '\0';
|
||||
}
|
||||
#endif
|
||||
ap->next = *app;
|
||||
*app = ap;
|
||||
INTON;
|
||||
}
|
||||
|
||||
STATIC int
|
||||
unalias(char *name)
|
||||
{
|
||||
struct alias *ap, **app;
|
||||
|
||||
app = hashalias(name);
|
||||
|
||||
for (ap = *app; ap; app = &(ap->next), ap = ap->next) {
|
||||
if (equal(name, ap->name)) {
|
||||
/*
|
||||
* if the alias is currently in use (i.e. its
|
||||
* buffer is being used by the input routine) we
|
||||
* just null out the name instead of freeing it.
|
||||
* We could clear it out later, but this situation
|
||||
* is so rare that it hardly seems worth it.
|
||||
*/
|
||||
if (ap->flag & ALIASINUSE)
|
||||
*ap->name = '\0';
|
||||
else {
|
||||
INTOFF;
|
||||
*app = ap->next;
|
||||
ckfree(ap->name);
|
||||
ckfree(ap->val);
|
||||
ckfree(ap);
|
||||
INTON;
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
}
|
||||
|
||||
return (1);
|
||||
}
|
||||
|
||||
#ifdef mkinit
|
||||
MKINIT void rmaliases(void);
|
||||
|
||||
SHELLPROC {
|
||||
rmaliases();
|
||||
}
|
||||
#endif
|
||||
|
||||
void
|
||||
rmaliases(void)
|
||||
{
|
||||
struct alias *ap, *tmp;
|
||||
int i;
|
||||
|
||||
INTOFF;
|
||||
for (i = 0; i < ATABSIZE; i++) {
|
||||
ap = atab[i];
|
||||
atab[i] = NULL;
|
||||
while (ap) {
|
||||
ckfree(ap->name);
|
||||
ckfree(ap->val);
|
||||
tmp = ap;
|
||||
ap = ap->next;
|
||||
ckfree(tmp);
|
||||
}
|
||||
}
|
||||
INTON;
|
||||
}
|
||||
|
||||
struct alias *
|
||||
lookupalias(char *name, int check)
|
||||
{
|
||||
struct alias *ap = *hashalias(name);
|
||||
|
||||
for (; ap; ap = ap->next) {
|
||||
if (equal(name, ap->name)) {
|
||||
if (check && (ap->flag & ALIASINUSE))
|
||||
return (NULL);
|
||||
return (ap);
|
||||
}
|
||||
}
|
||||
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
char *
|
||||
get_alias_text(char *name)
|
||||
{
|
||||
struct alias *ap;
|
||||
|
||||
ap = lookupalias(name, 0);
|
||||
if (ap == NULL)
|
||||
return NULL;
|
||||
return ap->val;
|
||||
}
|
||||
|
||||
/*
|
||||
* TODO - sort output
|
||||
*/
|
||||
int
|
||||
aliascmd(int argc, char **argv)
|
||||
{
|
||||
char *n, *v;
|
||||
int ret = 0;
|
||||
struct alias *ap;
|
||||
|
||||
if (argc == 1) {
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ATABSIZE; i++)
|
||||
for (ap = atab[i]; ap; ap = ap->next) {
|
||||
if (*ap->name != '\0') {
|
||||
out1fmt("alias %s=", ap->name);
|
||||
print_quoted(ap->val);
|
||||
out1c('\n');
|
||||
}
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
while ((n = *++argv) != NULL) {
|
||||
if ((v = strchr(n+1, '=')) == NULL) { /* n+1: funny ksh stuff */
|
||||
if ((ap = lookupalias(n, 0)) == NULL) {
|
||||
outfmt(out2, "alias: %s not found\n", n);
|
||||
ret = 1;
|
||||
} else {
|
||||
out1fmt("alias %s=", n);
|
||||
print_quoted(ap->val);
|
||||
out1c('\n');
|
||||
}
|
||||
} else {
|
||||
*v++ = '\0';
|
||||
setalias(n, v);
|
||||
}
|
||||
}
|
||||
|
||||
return (ret);
|
||||
}
|
||||
|
||||
int
|
||||
unaliascmd(int argc, char **argv)
|
||||
{
|
||||
int i;
|
||||
|
||||
while ((i = nextopt("a")) != '\0') {
|
||||
if (i == 'a') {
|
||||
rmaliases();
|
||||
return (0);
|
||||
}
|
||||
}
|
||||
for (i = 0; *argptr; argptr++)
|
||||
i = unalias(*argptr);
|
||||
|
||||
return (i);
|
||||
}
|
||||
|
||||
STATIC struct alias **
|
||||
hashalias(char *p)
|
||||
{
|
||||
unsigned int hashval;
|
||||
|
||||
hashval = *p << 4;
|
||||
while (*p)
|
||||
hashval+= *p++;
|
||||
return &atab[hashval % ATABSIZE];
|
||||
}
|
||||
50
sh/alias.h
50
sh/alias.h
|
|
@ -1,50 +0,0 @@
|
|||
/* $NetBSD: alias.h,v 1.6 2003/08/07 09:05:29 agc Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to Berkeley by
|
||||
* Kenneth Almquist.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)alias.h 8.2 (Berkeley) 5/4/95
|
||||
*/
|
||||
|
||||
#define ALIASINUSE 1
|
||||
|
||||
struct alias {
|
||||
struct alias *next;
|
||||
char *name;
|
||||
char *val;
|
||||
int flag;
|
||||
};
|
||||
|
||||
struct alias *lookupalias(char *, int);
|
||||
char *get_alias_text(char *);
|
||||
int aliascmd(int, char **);
|
||||
int unaliascmd(int, char **);
|
||||
void rmaliases(void);
|
||||
1587
sh/arith.c
1587
sh/arith.c
File diff suppressed because it is too large
Load diff
25
sh/arith.h
25
sh/arith.h
|
|
@ -1,25 +0,0 @@
|
|||
#define ARITH_NUM 258
|
||||
#define ARITH_LPAREN 259
|
||||
#define ARITH_RPAREN 260
|
||||
#define ARITH_OR 261
|
||||
#define ARITH_AND 262
|
||||
#define ARITH_BOR 263
|
||||
#define ARITH_BXOR 264
|
||||
#define ARITH_BAND 265
|
||||
#define ARITH_NE 266
|
||||
#define ARITH_EQ 267
|
||||
#define ARITH_LE 268
|
||||
#define ARITH_GE 269
|
||||
#define ARITH_GT 270
|
||||
#define ARITH_LT 271
|
||||
#define ARITH_RSHIFT 272
|
||||
#define ARITH_LSHIFT 273
|
||||
#define ARITH_SUB 274
|
||||
#define ARITH_ADD 275
|
||||
#define ARITH_REM 276
|
||||
#define ARITH_DIV 277
|
||||
#define ARITH_MUL 278
|
||||
#define ARITH_BNOT 279
|
||||
#define ARITH_NOT 280
|
||||
#define ARITH_UNARYPLUS 281
|
||||
#define ARITH_UNARYMINUS 282
|
||||
199
sh/arith.y
199
sh/arith.y
|
|
@ -1,199 +0,0 @@
|
|||
%{
|
||||
/* $NetBSD: arith.y,v 1.17 2003/09/17 17:33:36 jmmv Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to Berkeley by
|
||||
* Kenneth Almquist.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
#ifndef lint
|
||||
#if 0
|
||||
static char sccsid[] = "@(#)arith.y 8.3 (Berkeley) 5/4/95";
|
||||
#else
|
||||
__RCSID("$NetBSD: arith.y,v 1.17 2003/09/17 17:33:36 jmmv Exp $");
|
||||
#endif
|
||||
#endif /* not lint */
|
||||
|
||||
#include <stdlib.h>
|
||||
#include "expand.h"
|
||||
#include "shell.h"
|
||||
#include "error.h"
|
||||
#include "output.h"
|
||||
#include "memalloc.h"
|
||||
|
||||
const char *arith_buf, *arith_startbuf;
|
||||
|
||||
void yyerror(const char *);
|
||||
#ifdef TESTARITH
|
||||
int main(int , char *[]);
|
||||
int error(char *);
|
||||
#endif
|
||||
|
||||
%}
|
||||
%token ARITH_NUM ARITH_LPAREN ARITH_RPAREN
|
||||
|
||||
%left ARITH_OR
|
||||
%left ARITH_AND
|
||||
%left ARITH_BOR
|
||||
%left ARITH_BXOR
|
||||
%left ARITH_BAND
|
||||
%left ARITH_EQ ARITH_NE
|
||||
%left ARITH_LT ARITH_GT ARITH_GE ARITH_LE
|
||||
%left ARITH_LSHIFT ARITH_RSHIFT
|
||||
%left ARITH_ADD ARITH_SUB
|
||||
%left ARITH_MUL ARITH_DIV ARITH_REM
|
||||
%left ARITH_UNARYMINUS ARITH_UNARYPLUS ARITH_NOT ARITH_BNOT
|
||||
%%
|
||||
|
||||
exp: expr {
|
||||
return ($1);
|
||||
}
|
||||
;
|
||||
|
||||
|
||||
expr: ARITH_LPAREN expr ARITH_RPAREN { $$ = $2; }
|
||||
| expr ARITH_OR expr { $$ = $1 ? $1 : $3 ? $3 : 0; }
|
||||
| expr ARITH_AND expr { $$ = $1 ? ( $3 ? $3 : 0 ) : 0; }
|
||||
| expr ARITH_BOR expr { $$ = $1 | $3; }
|
||||
| expr ARITH_BXOR expr { $$ = $1 ^ $3; }
|
||||
| expr ARITH_BAND expr { $$ = $1 & $3; }
|
||||
| expr ARITH_EQ expr { $$ = $1 == $3; }
|
||||
| expr ARITH_GT expr { $$ = $1 > $3; }
|
||||
| expr ARITH_GE expr { $$ = $1 >= $3; }
|
||||
| expr ARITH_LT expr { $$ = $1 < $3; }
|
||||
| expr ARITH_LE expr { $$ = $1 <= $3; }
|
||||
| expr ARITH_NE expr { $$ = $1 != $3; }
|
||||
| expr ARITH_LSHIFT expr { $$ = $1 << $3; }
|
||||
| expr ARITH_RSHIFT expr { $$ = $1 >> $3; }
|
||||
| expr ARITH_ADD expr { $$ = $1 + $3; }
|
||||
| expr ARITH_SUB expr { $$ = $1 - $3; }
|
||||
| expr ARITH_MUL expr { $$ = $1 * $3; }
|
||||
| expr ARITH_DIV expr {
|
||||
if ($3 == 0)
|
||||
yyerror("division by zero");
|
||||
$$ = $1 / $3;
|
||||
}
|
||||
| expr ARITH_REM expr {
|
||||
if ($3 == 0)
|
||||
yyerror("division by zero");
|
||||
$$ = $1 % $3;
|
||||
}
|
||||
| ARITH_NOT expr { $$ = !($2); }
|
||||
| ARITH_BNOT expr { $$ = ~($2); }
|
||||
| ARITH_SUB expr %prec ARITH_UNARYMINUS { $$ = -($2); }
|
||||
| ARITH_ADD expr %prec ARITH_UNARYPLUS { $$ = $2; }
|
||||
| ARITH_NUM
|
||||
;
|
||||
%%
|
||||
int
|
||||
arith(s)
|
||||
const char *s;
|
||||
{
|
||||
long result;
|
||||
|
||||
arith_buf = arith_startbuf = s;
|
||||
|
||||
INTOFF;
|
||||
result = yyparse();
|
||||
arith_lex_reset(); /* reprime lex */
|
||||
INTON;
|
||||
|
||||
return (result);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* The exp(1) builtin.
|
||||
*/
|
||||
int
|
||||
expcmd(argc, argv)
|
||||
int argc;
|
||||
char **argv;
|
||||
{
|
||||
const char *p;
|
||||
char *concat;
|
||||
char **ap;
|
||||
long i;
|
||||
|
||||
if (argc > 1) {
|
||||
p = argv[1];
|
||||
if (argc > 2) {
|
||||
/*
|
||||
* concatenate arguments
|
||||
*/
|
||||
STARTSTACKSTR(concat);
|
||||
ap = argv + 2;
|
||||
for (;;) {
|
||||
while (*p)
|
||||
STPUTC(*p++, concat);
|
||||
if ((p = *ap++) == NULL)
|
||||
break;
|
||||
STPUTC(' ', concat);
|
||||
}
|
||||
STPUTC('\0', concat);
|
||||
p = grabstackstr(concat);
|
||||
}
|
||||
} else
|
||||
p = "";
|
||||
|
||||
i = arith(p);
|
||||
|
||||
out1fmt("%ld\n", i);
|
||||
return (! i);
|
||||
}
|
||||
|
||||
/*************************/
|
||||
#ifdef TEST_ARITH
|
||||
#include <stdio.h>
|
||||
main(argc, argv)
|
||||
char *argv[];
|
||||
{
|
||||
printf("%d\n", exp(argv[1]));
|
||||
}
|
||||
error(s)
|
||||
char *s;
|
||||
{
|
||||
fprintf(stderr, "exp: %s\n", s);
|
||||
exit(1);
|
||||
}
|
||||
#endif
|
||||
|
||||
void
|
||||
yyerror(s)
|
||||
const char *s;
|
||||
{
|
||||
|
||||
// yyerrok;
|
||||
yyclearin;
|
||||
arith_lex_reset(); /* reprime lex */
|
||||
error("arithmetic expression: %s: \"%s\"", s, arith_startbuf);
|
||||
/* NOTREACHED */
|
||||
}
|
||||
1890
sh/arith_lex.c
1890
sh/arith_lex.c
File diff suppressed because it is too large
Load diff
103
sh/arith_lex.l
103
sh/arith_lex.l
|
|
@ -1,103 +0,0 @@
|
|||
%{
|
||||
/* $NetBSD: arith_lex.l,v 1.12.6.1 2005/04/07 11:38:58 tron Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to Berkeley by
|
||||
* Kenneth Almquist.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
#ifndef lint
|
||||
#if 0
|
||||
static char sccsid[] = "@(#)arith_lex.l 8.3 (Berkeley) 5/4/95";
|
||||
#else
|
||||
__RCSID("$NetBSD: arith_lex.l,v 1.12.6.1 2005/04/07 11:38:58 tron Exp $");
|
||||
#endif
|
||||
#endif /* not lint */
|
||||
|
||||
#include <unistd.h>
|
||||
#include "arith.h"
|
||||
#include "error.h"
|
||||
#include "expand.h"
|
||||
#include "var.h"
|
||||
|
||||
extern int yylval;
|
||||
extern char *arith_buf, *arith_startbuf;
|
||||
#undef YY_INPUT
|
||||
#define YY_INPUT(buf,result,max) \
|
||||
result = (*buf = *arith_buf++) ? 1 : YY_NULL;
|
||||
#define YY_NO_UNPUT
|
||||
%}
|
||||
%option noyywrap
|
||||
|
||||
%%
|
||||
[ \t\n] { ; }
|
||||
0x[0-9a-fA-F]+ { yylval = strtol(yytext, 0, 0); return(ARITH_NUM); }
|
||||
0[0-7]* { yylval = strtol(yytext, 0, 0); return(ARITH_NUM); }
|
||||
[1-9][0-9]* { yylval = strtol(yytext, 0, 0); return(ARITH_NUM); }
|
||||
[A-Za-z_][A-Za-z_0-9]* { char *v = lookupvar(yytext);
|
||||
if (v) {
|
||||
yylval = strtol(v, &v, 0);
|
||||
if (*v == 0)
|
||||
return ARITH_NUM;
|
||||
}
|
||||
error("arith: syntax error: \"%s\"", arith_startbuf);
|
||||
}
|
||||
"(" { return(ARITH_LPAREN); }
|
||||
")" { return(ARITH_RPAREN); }
|
||||
"||" { return(ARITH_OR); }
|
||||
"&&" { return(ARITH_AND); }
|
||||
"|" { return(ARITH_BOR); }
|
||||
"^" { return(ARITH_BXOR); }
|
||||
"&" { return(ARITH_BAND); }
|
||||
"==" { return(ARITH_EQ); }
|
||||
"!=" { return(ARITH_NE); }
|
||||
">" { return(ARITH_GT); }
|
||||
">=" { return(ARITH_GE); }
|
||||
"<" { return(ARITH_LT); }
|
||||
"<=" { return(ARITH_LE); }
|
||||
"<<" { return(ARITH_LSHIFT); }
|
||||
">>" { return(ARITH_RSHIFT); }
|
||||
"*" { return(ARITH_MUL); }
|
||||
"/" { return(ARITH_DIV); }
|
||||
"%" { return(ARITH_REM); }
|
||||
"+" { return(ARITH_ADD); }
|
||||
"-" { return(ARITH_SUB); }
|
||||
"~" { return(ARITH_BNOT); }
|
||||
"!" { return(ARITH_NOT); }
|
||||
. { error("arith: syntax error: \"%s\"", arith_startbuf); }
|
||||
%%
|
||||
|
||||
void
|
||||
arith_lex_reset() {
|
||||
#ifdef YY_NEW_FILE
|
||||
YY_NEW_FILE;
|
||||
#endif
|
||||
}
|
||||
|
|
@ -1,94 +0,0 @@
|
|||
/* $NetBSD: bltin.h,v 1.11 2003/08/07 09:05:40 agc Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1991, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to Berkeley by
|
||||
* Kenneth Almquist.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)bltin.h 8.1 (Berkeley) 5/31/93
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file is included by programs which are optionally built into the
|
||||
* shell. If SHELL is defined, we try to map the standard UNIX library
|
||||
* routines to ash routines using defines.
|
||||
*/
|
||||
|
||||
#include "../shell.h"
|
||||
#include "../mystring.h"
|
||||
#ifdef SHELL
|
||||
#include "../output.h"
|
||||
#include "../error.h"
|
||||
#undef stdout
|
||||
#undef stderr
|
||||
#undef putc
|
||||
#undef putchar
|
||||
#undef fileno
|
||||
#define stdout out1
|
||||
#define stderr out2
|
||||
#define printf out1fmt
|
||||
#define putc(c, file) outc(c, file)
|
||||
#define putchar(c) out1c(c)
|
||||
#define FILE struct output
|
||||
#define fprintf outfmt
|
||||
#define fputs outstr
|
||||
#define fflush flushout
|
||||
#define fileno(f) ((f)->fd)
|
||||
#define INITARGS(argv)
|
||||
#define err sh_err
|
||||
#define verr sh_verr
|
||||
#define errx sh_errx
|
||||
#define verrx sh_verrx
|
||||
#define warn sh_warn
|
||||
#define vwarn sh_vwarn
|
||||
#define warnx sh_warnx
|
||||
#define vwarnx sh_vwarnx
|
||||
#define exit sh_exit
|
||||
#define setprogname(s)
|
||||
#define getprogname() commandname
|
||||
#define setlocate(l,s) 0
|
||||
|
||||
#define getenv(p) bltinlookup((p),0)
|
||||
|
||||
#else
|
||||
#undef NULL
|
||||
#include <stdio.h>
|
||||
#undef main
|
||||
#define INITARGS(argv) if ((commandname = argv[0]) == NULL) {fputs("Argc is zero\n", stderr); exit(2);} else
|
||||
#endif
|
||||
|
||||
pointer stalloc(int);
|
||||
void error(const char *, ...);
|
||||
void sh_warnx(const char *, ...);
|
||||
void sh_exit(int) __attribute__((__noreturn__));
|
||||
|
||||
int echocmd(int, char **);
|
||||
|
||||
|
||||
extern const char *commandname;
|
||||
109
sh/bltin/echo.1
109
sh/bltin/echo.1
|
|
@ -1,109 +0,0 @@
|
|||
.\" $NetBSD: echo.1,v 1.13 2003/08/07 09:05:40 agc Exp $
|
||||
.\"
|
||||
.\" Copyright (c) 1991, 1993
|
||||
.\" The Regents of the University of California. All rights reserved.
|
||||
.\"
|
||||
.\" This code is derived from software contributed to Berkeley by
|
||||
.\" Kenneth Almquist.
|
||||
.\" Copyright 1989 by Kenneth Almquist
|
||||
.\"
|
||||
.\" Redistribution and use in source and binary forms, with or without
|
||||
.\" modification, are permitted provided that the following conditions
|
||||
.\" are met:
|
||||
.\" 1. Redistributions of source code must retain the above copyright
|
||||
.\" notice, this list of conditions and the following disclaimer.
|
||||
.\" 2. Redistributions in binary form must reproduce the above copyright
|
||||
.\" notice, this list of conditions and the following disclaimer in the
|
||||
.\" documentation and/or other materials provided with the distribution.
|
||||
.\" 3. Neither the name of the University nor the names of its contributors
|
||||
.\" may be used to endorse or promote products derived from this software
|
||||
.\" without specific prior written permission.
|
||||
.\"
|
||||
.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
.\" SUCH DAMAGE.
|
||||
.\"
|
||||
.\" @(#)echo.1 8.1 (Berkeley) 5/31/93
|
||||
.\"
|
||||
.Dd May 31, 1993
|
||||
.Dt ECHO 1
|
||||
.Os
|
||||
.Sh NAME
|
||||
.Nm echo
|
||||
.Nd produce message in a shell script
|
||||
.Sh SYNOPSIS
|
||||
.Nm
|
||||
.Op Fl n | Fl e
|
||||
.Ar args ...
|
||||
.Sh DESCRIPTION
|
||||
.Nm
|
||||
prints its arguments on the standard output, separated by spaces.
|
||||
Unless the
|
||||
.Fl n
|
||||
option is present, a newline is output following the arguments.
|
||||
The
|
||||
.Fl e
|
||||
option causes
|
||||
.Nm
|
||||
to treat the escape sequences specially, as described in the following
|
||||
paragraph.
|
||||
The
|
||||
.Fl e
|
||||
option is the default, and is provided solely for compatibility with
|
||||
other systems.
|
||||
Only one of the options
|
||||
.Fl n
|
||||
and
|
||||
.Fl e
|
||||
may be given.
|
||||
.Pp
|
||||
If any of the following sequences of characters is encountered during
|
||||
output, the sequence is not output. Instead, the specified action is
|
||||
performed:
|
||||
.Bl -tag -width indent
|
||||
.It Li \eb
|
||||
A backspace character is output.
|
||||
.It Li \ec
|
||||
Subsequent output is suppressed. This is normally used at the end of the
|
||||
last argument to suppress the trailing newline that
|
||||
.Nm
|
||||
would otherwise output.
|
||||
.It Li \ef
|
||||
Output a form feed.
|
||||
.It Li \en
|
||||
Output a newline character.
|
||||
.It Li \er
|
||||
Output a carriage return.
|
||||
.It Li \et
|
||||
Output a (horizontal) tab character.
|
||||
.It Li \ev
|
||||
Output a vertical tab.
|
||||
.It Li \e0 Ns Ar digits
|
||||
Output the character whose value is given by zero to three digits.
|
||||
If there are zero digits, a nul character is output.
|
||||
.It Li \e\e
|
||||
Output a backslash.
|
||||
.El
|
||||
.Sh HINTS
|
||||
Remember that backslash is special to the shell and needs to be escaped.
|
||||
To output a message to standard error, say
|
||||
.Pp
|
||||
.D1 echo message \*[Gt]\*[Am]2
|
||||
.Sh BUGS
|
||||
The octal character escape mechanism
|
||||
.Pq Li \e0 Ns Ar digits
|
||||
differs from the
|
||||
C language mechanism.
|
||||
.Pp
|
||||
There is no way to force
|
||||
.Nm
|
||||
to treat its arguments literally, rather than interpreting them as
|
||||
options and escape sequences.
|
||||
116
sh/bltin/echo.c
116
sh/bltin/echo.c
|
|
@ -1,116 +0,0 @@
|
|||
/* $NetBSD: echo.c,v 1.12 2005/02/06 04:43:43 perry Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1991, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to Berkeley by
|
||||
* Kenneth Almquist.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)echo.c 8.1 (Berkeley) 5/31/93
|
||||
*/
|
||||
|
||||
/*
|
||||
* Echo command.
|
||||
*
|
||||
* echo is steeped in tradition - several of them!
|
||||
* netbsd has supported 'echo [-n | -e] args' in spite of -e not being
|
||||
* documented anywhere.
|
||||
* Posix requires that -n be supported, output from strings containing
|
||||
* \ is implementation defined
|
||||
* The Single Unix Spec requires that \ escapes be treated as if -e
|
||||
* were set, but that -n not be treated as an option.
|
||||
* (ksh supports 'echo [-eEn] args', but not -- so that it is actually
|
||||
* impossible to actually output '-n')
|
||||
*
|
||||
* It is suggested that 'printf "%b" "string"' be used to get \ sequences
|
||||
* expanded. printf is now a builtin of netbsd's sh and csh.
|
||||
*/
|
||||
|
||||
//#define main echocmd
|
||||
|
||||
#include "bltin.h"
|
||||
|
||||
int
|
||||
echocmd(int argc, char **argv)
|
||||
{
|
||||
char **ap;
|
||||
char *p;
|
||||
char c;
|
||||
int count;
|
||||
int nflag = 0;
|
||||
int eflag = 0;
|
||||
|
||||
ap = argv;
|
||||
if (argc)
|
||||
ap++;
|
||||
|
||||
if ((p = *ap) != NULL) {
|
||||
if (equal(p, "-n")) {
|
||||
nflag = 1;
|
||||
ap++;
|
||||
} else if (equal(p, "-e")) {
|
||||
eflag = 1;
|
||||
ap++;
|
||||
}
|
||||
}
|
||||
|
||||
while ((p = *ap++) != NULL) {
|
||||
while ((c = *p++) != '\0') {
|
||||
if (c == '\\' && eflag) {
|
||||
switch (*p++) {
|
||||
case 'a': c = '\a'; break; /* bell */
|
||||
case 'b': c = '\b'; break;
|
||||
case 'c': return 0; /* exit */
|
||||
case 'e': c = 033; break; /* escape */
|
||||
case 'f': c = '\f'; break;
|
||||
case 'n': c = '\n'; break;
|
||||
case 'r': c = '\r'; break;
|
||||
case 't': c = '\t'; break;
|
||||
case 'v': c = '\v'; break;
|
||||
case '\\': break; /* c = '\\' */
|
||||
case '0':
|
||||
c = 0;
|
||||
count = 3;
|
||||
while (--count >= 0 && (unsigned)(*p - '0') < 8)
|
||||
c = (c << 3) + (*p++ - '0');
|
||||
break;
|
||||
default:
|
||||
/* Output the '/' and char following */
|
||||
p--;
|
||||
break;
|
||||
}
|
||||
}
|
||||
putchar(c);
|
||||
}
|
||||
if (*ap)
|
||||
putchar(' ');
|
||||
}
|
||||
if (! nflag)
|
||||
putchar('\n');
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -1,61 +0,0 @@
|
|||
/*
|
||||
* This file was generated by the mkbuiltins program.
|
||||
*/
|
||||
|
||||
#include "shell.h"
|
||||
#include "builtins.h"
|
||||
|
||||
const struct builtincmd builtincmd[] = {
|
||||
|
||||
{ "command", bltincmd },
|
||||
{ "bg", bgcmd },
|
||||
{ "cd", cdcmd },
|
||||
{ "chdir", cdcmd },
|
||||
{ "echo", echocmd },
|
||||
{ "exp", expcmd },
|
||||
{ "let", expcmd },
|
||||
{ "false", falsecmd },
|
||||
#if WITH_HISTORY
|
||||
{ "fc", histcmd },
|
||||
{ "inputrc", inputrc },
|
||||
#endif
|
||||
{ "fg", fgcmd },
|
||||
{ "getopts", getoptscmd },
|
||||
{ "hash", hashcmd },
|
||||
{ "jobid", jobidcmd },
|
||||
{ "jobs", jobscmd },
|
||||
{ "local", localcmd },
|
||||
#ifndef SMALL
|
||||
#endif
|
||||
{ "pwd", pwdcmd },
|
||||
{ "read", readcmd },
|
||||
{ "setvar", setvarcmd },
|
||||
{ "true", truecmd },
|
||||
{ "type", typecmd },
|
||||
{ "umask", umaskcmd },
|
||||
{ "unalias", unaliascmd },
|
||||
{ "wait", waitcmd },
|
||||
{ "alias", aliascmd },
|
||||
{ "ulimit", ulimitcmd },
|
||||
{ "wordexp", wordexpcmd },
|
||||
{ 0, 0 },
|
||||
};
|
||||
|
||||
const struct builtincmd splbltincmd[] = {
|
||||
{ "break", breakcmd },
|
||||
{ "continue", breakcmd },
|
||||
{ ".", dotcmd },
|
||||
{ "eval", evalcmd },
|
||||
{ "exec", execcmd },
|
||||
{ "exit", exitcmd },
|
||||
{ "export", exportcmd },
|
||||
{ "readonly", exportcmd },
|
||||
{ "return", returncmd },
|
||||
{ "set", setcmd },
|
||||
{ "shift", shiftcmd },
|
||||
{ "times", timescmd },
|
||||
{ "trap", trapcmd },
|
||||
{ ":", truecmd },
|
||||
{ "unset", unsetcmd },
|
||||
{ 0, 0 },
|
||||
};
|
||||
|
|
@ -1,94 +0,0 @@
|
|||
#!/bin/sh -
|
||||
# $NetBSD: builtins.def,v 1.21 2004/07/13 15:05:59 seb Exp $
|
||||
#
|
||||
# Copyright (c) 1991, 1993
|
||||
# The Regents of the University of California. All rights reserved.
|
||||
#
|
||||
# This code is derived from software contributed to Berkeley by
|
||||
# Kenneth Almquist.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions
|
||||
# are met:
|
||||
# 1. Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# 2. Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in the
|
||||
# documentation and/or other materials provided with the distribution.
|
||||
# 3. Neither the name of the University nor the names of its contributors
|
||||
# may be used to endorse or promote products derived from this software
|
||||
# without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
# ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
# SUCH DAMAGE.
|
||||
#
|
||||
# @(#)builtins.def 8.4 (Berkeley) 5/4/95
|
||||
|
||||
#
|
||||
# This file lists all the builtin commands. The first column is the name
|
||||
# of a C routine.
|
||||
# The -j flag specifies that this command is to be excluded from systems
|
||||
# without job control.
|
||||
# The -h flag specifies that this command is to be excluded from systems
|
||||
# based on the SMALL compile-time symbol.
|
||||
# The -s flag specifies that this is a posix 'special builtin' command.
|
||||
# The -u flag specifies that this is a posix 'standard utility'.
|
||||
# The rest of the line specifies the command name or names used to run
|
||||
# the command.
|
||||
|
||||
bltincmd -u command
|
||||
bgcmd -j -u bg
|
||||
breakcmd -s break -s continue
|
||||
cdcmd -u cd chdir
|
||||
dotcmd -s .
|
||||
echocmd echo
|
||||
evalcmd -s eval
|
||||
execcmd -s exec
|
||||
exitcmd -s exit
|
||||
expcmd exp let
|
||||
exportcmd -s export -s readonly
|
||||
falsecmd -u false
|
||||
#if WITH_HISTORY
|
||||
histcmd -h -u fc
|
||||
inputrc inputrc
|
||||
#endif
|
||||
fgcmd -j -u fg
|
||||
getoptscmd -u getopts
|
||||
hashcmd hash
|
||||
jobidcmd jobid
|
||||
jobscmd -u jobs
|
||||
localcmd local
|
||||
#ifndef SMALL
|
||||
##printfcmd printf
|
||||
#endif
|
||||
pwdcmd -u pwd
|
||||
readcmd -u read
|
||||
returncmd -s return
|
||||
setcmd -s set
|
||||
setvarcmd setvar
|
||||
shiftcmd -s shift
|
||||
timescmd -s times
|
||||
trapcmd -s trap
|
||||
truecmd -s : -u true
|
||||
typecmd type
|
||||
umaskcmd -u umask
|
||||
unaliascmd -u unalias
|
||||
unsetcmd -s unset
|
||||
waitcmd -u wait
|
||||
aliascmd -u alias
|
||||
ulimitcmd ulimit
|
||||
##testcmd test [
|
||||
##killcmd -u kill # mandated by posix for 'kill %job'
|
||||
wordexpcmd wordexp
|
||||
#newgrp -u newgrp # optional command in posix
|
||||
|
||||
#exprcmd expr
|
||||
|
|
@ -1,56 +0,0 @@
|
|||
/*
|
||||
* This file was generated by the mkbuiltins program.
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
|
||||
struct builtincmd {
|
||||
const char *name;
|
||||
int (*builtin)(int, char **);
|
||||
};
|
||||
|
||||
extern const struct builtincmd builtincmd[];
|
||||
extern const struct builtincmd splbltincmd[];
|
||||
|
||||
|
||||
int bltincmd(int, char **);
|
||||
int bgcmd(int, char **);
|
||||
int breakcmd(int, char **);
|
||||
int cdcmd(int, char **);
|
||||
int dotcmd(int, char **);
|
||||
int echocmd(int, char **);
|
||||
int evalcmd(int, char **);
|
||||
int execcmd(int, char **);
|
||||
int exitcmd(int, char **);
|
||||
int expcmd(int, char **);
|
||||
int exportcmd(int, char **);
|
||||
int falsecmd(int, char **);
|
||||
#if WITH_HISTORY
|
||||
int histcmd(int, char **);
|
||||
int inputrc(int, char **);
|
||||
#endif
|
||||
int fgcmd(int, char **);
|
||||
int getoptscmd(int, char **);
|
||||
int hashcmd(int, char **);
|
||||
int jobidcmd(int, char **);
|
||||
int jobscmd(int, char **);
|
||||
int localcmd(int, char **);
|
||||
#ifndef SMALL
|
||||
#endif
|
||||
int pwdcmd(int, char **);
|
||||
int readcmd(int, char **);
|
||||
int returncmd(int, char **);
|
||||
int setcmd(int, char **);
|
||||
int setvarcmd(int, char **);
|
||||
int shiftcmd(int, char **);
|
||||
int timescmd(int, char **);
|
||||
int trapcmd(int, char **);
|
||||
int truecmd(int, char **);
|
||||
int typecmd(int, char **);
|
||||
int umaskcmd(int, char **);
|
||||
int unaliascmd(int, char **);
|
||||
int unsetcmd(int, char **);
|
||||
int waitcmd(int, char **);
|
||||
int aliascmd(int, char **);
|
||||
int ulimitcmd(int, char **);
|
||||
int wordexpcmd(int, char **);
|
||||
446
sh/cd.c
446
sh/cd.c
|
|
@ -1,446 +0,0 @@
|
|||
/* $NetBSD: cd.c,v 1.34 2003/11/14 20:00:28 dsl Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1991, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to Berkeley by
|
||||
* Kenneth Almquist.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
#ifndef lint
|
||||
#if 0
|
||||
static char sccsid[] = "@(#)cd.c 8.2 (Berkeley) 5/4/95";
|
||||
#else
|
||||
__RCSID("$NetBSD: cd.c,v 1.34 2003/11/14 20:00:28 dsl Exp $");
|
||||
#endif
|
||||
#endif /* not lint */
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
|
||||
/*
|
||||
* The cd and pwd commands.
|
||||
*/
|
||||
|
||||
#include "shell.h"
|
||||
#include "var.h"
|
||||
#include "nodes.h" /* for jobs.h */
|
||||
#include "jobs.h"
|
||||
#include "options.h"
|
||||
#include "output.h"
|
||||
#include "memalloc.h"
|
||||
#include "error.h"
|
||||
#include "exec.h"
|
||||
#include "redir.h"
|
||||
#include "mystring.h"
|
||||
#include "show.h"
|
||||
#include "cd.h"
|
||||
|
||||
STATIC int docd(char *, int);
|
||||
STATIC char *getcomponent(void);
|
||||
STATIC void updatepwd(char *);
|
||||
STATIC void find_curdir(int noerror);
|
||||
|
||||
char *curdir = NULL; /* current working directory */
|
||||
char *prevdir; /* previous working directory */
|
||||
STATIC char *cdcomppath;
|
||||
|
||||
int
|
||||
cdcmd(int argc, char **argv)
|
||||
{
|
||||
const char *dest;
|
||||
const char *path;
|
||||
char *p, *d;
|
||||
struct stat statb;
|
||||
int print = cdprint; /* set -cdprint to enable */
|
||||
|
||||
nextopt(nullstr);
|
||||
|
||||
/*
|
||||
* Try (quite hard) to have 'curdir' defined, nothing has set
|
||||
* it on entry to the shell, but we want 'cd fred; cd -' to work.
|
||||
*/
|
||||
getpwd(1);
|
||||
dest = *argptr;
|
||||
if (dest == NULL) {
|
||||
dest = bltinlookup("HOME", 1);
|
||||
if (dest == NULL)
|
||||
error("HOME not set");
|
||||
} else {
|
||||
if (argptr[1]) {
|
||||
/* Do 'ksh' style substitution */
|
||||
if (!curdir)
|
||||
error("PWD not set");
|
||||
p = strstr(curdir, dest);
|
||||
if (!p)
|
||||
error("bad substitution");
|
||||
d = stalloc(strlen(curdir) + strlen(argptr[1]) + 1);
|
||||
memcpy(d, curdir, p - curdir);
|
||||
strcpy(d + (p - curdir), argptr[1]);
|
||||
strcat(d, p + strlen(dest));
|
||||
dest = d;
|
||||
print = 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (dest[0] == '-' && dest[1] == '\0') {
|
||||
dest = prevdir ? prevdir : curdir;
|
||||
print = 1;
|
||||
}
|
||||
if (*dest == '\0')
|
||||
dest = ".";
|
||||
if (*dest == '/' || (path = bltinlookup("CDPATH", 1)) == NULL)
|
||||
path = nullstr;
|
||||
while ((p = padvance(&path, dest)) != NULL) {
|
||||
if (stat(p, &statb) >= 0 && S_ISDIR(statb.st_mode)) {
|
||||
if (!print) {
|
||||
/*
|
||||
* XXX - rethink
|
||||
*/
|
||||
if (p[0] == '.' && p[1] == '/' && p[2] != '\0')
|
||||
p += 2;
|
||||
print = strcmp(p, dest);
|
||||
}
|
||||
if (docd(p, print) >= 0)
|
||||
return 0;
|
||||
|
||||
}
|
||||
}
|
||||
error("can't cd to %s", dest);
|
||||
/* NOTREACHED */
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Actually do the chdir. In an interactive shell, print the
|
||||
* directory name if "print" is nonzero.
|
||||
*/
|
||||
|
||||
STATIC int
|
||||
docd(char *dest, int print)
|
||||
{
|
||||
char *p;
|
||||
char *q;
|
||||
char *component;
|
||||
struct stat statb;
|
||||
int first;
|
||||
int badstat;
|
||||
|
||||
TRACE(("docd(\"%s\", %d) called\n", dest, print));
|
||||
|
||||
/*
|
||||
* Check each component of the path. If we find a symlink or
|
||||
* something we can't stat, clear curdir to force a getcwd()
|
||||
* next time we get the value of the current directory.
|
||||
*/
|
||||
badstat = 0;
|
||||
cdcomppath = stalloc(strlen(dest) + 1);
|
||||
scopy(dest, cdcomppath);
|
||||
STARTSTACKSTR(p);
|
||||
if (*dest == '/') {
|
||||
STPUTC('/', p);
|
||||
cdcomppath++;
|
||||
}
|
||||
first = 1;
|
||||
while ((q = getcomponent()) != NULL) {
|
||||
if (q[0] == '\0' || (q[0] == '.' && q[1] == '\0'))
|
||||
continue;
|
||||
if (! first)
|
||||
STPUTC('/', p);
|
||||
first = 0;
|
||||
component = q;
|
||||
while (*q)
|
||||
STPUTC(*q++, p);
|
||||
if (equal(component, ".."))
|
||||
continue;
|
||||
STACKSTRNUL(p);
|
||||
if ((lstat(stackblock(), &statb) < 0)
|
||||
|| (S_ISLNK(statb.st_mode))) {
|
||||
/* print = 1; */
|
||||
badstat = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
INTOFF;
|
||||
if (chdir(dest) < 0) {
|
||||
INTON;
|
||||
return -1;
|
||||
}
|
||||
updatepwd(badstat ? NULL : dest);
|
||||
INTON;
|
||||
if (print && iflag && curdir)
|
||||
out1fmt("%s\n", curdir);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Get the next component of the path name pointed to by cdcomppath.
|
||||
* This routine overwrites the string pointed to by cdcomppath.
|
||||
*/
|
||||
|
||||
STATIC char *
|
||||
getcomponent()
|
||||
{
|
||||
char *p;
|
||||
char *start;
|
||||
|
||||
if ((p = cdcomppath) == NULL)
|
||||
return NULL;
|
||||
start = cdcomppath;
|
||||
while (*p != '/' && *p != '\0')
|
||||
p++;
|
||||
if (*p == '\0') {
|
||||
cdcomppath = NULL;
|
||||
} else {
|
||||
*p++ = '\0';
|
||||
cdcomppath = p;
|
||||
}
|
||||
return start;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Update curdir (the name of the current directory) in response to a
|
||||
* cd command. We also call hashcd to let the routines in exec.c know
|
||||
* that the current directory has changed.
|
||||
*/
|
||||
|
||||
STATIC void
|
||||
updatepwd(char *dir)
|
||||
{
|
||||
char *new;
|
||||
char *p;
|
||||
|
||||
hashcd(); /* update command hash table */
|
||||
|
||||
/*
|
||||
* If our argument is NULL, we don't know the current directory
|
||||
* any more because we traversed a symbolic link or something
|
||||
* we couldn't stat().
|
||||
*/
|
||||
if (dir == NULL || curdir == NULL) {
|
||||
if (prevdir)
|
||||
ckfree(prevdir);
|
||||
INTOFF;
|
||||
prevdir = curdir;
|
||||
curdir = NULL;
|
||||
getpwd(1);
|
||||
INTON;
|
||||
if (curdir)
|
||||
setvar("PWD", curdir, VEXPORT);
|
||||
else
|
||||
unsetvar("PWD", 0);
|
||||
return;
|
||||
}
|
||||
cdcomppath = stalloc(strlen(dir) + 1);
|
||||
scopy(dir, cdcomppath);
|
||||
STARTSTACKSTR(new);
|
||||
if (*dir != '/') {
|
||||
p = curdir;
|
||||
while (*p)
|
||||
STPUTC(*p++, new);
|
||||
if (p[-1] == '/')
|
||||
STUNPUTC(new);
|
||||
}
|
||||
while ((p = getcomponent()) != NULL) {
|
||||
if (equal(p, "..")) {
|
||||
while (new > stackblock() && (STUNPUTC(new), *new) != '/');
|
||||
} else if (*p != '\0' && ! equal(p, ".")) {
|
||||
STPUTC('/', new);
|
||||
while (*p)
|
||||
STPUTC(*p++, new);
|
||||
}
|
||||
}
|
||||
if (new == stackblock())
|
||||
STPUTC('/', new);
|
||||
STACKSTRNUL(new);
|
||||
INTOFF;
|
||||
if (prevdir)
|
||||
ckfree(prevdir);
|
||||
prevdir = curdir;
|
||||
curdir = savestr(stackblock());
|
||||
setvar("PWD", curdir, VEXPORT);
|
||||
INTON;
|
||||
}
|
||||
|
||||
/*
|
||||
* Posix says the default should be 'pwd -L' (as below), however
|
||||
* the 'cd' command (above) does something much nearer to the
|
||||
* posix 'cd -P' (not the posix default of 'cd -L').
|
||||
* If 'cd' is changed to support -P/L then the default here
|
||||
* needs to be revisited if the historic behaviour is to be kept.
|
||||
*/
|
||||
|
||||
int
|
||||
pwdcmd(int argc, char **argv)
|
||||
{
|
||||
int i;
|
||||
char opt = 'L';
|
||||
|
||||
while ((i = nextopt("LP")) != '\0')
|
||||
opt = i;
|
||||
if (*argptr)
|
||||
error("unexpected argument");
|
||||
|
||||
if (opt == 'L')
|
||||
getpwd(0);
|
||||
else
|
||||
find_curdir(0);
|
||||
|
||||
setvar("PWD", curdir, VEXPORT);
|
||||
out1str(curdir);
|
||||
out1c('\n');
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
#define MAXPWD 256
|
||||
|
||||
/*
|
||||
* Find out what the current directory is. If we already know the current
|
||||
* directory, this routine returns immediately.
|
||||
*/
|
||||
void
|
||||
getpwd(int noerror)
|
||||
{
|
||||
char *pwd;
|
||||
struct stat stdot, stpwd;
|
||||
static int first = 1;
|
||||
|
||||
if (curdir)
|
||||
return;
|
||||
|
||||
if (first) {
|
||||
first = 0;
|
||||
pwd = getenv("PWD");
|
||||
if (pwd && *pwd == '/' && stat(".", &stdot) != -1 &&
|
||||
stat(pwd, &stpwd) != -1 &&
|
||||
stdot.st_dev == stpwd.st_dev &&
|
||||
stdot.st_ino == stpwd.st_ino) {
|
||||
curdir = savestr(pwd);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
find_curdir(noerror);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
STATIC void
|
||||
find_curdir(int noerror)
|
||||
{
|
||||
int i;
|
||||
char *pwd;
|
||||
|
||||
/*
|
||||
* Things are a bit complicated here; we could have just used
|
||||
* getcwd, but traditionally getcwd is implemented using popen
|
||||
* to /bin/pwd. This creates a problem for us, since we cannot
|
||||
* keep track of the job if it is being ran behind our backs.
|
||||
* So we re-implement getcwd(), and we suppress interrupts
|
||||
* throughout the process. This is not completely safe, since
|
||||
* the user can still break out of it by killing the pwd program.
|
||||
* We still try to use getcwd for systems that we know have a
|
||||
* c implementation of getcwd, that does not open a pipe to
|
||||
* /bin/pwd.
|
||||
*/
|
||||
#if defined(__NetBSD__) || defined(__SVR4) || defined(__linux__)
|
||||
for (i = MAXPWD;; i *= 2) {
|
||||
pwd = stalloc(i);
|
||||
if (getcwd(pwd, i) != NULL) {
|
||||
curdir = savestr(pwd);
|
||||
return;
|
||||
}
|
||||
stunalloc(pwd);
|
||||
if (errno == ERANGE)
|
||||
continue;
|
||||
if (!noerror)
|
||||
error("getcwd() failed: %s", strerror(errno));
|
||||
return;
|
||||
}
|
||||
#else
|
||||
{
|
||||
char *p;
|
||||
int status;
|
||||
struct job *jp;
|
||||
int pip[2];
|
||||
|
||||
pwd = stalloc(MAXPWD);
|
||||
INTOFF;
|
||||
if (pipe(pip) < 0)
|
||||
error("Pipe call failed");
|
||||
jp = makejob((union node *)NULL, 1);
|
||||
if (forkshell(jp, (union node *)NULL, FORK_NOJOB) == 0) {
|
||||
(void) close(pip[0]);
|
||||
if (pip[1] != 1) {
|
||||
close(1);
|
||||
copyfd(pip[1], 1);
|
||||
close(pip[1]);
|
||||
}
|
||||
(void) execl("/bin/pwd", "pwd", (char *)0);
|
||||
sh_warn("Cannot exec /bin/pwd");
|
||||
exit(1);
|
||||
}
|
||||
(void) close(pip[1]);
|
||||
pip[1] = -1;
|
||||
p = pwd;
|
||||
while ((i = read(pip[0], p, pwd + MAXPWD - p)) > 0
|
||||
|| (i == -1 && errno == EINTR)) {
|
||||
if (i > 0)
|
||||
p += i;
|
||||
}
|
||||
(void) close(pip[0]);
|
||||
pip[0] = -1;
|
||||
status = waitforjob(jp);
|
||||
if (status != 0)
|
||||
error((char *)0);
|
||||
if (i < 0 || p == pwd || p[-1] != '\n') {
|
||||
if (noerror) {
|
||||
INTON;
|
||||
return;
|
||||
}
|
||||
error("pwd command failed");
|
||||
}
|
||||
p[-1] = '\0';
|
||||
INTON;
|
||||
curdir = savestr(pwd);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
35
sh/cd.h
35
sh/cd.h
|
|
@ -1,35 +0,0 @@
|
|||
/* $NetBSD: cd.h,v 1.4 2003/08/07 09:05:30 agc Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1995
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
|
||||
void getpwd(int);
|
||||
int cdcmd(int, char **);
|
||||
int pwdcmd(int, char **);
|
||||
366
sh/error.c
366
sh/error.c
|
|
@ -1,366 +0,0 @@
|
|||
/* $NetBSD: error.c,v 1.31 2003/08/07 09:05:30 agc Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1991, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to Berkeley by
|
||||
* Kenneth Almquist.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
#ifndef lint
|
||||
#if 0
|
||||
static char sccsid[] = "@(#)error.c 8.2 (Berkeley) 5/4/95";
|
||||
#else
|
||||
__RCSID("$NetBSD: error.c,v 1.31 2003/08/07 09:05:30 agc Exp $");
|
||||
#endif
|
||||
#endif /* not lint */
|
||||
|
||||
/*
|
||||
* Errors and exceptions.
|
||||
*/
|
||||
|
||||
#include <signal.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "shell.h"
|
||||
#include "main.h"
|
||||
#include "options.h"
|
||||
#include "output.h"
|
||||
#include "error.h"
|
||||
#include "show.h"
|
||||
|
||||
#define signal bsd_signal
|
||||
/*
|
||||
* Code to handle exceptions in C.
|
||||
*/
|
||||
|
||||
struct jmploc *handler;
|
||||
int exception;
|
||||
volatile int suppressint;
|
||||
volatile int intpending;
|
||||
char *commandname;
|
||||
|
||||
|
||||
static void exverror(int, const char *, va_list)
|
||||
__attribute__((__noreturn__));
|
||||
|
||||
/*
|
||||
* Called to raise an exception. Since C doesn't include exceptions, we
|
||||
* just do a longjmp to the exception handler. The type of exception is
|
||||
* stored in the global variable "exception".
|
||||
*/
|
||||
|
||||
void
|
||||
exraise(int e)
|
||||
{
|
||||
if (handler == NULL)
|
||||
abort();
|
||||
exception = e;
|
||||
longjmp(handler->loc, 1);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Called from trap.c when a SIGINT is received. (If the user specifies
|
||||
* that SIGINT is to be trapped or ignored using the trap builtin, then
|
||||
* this routine is not called.) Suppressint is nonzero when interrupts
|
||||
* are held using the INTOFF macro. The call to _exit is necessary because
|
||||
* there is a short period after a fork before the signal handlers are
|
||||
* set to the appropriate value for the child. (The test for iflag is
|
||||
* just defensive programming.)
|
||||
*/
|
||||
|
||||
void
|
||||
onint(void)
|
||||
{
|
||||
sigset_t nsigset;
|
||||
|
||||
if (suppressint) {
|
||||
intpending = 1;
|
||||
return;
|
||||
}
|
||||
intpending = 0;
|
||||
sigemptyset(&nsigset);
|
||||
sigprocmask(SIG_SETMASK, &nsigset, NULL);
|
||||
if (rootshell && iflag)
|
||||
exraise(EXINT);
|
||||
else {
|
||||
signal(SIGINT, SIG_DFL);
|
||||
raise(SIGINT);
|
||||
}
|
||||
/* NOTREACHED */
|
||||
}
|
||||
|
||||
static void
|
||||
exvwarning(int sv_errno, const char *msg, va_list ap)
|
||||
{
|
||||
/* Partially emulate line buffered output so that:
|
||||
* printf '%d\n' 1 a 2
|
||||
* and
|
||||
* printf '%d %d %d\n' 1 a 2
|
||||
* both generate sensible text when stdout and stderr are merged.
|
||||
*/
|
||||
if (output.nextc != output.buf && output.nextc[-1] == '\n')
|
||||
flushout(&output);
|
||||
if (commandname)
|
||||
outfmt(&errout, "%s: ", commandname);
|
||||
if (msg != NULL) {
|
||||
doformat(&errout, msg, ap);
|
||||
if (sv_errno >= 0)
|
||||
outfmt(&errout, ": ");
|
||||
}
|
||||
if (sv_errno >= 0)
|
||||
outfmt(&errout, "%s", strerror(sv_errno));
|
||||
out2c('\n');
|
||||
flushout(&errout);
|
||||
}
|
||||
|
||||
/*
|
||||
* Exverror is called to raise the error exception. If the second argument
|
||||
* is not NULL then error prints an error message using printf style
|
||||
* formatting. It then raises the error exception.
|
||||
*/
|
||||
static void
|
||||
exverror(int cond, const char *msg, va_list ap)
|
||||
{
|
||||
CLEAR_PENDING_INT;
|
||||
INTOFF;
|
||||
|
||||
#ifdef DEBUG
|
||||
if (msg) {
|
||||
TRACE(("exverror(%d, \"", cond));
|
||||
TRACEV((msg, ap));
|
||||
TRACE(("\") pid=%d\n", getpid()));
|
||||
} else
|
||||
TRACE(("exverror(%d, NULL) pid=%d\n", cond, getpid()));
|
||||
#endif
|
||||
if (msg)
|
||||
exvwarning(-1, msg, ap);
|
||||
|
||||
flushall();
|
||||
exraise(cond);
|
||||
/* NOTREACHED */
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
error(const char *msg, ...)
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, msg);
|
||||
exverror(EXERROR, msg, ap);
|
||||
/* NOTREACHED */
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
exerror(int cond, const char *msg, ...)
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, msg);
|
||||
exverror(cond, msg, ap);
|
||||
/* NOTREACHED */
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
/*
|
||||
* error/warning routines for external builtins
|
||||
*/
|
||||
|
||||
void
|
||||
sh_exit(int rval)
|
||||
{
|
||||
exerrno = rval & 255;
|
||||
exraise(EXEXEC);
|
||||
}
|
||||
|
||||
void
|
||||
sh_err(int status, const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, fmt);
|
||||
exvwarning(errno, fmt, ap);
|
||||
va_end(ap);
|
||||
sh_exit(status);
|
||||
}
|
||||
|
||||
void
|
||||
sh_verr(int status, const char *fmt, va_list ap)
|
||||
{
|
||||
exvwarning(errno, fmt, ap);
|
||||
sh_exit(status);
|
||||
}
|
||||
|
||||
void
|
||||
sh_errx(int status, const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, fmt);
|
||||
exvwarning(-1, fmt, ap);
|
||||
va_end(ap);
|
||||
sh_exit(status);
|
||||
}
|
||||
|
||||
void
|
||||
sh_verrx(int status, const char *fmt, va_list ap)
|
||||
{
|
||||
exvwarning(-1, fmt, ap);
|
||||
sh_exit(status);
|
||||
}
|
||||
|
||||
void
|
||||
sh_warn(const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, fmt);
|
||||
exvwarning(errno, fmt, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
void
|
||||
sh_vwarn(const char *fmt, va_list ap)
|
||||
{
|
||||
exvwarning(errno, fmt, ap);
|
||||
}
|
||||
|
||||
void
|
||||
sh_warnx(const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, fmt);
|
||||
exvwarning(-1, fmt, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
void
|
||||
sh_vwarnx(const char *fmt, va_list ap)
|
||||
{
|
||||
exvwarning(-1, fmt, ap);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Table of error messages.
|
||||
*/
|
||||
|
||||
struct errname {
|
||||
short errcode; /* error number */
|
||||
short action; /* operation which encountered the error */
|
||||
const char *msg; /* text describing the error */
|
||||
};
|
||||
|
||||
|
||||
#define ALL (E_OPEN|E_CREAT|E_EXEC)
|
||||
|
||||
STATIC const struct errname errormsg[] = {
|
||||
{ EINTR, ALL, "interrupted" },
|
||||
{ EACCES, ALL, "permission denied" },
|
||||
{ EIO, ALL, "I/O error" },
|
||||
{ EEXIST, ALL, "file exists" },
|
||||
{ ENOENT, E_OPEN, "no such file" },
|
||||
{ ENOENT, E_CREAT,"directory nonexistent" },
|
||||
{ ENOENT, E_EXEC, "not found" },
|
||||
{ ENOTDIR, E_OPEN, "no such file" },
|
||||
{ ENOTDIR, E_CREAT,"directory nonexistent" },
|
||||
{ ENOTDIR, E_EXEC, "not found" },
|
||||
{ EISDIR, ALL, "is a directory" },
|
||||
#ifdef EMFILE
|
||||
{ EMFILE, ALL, "too many open files" },
|
||||
#endif
|
||||
{ ENFILE, ALL, "file table overflow" },
|
||||
{ ENOSPC, ALL, "file system full" },
|
||||
#ifdef EDQUOT
|
||||
{ EDQUOT, ALL, "disk quota exceeded" },
|
||||
#endif
|
||||
#ifdef ENOSR
|
||||
{ ENOSR, ALL, "no streams resources" },
|
||||
#endif
|
||||
{ ENXIO, ALL, "no such device or address" },
|
||||
{ EROFS, ALL, "read-only file system" },
|
||||
{ ETXTBSY, ALL, "text busy" },
|
||||
#ifdef EAGAIN
|
||||
{ EAGAIN, E_EXEC, "not enough memory" },
|
||||
#endif
|
||||
{ ENOMEM, ALL, "not enough memory" },
|
||||
#ifdef ENOLINK
|
||||
{ ENOLINK, ALL, "remote access failed" },
|
||||
#endif
|
||||
#ifdef EMULTIHOP
|
||||
{ EMULTIHOP, ALL, "remote access failed" },
|
||||
#endif
|
||||
#ifdef ECOMM
|
||||
{ ECOMM, ALL, "remote access failed" },
|
||||
#endif
|
||||
#ifdef ESTALE
|
||||
{ ESTALE, ALL, "remote access failed" },
|
||||
#endif
|
||||
#ifdef ETIMEDOUT
|
||||
{ ETIMEDOUT, ALL, "remote access failed" },
|
||||
#endif
|
||||
#ifdef ELOOP
|
||||
{ ELOOP, ALL, "symbolic link loop" },
|
||||
#endif
|
||||
{ E2BIG, E_EXEC, "argument list too long" },
|
||||
#ifdef ELIBACC
|
||||
{ ELIBACC, E_EXEC, "shared library missing" },
|
||||
#endif
|
||||
{ 0, 0, NULL },
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* Return a string describing an error. The returned string may be a
|
||||
* pointer to a static buffer that will be overwritten on the next call.
|
||||
* Action describes the operation that got the error.
|
||||
*/
|
||||
|
||||
const char *
|
||||
errmsg(int e, int action)
|
||||
{
|
||||
struct errname const *ep;
|
||||
static char buf[12];
|
||||
|
||||
for (ep = errormsg ; ep->errcode ; ep++) {
|
||||
if (ep->errcode == e && (ep->action & action) != 0)
|
||||
return ep->msg;
|
||||
}
|
||||
fmtstr(buf, sizeof buf, "error %d", e);
|
||||
return buf;
|
||||
}
|
||||
117
sh/error.h
117
sh/error.h
|
|
@ -1,117 +0,0 @@
|
|||
/* $NetBSD: error.h,v 1.16 2003/08/07 09:05:30 agc Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1991, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to Berkeley by
|
||||
* Kenneth Almquist.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)error.h 8.2 (Berkeley) 5/4/95
|
||||
*/
|
||||
|
||||
#include <stdarg.h>
|
||||
|
||||
/*
|
||||
* Types of operations (passed to the errmsg routine).
|
||||
*/
|
||||
|
||||
#define E_OPEN 01 /* opening a file */
|
||||
#define E_CREAT 02 /* creating a file */
|
||||
#define E_EXEC 04 /* executing a program */
|
||||
|
||||
|
||||
/*
|
||||
* We enclose jmp_buf in a structure so that we can declare pointers to
|
||||
* jump locations. The global variable handler contains the location to
|
||||
* jump to when an exception occurs, and the global variable exception
|
||||
* contains a code identifying the exeception. To implement nested
|
||||
* exception handlers, the user should save the value of handler on entry
|
||||
* to an inner scope, set handler to point to a jmploc structure for the
|
||||
* inner scope, and restore handler on exit from the scope.
|
||||
*/
|
||||
|
||||
#include <setjmp.h>
|
||||
|
||||
struct jmploc {
|
||||
jmp_buf loc;
|
||||
};
|
||||
|
||||
extern struct jmploc *handler;
|
||||
extern int exception;
|
||||
extern int exerrno; /* error for EXEXEC */
|
||||
|
||||
/* exceptions */
|
||||
#define EXINT 0 /* SIGINT received */
|
||||
#define EXERROR 1 /* a generic error */
|
||||
#define EXSHELLPROC 2 /* execute a shell procedure */
|
||||
#define EXEXEC 3 /* command execution failed */
|
||||
|
||||
|
||||
/*
|
||||
* These macros allow the user to suspend the handling of interrupt signals
|
||||
* over a period of time. This is similar to SIGHOLD to or sigblock, but
|
||||
* much more efficient and portable. (But hacking the kernel is so much
|
||||
* more fun than worrying about efficiency and portability. :-))
|
||||
*/
|
||||
|
||||
extern volatile int suppressint;
|
||||
extern volatile int intpending;
|
||||
|
||||
#define INTOFF suppressint++
|
||||
#define INTON { if (--suppressint == 0 && intpending) onint(); }
|
||||
#define FORCEINTON {suppressint = 0; if (intpending) onint();}
|
||||
#define CLEAR_PENDING_INT intpending = 0
|
||||
#define int_pending() intpending
|
||||
|
||||
void exraise(int) __attribute__((__noreturn__));
|
||||
void onint(void);
|
||||
void error(const char *, ...) __attribute__((__noreturn__));
|
||||
void exerror(int, const char *, ...) __attribute__((__noreturn__));
|
||||
const char *errmsg(int, int);
|
||||
|
||||
void sh_err(int, const char *, ...) __attribute__((__noreturn__));
|
||||
void sh_verr(int, const char *, va_list) __attribute__((__noreturn__));
|
||||
void sh_errx(int, const char *, ...) __attribute__((__noreturn__));
|
||||
void sh_verrx(int, const char *, va_list) __attribute__((__noreturn__));
|
||||
void sh_warn(const char *, ...);
|
||||
void sh_vwarn(const char *, va_list);
|
||||
void sh_warnx(const char *, ...);
|
||||
void sh_vwarnx(const char *, va_list);
|
||||
|
||||
void sh_exit(int) __attribute__((__noreturn__));
|
||||
|
||||
|
||||
/*
|
||||
* BSD setjmp saves the signal mask, which violates ANSI C and takes time,
|
||||
* so we use _setjmp instead.
|
||||
*/
|
||||
|
||||
#if defined(BSD) && !defined(__SVR4) && !defined(__linux__)
|
||||
#define setjmp(jmploc) _setjmp(jmploc)
|
||||
#define longjmp(jmploc, val) _longjmp(jmploc, val)
|
||||
#endif
|
||||
64
sh/eval.h
64
sh/eval.h
|
|
@ -1,64 +0,0 @@
|
|||
/* $NetBSD: eval.h,v 1.14 2003/08/07 09:05:31 agc Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1991, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to Berkeley by
|
||||
* Kenneth Almquist.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)eval.h 8.2 (Berkeley) 5/4/95
|
||||
*/
|
||||
|
||||
extern char *commandname; /* currently executing command */
|
||||
extern int exitstatus; /* exit status of last command */
|
||||
extern int back_exitstatus; /* exit status of backquoted command */
|
||||
extern struct strlist *cmdenviron; /* environment for builtin command */
|
||||
|
||||
|
||||
struct backcmd { /* result of evalbackcmd */
|
||||
int fd; /* file descriptor to read from */
|
||||
char *buf; /* buffer */
|
||||
int nleft; /* number of chars in buffer */
|
||||
struct job *jp; /* job structure for command */
|
||||
};
|
||||
|
||||
void evalstring(char *, int);
|
||||
union node; /* BLETCH for ansi C */
|
||||
void evaltree(union node *, int);
|
||||
void evalbackcmd(union node *, struct backcmd *);
|
||||
|
||||
/* in_function returns nonzero if we are currently evaluating a function */
|
||||
#define in_function() funcnest
|
||||
extern int funcnest;
|
||||
extern int evalskip;
|
||||
|
||||
/* reasons for skipping commands (see comment on breakcmd routine) */
|
||||
#define SKIPBREAK 1
|
||||
#define SKIPCONT 2
|
||||
#define SKIPFUNC 3
|
||||
#define SKIPFILE 4
|
||||
79
sh/exec.h
79
sh/exec.h
|
|
@ -1,79 +0,0 @@
|
|||
/* $NetBSD: exec.h,v 1.21 2003/08/07 09:05:31 agc Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1991, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to Berkeley by
|
||||
* Kenneth Almquist.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)exec.h 8.3 (Berkeley) 6/8/95
|
||||
*/
|
||||
|
||||
/* values of cmdtype */
|
||||
#define CMDUNKNOWN -1 /* no entry in table for command */
|
||||
#define CMDNORMAL 0 /* command is an executable program */
|
||||
#define CMDFUNCTION 1 /* command is a shell function */
|
||||
#define CMDBUILTIN 2 /* command is a shell builtin */
|
||||
#define CMDSPLBLTIN 3 /* command is a special shell builtin */
|
||||
|
||||
|
||||
struct cmdentry {
|
||||
int cmdtype;
|
||||
union param {
|
||||
int index;
|
||||
int (*bltin)(int, char**);
|
||||
union node *func;
|
||||
} u;
|
||||
};
|
||||
|
||||
|
||||
/* action to find_command() */
|
||||
#define DO_ERR 0x01 /* prints errors */
|
||||
#define DO_ABS 0x02 /* checks absolute paths */
|
||||
#define DO_NOFUNC 0x04 /* don't return shell functions, for command */
|
||||
#define DO_ALTPATH 0x08 /* using alternate path */
|
||||
#define DO_ALTBLTIN 0x20 /* %builtin in alt. path */
|
||||
|
||||
extern const char *pathopt; /* set by padvance */
|
||||
|
||||
void shellexec(char **, char **, const char *, int, int)
|
||||
__attribute__((__noreturn__));
|
||||
char *padvance(const char **, const char *);
|
||||
int hashcmd(int, char **);
|
||||
void find_command(char *, struct cmdentry *, int, const char *);
|
||||
int (*find_builtin(char *))(int, char **);
|
||||
int (*find_splbltin(char *))(int, char **);
|
||||
void hashcd(void);
|
||||
void changepath(const char *);
|
||||
void deletefuncs(void);
|
||||
void getcmdentry(char *, struct cmdentry *);
|
||||
void addcmdentry(char *, struct cmdentry *);
|
||||
void defun(char *, union node *);
|
||||
int unsetfunc(char *);
|
||||
int typecmd(int, char **);
|
||||
void hash_special_builtins(void);
|
||||
1559
sh/expand.c
1559
sh/expand.c
File diff suppressed because it is too large
Load diff
72
sh/expand.h
72
sh/expand.h
|
|
@ -1,72 +0,0 @@
|
|||
/* $NetBSD: expand.h,v 1.16 2004/07/13 15:05:59 seb Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1991, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to Berkeley by
|
||||
* Kenneth Almquist.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)expand.h 8.2 (Berkeley) 5/4/95
|
||||
*/
|
||||
|
||||
struct strlist {
|
||||
struct strlist *next;
|
||||
char *text;
|
||||
};
|
||||
|
||||
|
||||
struct arglist {
|
||||
struct strlist *list;
|
||||
struct strlist **lastp;
|
||||
};
|
||||
|
||||
/*
|
||||
* expandarg() flags
|
||||
*/
|
||||
#define EXP_FULL 0x1 /* perform word splitting & file globbing */
|
||||
#define EXP_TILDE 0x2 /* do normal tilde expansion */
|
||||
#define EXP_VARTILDE 0x4 /* expand tildes in an assignment */
|
||||
#define EXP_REDIR 0x8 /* file glob for a redirection (1 match only) */
|
||||
#define EXP_CASE 0x10 /* keeps quotes around for CASE pattern */
|
||||
#define EXP_IFS_SPLIT 0x20 /* need to record arguments for ifs breakup */
|
||||
|
||||
|
||||
union node;
|
||||
void expandhere(union node *, int);
|
||||
void expandarg(union node *, struct arglist *, int);
|
||||
void expari(int);
|
||||
int patmatch(char *, char *, int);
|
||||
void rmescapes(char *);
|
||||
int casematch(union node *, char *);
|
||||
int wordexpcmd(int, char **);
|
||||
|
||||
/* From arith.y */
|
||||
int arith(const char *);
|
||||
int expcmd(int , char **);
|
||||
void arith_lex_reset(void);
|
||||
int yylex(void);
|
||||
50
sh/funcs/cmv
50
sh/funcs/cmv
|
|
@ -1,50 +0,0 @@
|
|||
# $NetBSD: cmv,v 1.7 1995/05/11 21:31:05 christos Exp $
|
||||
# Copyright (c) 1991, 1993
|
||||
# The Regents of the University of California. All rights reserved.
|
||||
#
|
||||
# This code is derived from software contributed to Berkeley by
|
||||
# Kenneth Almquist.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions
|
||||
# are met:
|
||||
# 1. Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# 2. Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in the
|
||||
# documentation and/or other materials provided with the distribution.
|
||||
# 3. All advertising materials mentioning features or use of this software
|
||||
# must display the following acknowledgement:
|
||||
# This product includes software developed by the University of
|
||||
# California, Berkeley and its contributors.
|
||||
# 4. Neither the name of the University nor the names of its contributors
|
||||
# may be used to endorse or promote products derived from this software
|
||||
# without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
# ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
# SUCH DAMAGE.
|
||||
#
|
||||
# @(#)cmv 8.2 (Berkeley) 5/4/95
|
||||
|
||||
# Conditional move--don't replace an existing file.
|
||||
|
||||
cmv() {
|
||||
if test $# != 2
|
||||
then echo "cmv: arg count"
|
||||
return 2
|
||||
fi
|
||||
if test -f "$2" -o -w "$2"
|
||||
then echo "$2 exists"
|
||||
return 2
|
||||
fi
|
||||
/bin/mv "$1" "$2"
|
||||
}
|
||||
|
|
@ -1,74 +0,0 @@
|
|||
# $NetBSD: dirs,v 1.7 1995/05/11 21:31:08 christos Exp $
|
||||
# Copyright (c) 1991, 1993
|
||||
# The Regents of the University of California. All rights reserved.
|
||||
#
|
||||
# This code is derived from software contributed to Berkeley by
|
||||
# Kenneth Almquist.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions
|
||||
# are met:
|
||||
# 1. Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# 2. Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in the
|
||||
# documentation and/or other materials provided with the distribution.
|
||||
# 3. All advertising materials mentioning features or use of this software
|
||||
# must display the following acknowledgement:
|
||||
# This product includes software developed by the University of
|
||||
# California, Berkeley and its contributors.
|
||||
# 4. Neither the name of the University nor the names of its contributors
|
||||
# may be used to endorse or promote products derived from this software
|
||||
# without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
# ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
# SUCH DAMAGE.
|
||||
#
|
||||
# @(#)dirs 8.2 (Berkeley) 5/4/95
|
||||
|
||||
# pushd, popd, and dirs --- written by Chris Bertin
|
||||
# Pixel Computer Inc. ...!wjh12!pixel!pixutl!chris
|
||||
# as modified by Patrick Elam of GTRI and Kenneth Almquist at UW
|
||||
|
||||
pushd () {
|
||||
SAVE=`pwd`
|
||||
if [ "$1" = "" ]
|
||||
then if [ "$DSTACK" = "" ]
|
||||
then echo "pushd: directory stack empty."
|
||||
return 1
|
||||
fi
|
||||
set $DSTACK
|
||||
cd $1 || return
|
||||
shift 1
|
||||
DSTACK="$*"
|
||||
else cd $1 > /dev/null || return
|
||||
fi
|
||||
DSTACK="$SAVE $DSTACK"
|
||||
dirs
|
||||
}
|
||||
|
||||
popd () {
|
||||
if [ "$DSTACK" = "" ]
|
||||
then echo "popd: directory stack empty."
|
||||
return 1
|
||||
fi
|
||||
set $DSTACK
|
||||
cd $1
|
||||
shift
|
||||
DSTACK=$*
|
||||
dirs
|
||||
}
|
||||
|
||||
dirs () {
|
||||
echo "`pwd` $DSTACK"
|
||||
return 0
|
||||
}
|
||||
|
|
@ -1,50 +0,0 @@
|
|||
# $NetBSD: kill,v 1.7 1995/05/11 21:31:10 christos Exp $
|
||||
# Copyright (c) 1991, 1993
|
||||
# The Regents of the University of California. All rights reserved.
|
||||
#
|
||||
# This code is derived from software contributed to Berkeley by
|
||||
# Kenneth Almquist.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions
|
||||
# are met:
|
||||
# 1. Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# 2. Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in the
|
||||
# documentation and/or other materials provided with the distribution.
|
||||
# 3. All advertising materials mentioning features or use of this software
|
||||
# must display the following acknowledgement:
|
||||
# This product includes software developed by the University of
|
||||
# California, Berkeley and its contributors.
|
||||
# 4. Neither the name of the University nor the names of its contributors
|
||||
# may be used to endorse or promote products derived from this software
|
||||
# without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
# ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
# SUCH DAMAGE.
|
||||
#
|
||||
# @(#)kill 8.2 (Berkeley) 5/4/95
|
||||
|
||||
# Convert job names to process ids and then run /bin/kill.
|
||||
|
||||
kill() {
|
||||
local args x
|
||||
args=
|
||||
for x in "$@"
|
||||
do case $x in
|
||||
%*) x=`jobid "$x"` ;;
|
||||
esac
|
||||
args="$args $x"
|
||||
done
|
||||
/bin/kill $args
|
||||
}
|
||||
|
|
@ -1,39 +0,0 @@
|
|||
# $NetBSD: login,v 1.7 1995/05/11 21:31:11 christos Exp $
|
||||
# Copyright (c) 1991, 1993
|
||||
# The Regents of the University of California. All rights reserved.
|
||||
#
|
||||
# This code is derived from software contributed to Berkeley by
|
||||
# Kenneth Almquist.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions
|
||||
# are met:
|
||||
# 1. Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# 2. Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in the
|
||||
# documentation and/or other materials provided with the distribution.
|
||||
# 3. All advertising materials mentioning features or use of this software
|
||||
# must display the following acknowledgement:
|
||||
# This product includes software developed by the University of
|
||||
# California, Berkeley and its contributors.
|
||||
# 4. Neither the name of the University nor the names of its contributors
|
||||
# may be used to endorse or promote products derived from this software
|
||||
# without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
# ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
# SUCH DAMAGE.
|
||||
#
|
||||
# @(#)login 8.2 (Berkeley) 5/4/95
|
||||
|
||||
# replaces the login builtin in the BSD shell
|
||||
login () exec login "$@"
|
||||
|
|
@ -1,38 +0,0 @@
|
|||
# $NetBSD: newgrp,v 1.7 1995/05/11 21:31:12 christos Exp $
|
||||
# Copyright (c) 1991, 1993
|
||||
# The Regents of the University of California. All rights reserved.
|
||||
#
|
||||
# This code is derived from software contributed to Berkeley by
|
||||
# Kenneth Almquist.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions
|
||||
# are met:
|
||||
# 1. Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# 2. Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in the
|
||||
# documentation and/or other materials provided with the distribution.
|
||||
# 3. All advertising materials mentioning features or use of this software
|
||||
# must display the following acknowledgement:
|
||||
# This product includes software developed by the University of
|
||||
# California, Berkeley and its contributors.
|
||||
# 4. Neither the name of the University nor the names of its contributors
|
||||
# may be used to endorse or promote products derived from this software
|
||||
# without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
# ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
# SUCH DAMAGE.
|
||||
#
|
||||
# @(#)newgrp 8.2 (Berkeley) 5/4/95
|
||||
|
||||
newgrp() exec newgrp "$@"
|
||||
|
|
@ -1,74 +0,0 @@
|
|||
# $NetBSD: popd,v 1.7 1995/05/11 21:31:13 christos Exp $
|
||||
# Copyright (c) 1991, 1993
|
||||
# The Regents of the University of California. All rights reserved.
|
||||
#
|
||||
# This code is derived from software contributed to Berkeley by
|
||||
# Kenneth Almquist.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions
|
||||
# are met:
|
||||
# 1. Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# 2. Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in the
|
||||
# documentation and/or other materials provided with the distribution.
|
||||
# 3. All advertising materials mentioning features or use of this software
|
||||
# must display the following acknowledgement:
|
||||
# This product includes software developed by the University of
|
||||
# California, Berkeley and its contributors.
|
||||
# 4. Neither the name of the University nor the names of its contributors
|
||||
# may be used to endorse or promote products derived from this software
|
||||
# without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
# ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
# SUCH DAMAGE.
|
||||
#
|
||||
# @(#)popd 8.2 (Berkeley) 5/4/95
|
||||
|
||||
# pushd, popd, and dirs --- written by Chris Bertin
|
||||
# Pixel Computer Inc. ...!wjh12!pixel!pixutl!chris
|
||||
# as modified by Patrick Elam of GTRI and Kenneth Almquist at UW
|
||||
|
||||
pushd () {
|
||||
SAVE=`pwd`
|
||||
if [ "$1" = "" ]
|
||||
then if [ "$DSTACK" = "" ]
|
||||
then echo "pushd: directory stack empty."
|
||||
return 1
|
||||
fi
|
||||
set $DSTACK
|
||||
cd $1 || return
|
||||
shift 1
|
||||
DSTACK="$*"
|
||||
else cd $1 > /dev/null || return
|
||||
fi
|
||||
DSTACK="$SAVE $DSTACK"
|
||||
dirs
|
||||
}
|
||||
|
||||
popd () {
|
||||
if [ "$DSTACK" = "" ]
|
||||
then echo "popd: directory stack empty."
|
||||
return 1
|
||||
fi
|
||||
set $DSTACK
|
||||
cd $1
|
||||
shift
|
||||
DSTACK=$*
|
||||
dirs
|
||||
}
|
||||
|
||||
dirs () {
|
||||
echo "`pwd` $DSTACK"
|
||||
return 0
|
||||
}
|
||||
|
|
@ -1,74 +0,0 @@
|
|||
# $NetBSD: pushd,v 1.7 1995/05/11 21:31:15 christos Exp $
|
||||
# Copyright (c) 1991, 1993
|
||||
# The Regents of the University of California. All rights reserved.
|
||||
#
|
||||
# This code is derived from software contributed to Berkeley by
|
||||
# Kenneth Almquist.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions
|
||||
# are met:
|
||||
# 1. Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# 2. Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in the
|
||||
# documentation and/or other materials provided with the distribution.
|
||||
# 3. All advertising materials mentioning features or use of this software
|
||||
# must display the following acknowledgement:
|
||||
# This product includes software developed by the University of
|
||||
# California, Berkeley and its contributors.
|
||||
# 4. Neither the name of the University nor the names of its contributors
|
||||
# may be used to endorse or promote products derived from this software
|
||||
# without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
# ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
# SUCH DAMAGE.
|
||||
#
|
||||
# @(#)pushd 8.2 (Berkeley) 5/4/95
|
||||
|
||||
# pushd, popd, and dirs --- written by Chris Bertin
|
||||
# Pixel Computer Inc. ...!wjh12!pixel!pixutl!chris
|
||||
# as modified by Patrick Elam of GTRI and Kenneth Almquist at UW
|
||||
|
||||
pushd () {
|
||||
SAVE=`pwd`
|
||||
if [ "$1" = "" ]
|
||||
then if [ "$DSTACK" = "" ]
|
||||
then echo "pushd: directory stack empty."
|
||||
return 1
|
||||
fi
|
||||
set $DSTACK
|
||||
cd $1 || return
|
||||
shift 1
|
||||
DSTACK="$*"
|
||||
else cd $1 > /dev/null || return
|
||||
fi
|
||||
DSTACK="$SAVE $DSTACK"
|
||||
dirs
|
||||
}
|
||||
|
||||
popd () {
|
||||
if [ "$DSTACK" = "" ]
|
||||
then echo "popd: directory stack empty."
|
||||
return 1
|
||||
fi
|
||||
set $DSTACK
|
||||
cd $1
|
||||
shift
|
||||
DSTACK=$*
|
||||
dirs
|
||||
}
|
||||
|
||||
dirs () {
|
||||
echo "`pwd` $DSTACK"
|
||||
return 0
|
||||
}
|
||||
|
|
@ -1,42 +0,0 @@
|
|||
# $NetBSD: suspend,v 1.7 1995/05/11 21:31:17 christos Exp $
|
||||
# Copyright (c) 1991, 1993
|
||||
# The Regents of the University of California. All rights reserved.
|
||||
#
|
||||
# This code is derived from software contributed to Berkeley by
|
||||
# Kenneth Almquist.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions
|
||||
# are met:
|
||||
# 1. Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# 2. Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in the
|
||||
# documentation and/or other materials provided with the distribution.
|
||||
# 3. All advertising materials mentioning features or use of this software
|
||||
# must display the following acknowledgement:
|
||||
# This product includes software developed by the University of
|
||||
# California, Berkeley and its contributors.
|
||||
# 4. Neither the name of the University nor the names of its contributors
|
||||
# may be used to endorse or promote products derived from this software
|
||||
# without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
# ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
# SUCH DAMAGE.
|
||||
#
|
||||
# @(#)suspend 8.2 (Berkeley) 5/4/95
|
||||
|
||||
suspend() {
|
||||
local -
|
||||
set +j
|
||||
kill -TSTP 0
|
||||
}
|
||||
540
sh/histedit.c
540
sh/histedit.c
|
|
@ -1,540 +0,0 @@
|
|||
/* $NetBSD: histedit.c,v 1.34 2003/10/27 06:19:29 lukem Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to Berkeley by
|
||||
* Kenneth Almquist.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
#ifndef lint
|
||||
#if 0
|
||||
static char sccsid[] = "@(#)histedit.c 8.2 (Berkeley) 5/4/95";
|
||||
#else
|
||||
__RCSID("$NetBSD: histedit.c,v 1.34 2003/10/27 06:19:29 lukem Exp $");
|
||||
#endif
|
||||
#endif /* not lint */
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <paths.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
/*
|
||||
* Editline and history functions (and glue).
|
||||
*/
|
||||
#include "shell.h"
|
||||
#include "parser.h"
|
||||
#include "var.h"
|
||||
#include "options.h"
|
||||
#include "main.h"
|
||||
#include "output.h"
|
||||
#include "mystring.h"
|
||||
#include "myhistedit.h"
|
||||
#include "error.h"
|
||||
#ifndef SMALL
|
||||
#include "eval.h"
|
||||
#include "memalloc.h"
|
||||
|
||||
#define MAXHISTLOOPS 4 /* max recursions through fc */
|
||||
#define DEFEDITOR "ed" /* default editor *should* be $EDITOR */
|
||||
|
||||
History *hist; /* history cookie */
|
||||
EditLine *el; /* editline cookie */
|
||||
int displayhist;
|
||||
static FILE *el_in, *el_out;
|
||||
|
||||
STATIC const char *fc_replace(const char *, char *, char *);
|
||||
|
||||
#ifdef DEBUG
|
||||
extern FILE *tracefile;
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Set history and editing status. Called whenever the status may
|
||||
* have changed (figures out what to do).
|
||||
*/
|
||||
void
|
||||
histedit(void)
|
||||
{
|
||||
FILE *el_err;
|
||||
|
||||
#define editing (Eflag || Vflag)
|
||||
|
||||
if (iflag) {
|
||||
if (!hist) {
|
||||
/*
|
||||
* turn history on
|
||||
*/
|
||||
INTOFF;
|
||||
hist = history_init();
|
||||
INTON;
|
||||
|
||||
if (hist != NULL)
|
||||
sethistsize(histsizeval());
|
||||
else
|
||||
out2str("sh: can't initialize history\n");
|
||||
}
|
||||
if (editing && !el && isatty(0)) { /* && isatty(2) ??? */
|
||||
/*
|
||||
* turn editing on
|
||||
*/
|
||||
char *term, *shname;
|
||||
|
||||
INTOFF;
|
||||
if (el_in == NULL)
|
||||
el_in = fdopen(0, "r");
|
||||
if (el_out == NULL)
|
||||
el_out = fdopen(2, "w");
|
||||
if (el_in == NULL || el_out == NULL)
|
||||
goto bad;
|
||||
el_err = el_out;
|
||||
#if DEBUG
|
||||
if (tracefile)
|
||||
el_err = tracefile;
|
||||
#endif
|
||||
term = lookupvar("TERM");
|
||||
if (term)
|
||||
setenv("TERM", term, 1);
|
||||
else
|
||||
unsetenv("TERM");
|
||||
shname = arg0;
|
||||
if (shname[0] == '-')
|
||||
shname++;
|
||||
el = el_init(shname, el_in, el_out, el_err);
|
||||
if (el != NULL) {
|
||||
if (hist)
|
||||
el_set(el, EL_HIST, history, hist);
|
||||
el_set(el, EL_PROMPT, getprompt);
|
||||
el_set(el, EL_SIGNAL, 1);
|
||||
} else {
|
||||
bad:
|
||||
out2str("sh: can't initialize editing\n");
|
||||
}
|
||||
INTON;
|
||||
} else if (!editing && el) {
|
||||
INTOFF;
|
||||
el_end(el);
|
||||
el = NULL;
|
||||
INTON;
|
||||
}
|
||||
if (el) {
|
||||
if (Vflag)
|
||||
el_set(el, EL_EDITOR, "vi");
|
||||
else if (Eflag)
|
||||
el_set(el, EL_EDITOR, "emacs");
|
||||
el_source(el, NULL);
|
||||
}
|
||||
} else {
|
||||
INTOFF;
|
||||
if (el) { /* no editing if not interactive */
|
||||
el_end(el);
|
||||
el = NULL;
|
||||
}
|
||||
if (hist) {
|
||||
history_end(hist);
|
||||
hist = NULL;
|
||||
}
|
||||
INTON;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
sethistsize(const char *hs)
|
||||
{
|
||||
int histsize;
|
||||
HistEvent he;
|
||||
|
||||
if (hist != NULL) {
|
||||
if (hs == NULL || *hs == '\0' ||
|
||||
(histsize = atoi(hs)) < 0)
|
||||
histsize = 100;
|
||||
history(hist, &he, H_SETSIZE, histsize);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
setterm(const char *term)
|
||||
{
|
||||
if (el != NULL && term != NULL)
|
||||
if (el_set(el, EL_TERMINAL, term) != 0) {
|
||||
outfmt(out2, "sh: Can't set terminal type %s\n", term);
|
||||
outfmt(out2, "sh: Using dumb terminal settings.\n");
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
inputrc(argc, argv)
|
||||
int argc;
|
||||
char **argv;
|
||||
{
|
||||
if (argc != 2) {
|
||||
out2str("usage: inputrc file\n");
|
||||
return 1;
|
||||
}
|
||||
if (el != NULL) {
|
||||
if (el_source(el, argv[1])) {
|
||||
out2str("inputrc: failed\n");
|
||||
return 1;
|
||||
} else
|
||||
return 0;
|
||||
} else {
|
||||
out2str("sh: inputrc ignored, not editing\n");
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* This command is provided since POSIX decided to standardize
|
||||
* the Korn shell fc command. Oh well...
|
||||
*/
|
||||
int
|
||||
histcmd(int argc, char **argv)
|
||||
{
|
||||
int ch;
|
||||
const char *editor = NULL;
|
||||
HistEvent he;
|
||||
int lflg = 0, nflg = 0, rflg = 0, sflg = 0;
|
||||
int i, retval;
|
||||
const char *firststr, *laststr;
|
||||
int first, last, direction;
|
||||
char *pat = NULL, *repl; /* ksh "fc old=new" crap */
|
||||
static int active = 0;
|
||||
struct jmploc jmploc;
|
||||
struct jmploc *volatile savehandler;
|
||||
char editfile[MAXPATHLEN + 1];
|
||||
FILE *efp;
|
||||
#ifdef __GNUC__
|
||||
/* Avoid longjmp clobbering */
|
||||
(void) &editor;
|
||||
(void) &lflg;
|
||||
(void) &nflg;
|
||||
(void) &rflg;
|
||||
(void) &sflg;
|
||||
(void) &firststr;
|
||||
(void) &laststr;
|
||||
(void) &pat;
|
||||
(void) &repl;
|
||||
(void) &efp;
|
||||
(void) &argc;
|
||||
(void) &argv;
|
||||
#endif
|
||||
|
||||
if (hist == NULL)
|
||||
error("history not active");
|
||||
|
||||
if (argc == 1)
|
||||
error("missing history argument");
|
||||
|
||||
optreset = 1; optind = 1; /* initialize getopt */
|
||||
while (not_fcnumber(argv[optind]) &&
|
||||
(ch = getopt(argc, argv, ":e:lnrs")) != -1)
|
||||
switch ((char)ch) {
|
||||
case 'e':
|
||||
editor = optionarg;
|
||||
break;
|
||||
case 'l':
|
||||
lflg = 1;
|
||||
break;
|
||||
case 'n':
|
||||
nflg = 1;
|
||||
break;
|
||||
case 'r':
|
||||
rflg = 1;
|
||||
break;
|
||||
case 's':
|
||||
sflg = 1;
|
||||
break;
|
||||
case ':':
|
||||
error("option -%c expects argument", optopt);
|
||||
/* NOTREACHED */
|
||||
case '?':
|
||||
default:
|
||||
error("unknown option: -%c", optopt);
|
||||
/* NOTREACHED */
|
||||
}
|
||||
argc -= optind, argv += optind;
|
||||
|
||||
/*
|
||||
* If executing...
|
||||
*/
|
||||
if (lflg == 0 || editor || sflg) {
|
||||
lflg = 0; /* ignore */
|
||||
editfile[0] = '\0';
|
||||
/*
|
||||
* Catch interrupts to reset active counter and
|
||||
* cleanup temp files.
|
||||
*/
|
||||
if (setjmp(jmploc.loc)) {
|
||||
active = 0;
|
||||
if (*editfile)
|
||||
unlink(editfile);
|
||||
handler = savehandler;
|
||||
longjmp(handler->loc, 1);
|
||||
}
|
||||
savehandler = handler;
|
||||
handler = &jmploc;
|
||||
if (++active > MAXHISTLOOPS) {
|
||||
active = 0;
|
||||
displayhist = 0;
|
||||
error("called recursively too many times");
|
||||
}
|
||||
/*
|
||||
* Set editor.
|
||||
*/
|
||||
if (sflg == 0) {
|
||||
if (editor == NULL &&
|
||||
(editor = bltinlookup("FCEDIT", 1)) == NULL &&
|
||||
(editor = bltinlookup("EDITOR", 1)) == NULL)
|
||||
editor = DEFEDITOR;
|
||||
if (editor[0] == '-' && editor[1] == '\0') {
|
||||
sflg = 1; /* no edit */
|
||||
editor = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* If executing, parse [old=new] now
|
||||
*/
|
||||
if (lflg == 0 && argc > 0 &&
|
||||
((repl = strchr(argv[0], '=')) != NULL)) {
|
||||
pat = argv[0];
|
||||
*repl++ = '\0';
|
||||
argc--, argv++;
|
||||
}
|
||||
/*
|
||||
* determine [first] and [last]
|
||||
*/
|
||||
switch (argc) {
|
||||
case 0:
|
||||
firststr = lflg ? "-16" : "-1";
|
||||
laststr = "-1";
|
||||
break;
|
||||
case 1:
|
||||
firststr = argv[0];
|
||||
laststr = lflg ? "-1" : argv[0];
|
||||
break;
|
||||
case 2:
|
||||
firststr = argv[0];
|
||||
laststr = argv[1];
|
||||
break;
|
||||
default:
|
||||
error("too many args");
|
||||
/* NOTREACHED */
|
||||
}
|
||||
/*
|
||||
* Turn into event numbers.
|
||||
*/
|
||||
first = str_to_event(firststr, 0);
|
||||
last = str_to_event(laststr, 1);
|
||||
|
||||
if (rflg) {
|
||||
i = last;
|
||||
last = first;
|
||||
first = i;
|
||||
}
|
||||
/*
|
||||
* XXX - this should not depend on the event numbers
|
||||
* always increasing. Add sequence numbers or offset
|
||||
* to the history element in next (diskbased) release.
|
||||
*/
|
||||
direction = first < last ? H_PREV : H_NEXT;
|
||||
|
||||
/*
|
||||
* If editing, grab a temp file.
|
||||
*/
|
||||
if (editor) {
|
||||
int fd;
|
||||
INTOFF; /* easier */
|
||||
snprintf(editfile, sizeof(editfile), "%s_shXXXXXX", _PATH_TMP);
|
||||
if ((fd = mkstemp(editfile)) < 0)
|
||||
error("can't create temporary file %s", editfile);
|
||||
if ((efp = fdopen(fd, "w")) == NULL) {
|
||||
close(fd);
|
||||
error("can't allocate stdio buffer for temp");
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Loop through selected history events. If listing or executing,
|
||||
* do it now. Otherwise, put into temp file and call the editor
|
||||
* after.
|
||||
*
|
||||
* The history interface needs rethinking, as the following
|
||||
* convolutions will demonstrate.
|
||||
*/
|
||||
history(hist, &he, H_FIRST);
|
||||
retval = history(hist, &he, H_NEXT_EVENT, first);
|
||||
for (;retval != -1; retval = history(hist, &he, direction)) {
|
||||
if (lflg) {
|
||||
if (!nflg)
|
||||
out1fmt("%5d ", he.num);
|
||||
out1str(he.str);
|
||||
} else {
|
||||
const char *s = pat ?
|
||||
fc_replace(he.str, pat, repl) : he.str;
|
||||
|
||||
if (sflg) {
|
||||
if (displayhist) {
|
||||
out2str(s);
|
||||
}
|
||||
|
||||
evalstring(strcpy(stalloc(strlen(s) + 1), s), 0);
|
||||
if (displayhist && hist) {
|
||||
/*
|
||||
* XXX what about recursive and
|
||||
* relative histnums.
|
||||
*/
|
||||
history(hist, &he, H_ENTER, s);
|
||||
}
|
||||
} else
|
||||
fputs(s, efp);
|
||||
}
|
||||
/*
|
||||
* At end? (if we were to lose last, we'd sure be
|
||||
* messed up).
|
||||
*/
|
||||
if (he.num == last)
|
||||
break;
|
||||
}
|
||||
if (editor) {
|
||||
char *editcmd;
|
||||
|
||||
fclose(efp);
|
||||
editcmd = stalloc(strlen(editor) + strlen(editfile) + 2);
|
||||
sprintf(editcmd, "%s %s", editor, editfile);
|
||||
evalstring(editcmd, 0); /* XXX - should use no JC command */
|
||||
INTON;
|
||||
readcmdfile(editfile); /* XXX - should read back - quick tst */
|
||||
unlink(editfile);
|
||||
}
|
||||
|
||||
if (lflg == 0 && active > 0)
|
||||
--active;
|
||||
if (displayhist)
|
||||
displayhist = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
STATIC const char *
|
||||
fc_replace(const char *s, char *p, char *r)
|
||||
{
|
||||
char *dest;
|
||||
int plen = strlen(p);
|
||||
|
||||
STARTSTACKSTR(dest);
|
||||
while (*s) {
|
||||
if (*s == *p && strncmp(s, p, plen) == 0) {
|
||||
while (*r)
|
||||
STPUTC(*r++, dest);
|
||||
s += plen;
|
||||
*p = '\0'; /* so no more matches */
|
||||
} else
|
||||
STPUTC(*s++, dest);
|
||||
}
|
||||
STACKSTRNUL(dest);
|
||||
dest = grabstackstr(dest);
|
||||
|
||||
return (dest);
|
||||
}
|
||||
|
||||
int
|
||||
not_fcnumber(char *s)
|
||||
{
|
||||
if (s == NULL)
|
||||
return 0;
|
||||
if (*s == '-')
|
||||
s++;
|
||||
return (!is_number(s));
|
||||
}
|
||||
|
||||
int
|
||||
str_to_event(const char *str, int last)
|
||||
{
|
||||
HistEvent he;
|
||||
const char *s = str;
|
||||
int relative = 0;
|
||||
int i, retval;
|
||||
|
||||
retval = history(hist, &he, H_FIRST);
|
||||
switch (*s) {
|
||||
case '-':
|
||||
relative = 1;
|
||||
/*FALLTHROUGH*/
|
||||
case '+':
|
||||
s++;
|
||||
}
|
||||
if (is_number(s)) {
|
||||
i = atoi(s);
|
||||
if (relative) {
|
||||
while (retval != -1 && i--) {
|
||||
retval = history(hist, &he, H_NEXT);
|
||||
}
|
||||
if (retval == -1)
|
||||
retval = history(hist, &he, H_LAST);
|
||||
} else {
|
||||
retval = history(hist, &he, H_NEXT_EVENT, i);
|
||||
if (retval == -1) {
|
||||
/*
|
||||
* the notion of first and last is
|
||||
* backwards to that of the history package
|
||||
*/
|
||||
retval = history(hist, &he,
|
||||
last ? H_FIRST : H_LAST);
|
||||
}
|
||||
}
|
||||
if (retval == -1)
|
||||
error("history number %s not found (internal error)",
|
||||
str);
|
||||
} else {
|
||||
/*
|
||||
* pattern
|
||||
*/
|
||||
retval = history(hist, &he, H_PREV_STR, str);
|
||||
if (retval == -1)
|
||||
error("history pattern not found: %s", str);
|
||||
}
|
||||
return (he.num);
|
||||
}
|
||||
#else
|
||||
int
|
||||
histcmd(int argc, char **argv)
|
||||
{
|
||||
error("not compiled with history support");
|
||||
/* NOTREACHED */
|
||||
}
|
||||
int
|
||||
inputrc(int argc, char **argv)
|
||||
{
|
||||
error("not compiled with history support");
|
||||
/* NOTREACHED */
|
||||
}
|
||||
#endif
|
||||
39
sh/init.h
39
sh/init.h
|
|
@ -1,39 +0,0 @@
|
|||
/* $NetBSD: init.h,v 1.10 2003/08/07 09:05:32 agc Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1991, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to Berkeley by
|
||||
* Kenneth Almquist.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)init.h 8.2 (Berkeley) 5/4/95
|
||||
*/
|
||||
|
||||
void init(void);
|
||||
void reset(void);
|
||||
void initshellproc(void);
|
||||
577
sh/input.c
577
sh/input.c
|
|
@ -1,577 +0,0 @@
|
|||
/* $NetBSD: input.c,v 1.39 2003/08/07 09:05:32 agc Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1991, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to Berkeley by
|
||||
* Kenneth Almquist.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
#ifndef lint
|
||||
#if 0
|
||||
static char sccsid[] = "@(#)input.c 8.3 (Berkeley) 6/9/95";
|
||||
#else
|
||||
__RCSID("$NetBSD: input.c,v 1.39 2003/08/07 09:05:32 agc Exp $");
|
||||
#endif
|
||||
#endif /* not lint */
|
||||
|
||||
#include <stdio.h> /* defines BUFSIZ */
|
||||
#include <fcntl.h>
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
/*
|
||||
* This file implements the input routines used by the parser.
|
||||
*/
|
||||
|
||||
#include "shell.h"
|
||||
#include "redir.h"
|
||||
#include "syntax.h"
|
||||
#include "input.h"
|
||||
#include "output.h"
|
||||
#include "options.h"
|
||||
#include "memalloc.h"
|
||||
#include "error.h"
|
||||
#include "alias.h"
|
||||
#include "parser.h"
|
||||
#include "myhistedit.h"
|
||||
|
||||
#ifdef WITH_LINENOISE
|
||||
#include "linenoise.h"
|
||||
#endif
|
||||
|
||||
#define EOF_NLEFT -99 /* value of parsenleft when EOF pushed back */
|
||||
|
||||
MKINIT
|
||||
struct strpush {
|
||||
struct strpush *prev; /* preceding string on stack */
|
||||
char *prevstring;
|
||||
int prevnleft;
|
||||
int prevlleft;
|
||||
struct alias *ap; /* if push was associated with an alias */
|
||||
};
|
||||
|
||||
/*
|
||||
* The parsefile structure pointed to by the global variable parsefile
|
||||
* contains information about the current file being read.
|
||||
*/
|
||||
|
||||
MKINIT
|
||||
struct parsefile {
|
||||
struct parsefile *prev; /* preceding file on stack */
|
||||
int linno; /* current line */
|
||||
int fd; /* file descriptor (or -1 if string) */
|
||||
int nleft; /* number of chars left in this line */
|
||||
int lleft; /* number of chars left in this buffer */
|
||||
char *nextc; /* next char in buffer */
|
||||
char *buf; /* input buffer */
|
||||
struct strpush *strpush; /* for pushing strings at this level */
|
||||
struct strpush basestrpush; /* so pushing one is fast */
|
||||
};
|
||||
|
||||
|
||||
int plinno = 1; /* input line number */
|
||||
int parsenleft; /* copy of parsefile->nleft */
|
||||
MKINIT int parselleft; /* copy of parsefile->lleft */
|
||||
char *parsenextc; /* copy of parsefile->nextc */
|
||||
MKINIT struct parsefile basepf; /* top level input file */
|
||||
MKINIT char basebuf[BUFSIZ]; /* buffer for top level input file */
|
||||
struct parsefile *parsefile = &basepf; /* current input file */
|
||||
int init_editline = 0; /* editline library initialized? */
|
||||
int whichprompt; /* 1 == PS1, 2 == PS2 */
|
||||
|
||||
#if WITH_HISTORY
|
||||
EditLine *el; /* cookie for editline package */
|
||||
#endif
|
||||
|
||||
STATIC void pushfile(void);
|
||||
static int preadfd(void);
|
||||
|
||||
#ifdef mkinit
|
||||
INCLUDE <stdio.h>
|
||||
INCLUDE "input.h"
|
||||
INCLUDE "error.h"
|
||||
|
||||
INIT {
|
||||
basepf.nextc = basepf.buf = basebuf;
|
||||
}
|
||||
|
||||
RESET {
|
||||
if (exception != EXSHELLPROC)
|
||||
parselleft = parsenleft = 0; /* clear input buffer */
|
||||
popallfiles();
|
||||
}
|
||||
|
||||
SHELLPROC {
|
||||
popallfiles();
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
* Read a line from the script.
|
||||
*/
|
||||
|
||||
char *
|
||||
pfgets(char *line, int len)
|
||||
{
|
||||
char *p = line;
|
||||
int nleft = len;
|
||||
int c;
|
||||
|
||||
while (--nleft > 0) {
|
||||
c = pgetc_macro();
|
||||
if (c == PEOF) {
|
||||
if (p == line)
|
||||
return NULL;
|
||||
break;
|
||||
}
|
||||
*p++ = c;
|
||||
if (c == '\n')
|
||||
break;
|
||||
}
|
||||
*p = '\0';
|
||||
return line;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Read a character from the script, returning PEOF on end of file.
|
||||
* Nul characters in the input are silently discarded.
|
||||
*/
|
||||
|
||||
int
|
||||
pgetc(void)
|
||||
{
|
||||
return pgetc_macro();
|
||||
}
|
||||
|
||||
int in_interactive_mode() {
|
||||
return parsefile != NULL && parsefile->fd == 0;
|
||||
}
|
||||
|
||||
static int
|
||||
preadfd(void)
|
||||
{
|
||||
int nr;
|
||||
char *buf = parsefile->buf;
|
||||
parsenextc = buf;
|
||||
|
||||
retry:
|
||||
#ifdef WITH_HISTORY
|
||||
if (parsefile->fd == 0 && el) {
|
||||
static const char *rl_cp;
|
||||
static int el_len;
|
||||
|
||||
if (rl_cp == NULL)
|
||||
rl_cp = el_gets(el, &el_len);
|
||||
if (rl_cp == NULL)
|
||||
nr = 0;
|
||||
else {
|
||||
nr = el_len;
|
||||
if (nr > BUFSIZ - 8)
|
||||
nr = BUFSIZ - 8;
|
||||
memcpy(buf, rl_cp, nr);
|
||||
if (nr != el_len) {
|
||||
el_len -= nr;
|
||||
rl_cp += nr;
|
||||
} else
|
||||
rl_cp = 0;
|
||||
}
|
||||
|
||||
} else
|
||||
#endif
|
||||
#ifdef WITH_LINENOISE
|
||||
if (parsefile->fd == 0) {
|
||||
static char *rl_start;
|
||||
static const char *rl_cp;
|
||||
static int el_len;
|
||||
|
||||
if (rl_cp == NULL) {
|
||||
rl_cp = rl_start = linenoise(getprompt(""));
|
||||
if (rl_cp != NULL) {
|
||||
el_len = strlen(rl_start);
|
||||
if (el_len != 0) {
|
||||
/* Add non-blank lines to history. */
|
||||
linenoiseHistoryAdd(rl_start);
|
||||
}
|
||||
out2str("\n");
|
||||
/* Client expects a newline at end of input, doesn't expect null */
|
||||
rl_start[el_len++] = '\n';
|
||||
}
|
||||
}
|
||||
if (rl_cp == NULL)
|
||||
nr = 0;
|
||||
else {
|
||||
nr = el_len;
|
||||
if (nr > BUFSIZ - 8)
|
||||
nr = BUFSIZ - 8;
|
||||
memcpy(buf, rl_cp, nr);
|
||||
if (nr != el_len) {
|
||||
el_len -= nr;
|
||||
rl_cp += nr;
|
||||
} else {
|
||||
rl_cp = 0;
|
||||
if (rl_start != NULL) {
|
||||
free(rl_start);
|
||||
rl_start = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else
|
||||
#endif
|
||||
nr = read(parsefile->fd, buf, BUFSIZ - 8);
|
||||
|
||||
|
||||
if (nr <= 0) {
|
||||
if (nr < 0) {
|
||||
if (errno == EINTR)
|
||||
goto retry;
|
||||
if (parsefile->fd == 0 && errno == EWOULDBLOCK) {
|
||||
int flags = fcntl(0, F_GETFL, 0);
|
||||
if (flags >= 0 && flags & O_NONBLOCK) {
|
||||
flags &=~ O_NONBLOCK;
|
||||
if (fcntl(0, F_SETFL, flags) >= 0) {
|
||||
out2str("sh: turning off NDELAY mode\n");
|
||||
goto retry;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
nr = -1;
|
||||
}
|
||||
return nr;
|
||||
}
|
||||
|
||||
/*
|
||||
* Refill the input buffer and return the next input character:
|
||||
*
|
||||
* 1) If a string was pushed back on the input, pop it;
|
||||
* 2) If an EOF was pushed back (parsenleft == EOF_NLEFT) or we are reading
|
||||
* from a string so we can't refill the buffer, return EOF.
|
||||
* 3) If the is more stuff in this buffer, use it else call read to fill it.
|
||||
* 4) Process input up to the next newline, deleting nul characters.
|
||||
*/
|
||||
|
||||
int
|
||||
preadbuffer(void)
|
||||
{
|
||||
char *p, *q;
|
||||
int more;
|
||||
int something;
|
||||
char savec;
|
||||
|
||||
if (parsefile->strpush) {
|
||||
popstring();
|
||||
if (--parsenleft >= 0)
|
||||
return (*parsenextc++);
|
||||
}
|
||||
if (parsenleft == EOF_NLEFT || parsefile->buf == NULL)
|
||||
return PEOF;
|
||||
flushout(&output);
|
||||
flushout(&errout);
|
||||
|
||||
again:
|
||||
if (parselleft <= 0) {
|
||||
if ((parselleft = preadfd()) == -1) {
|
||||
parselleft = parsenleft = EOF_NLEFT;
|
||||
return PEOF;
|
||||
}
|
||||
}
|
||||
|
||||
q = p = parsenextc;
|
||||
|
||||
/* delete nul characters */
|
||||
something = 0;
|
||||
for (more = 1; more;) {
|
||||
switch (*p) {
|
||||
case '\0':
|
||||
p++; /* Skip nul */
|
||||
goto check;
|
||||
|
||||
case '\t':
|
||||
case ' ':
|
||||
break;
|
||||
|
||||
case '\n':
|
||||
parsenleft = q - parsenextc;
|
||||
more = 0; /* Stop processing here */
|
||||
break;
|
||||
|
||||
default:
|
||||
something = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
*q++ = *p++;
|
||||
check:
|
||||
if (--parselleft <= 0) {
|
||||
parsenleft = q - parsenextc - 1;
|
||||
if (parsenleft < 0)
|
||||
goto again;
|
||||
*q = '\0';
|
||||
more = 0;
|
||||
}
|
||||
}
|
||||
|
||||
savec = *q;
|
||||
*q = '\0';
|
||||
|
||||
#ifdef WITH_HISTORY
|
||||
if (parsefile->fd == 0 && hist && something) {
|
||||
HistEvent he;
|
||||
INTOFF;
|
||||
history(hist, &he, whichprompt == 1? H_ENTER : H_APPEND,
|
||||
parsenextc);
|
||||
INTON;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (vflag) {
|
||||
out2str(parsenextc);
|
||||
flushout(out2);
|
||||
}
|
||||
|
||||
*q = savec;
|
||||
|
||||
return *parsenextc++;
|
||||
}
|
||||
|
||||
/*
|
||||
* Undo the last call to pgetc. Only one character may be pushed back.
|
||||
* PEOF may be pushed back.
|
||||
*/
|
||||
|
||||
void
|
||||
pungetc(void)
|
||||
{
|
||||
parsenleft++;
|
||||
parsenextc--;
|
||||
}
|
||||
|
||||
/*
|
||||
* Push a string back onto the input at this current parsefile level.
|
||||
* We handle aliases this way.
|
||||
*/
|
||||
void
|
||||
pushstring(char *s, int len, void *ap)
|
||||
{
|
||||
struct strpush *sp;
|
||||
|
||||
INTOFF;
|
||||
/*dprintf("*** calling pushstring: %s, %d\n", s, len);*/
|
||||
if (parsefile->strpush) {
|
||||
sp = ckmalloc(sizeof (struct strpush));
|
||||
sp->prev = parsefile->strpush;
|
||||
parsefile->strpush = sp;
|
||||
} else
|
||||
sp = parsefile->strpush = &(parsefile->basestrpush);
|
||||
sp->prevstring = parsenextc;
|
||||
sp->prevnleft = parsenleft;
|
||||
sp->prevlleft = parselleft;
|
||||
sp->ap = (struct alias *)ap;
|
||||
if (ap)
|
||||
((struct alias *)ap)->flag |= ALIASINUSE;
|
||||
parsenextc = s;
|
||||
parsenleft = len;
|
||||
INTON;
|
||||
}
|
||||
|
||||
void
|
||||
popstring(void)
|
||||
{
|
||||
struct strpush *sp = parsefile->strpush;
|
||||
|
||||
INTOFF;
|
||||
parsenextc = sp->prevstring;
|
||||
parsenleft = sp->prevnleft;
|
||||
parselleft = sp->prevlleft;
|
||||
/*dprintf("*** calling popstring: restoring to '%s'\n", parsenextc);*/
|
||||
if (sp->ap)
|
||||
sp->ap->flag &= ~ALIASINUSE;
|
||||
parsefile->strpush = sp->prev;
|
||||
if (sp != &(parsefile->basestrpush))
|
||||
ckfree(sp);
|
||||
INTON;
|
||||
}
|
||||
|
||||
/*
|
||||
* Set the input to take input from a file. If push is set, push the
|
||||
* old input onto the stack first.
|
||||
*/
|
||||
|
||||
void
|
||||
setinputfile(const char *fname, int push)
|
||||
{
|
||||
int fd;
|
||||
int fd2;
|
||||
|
||||
INTOFF;
|
||||
if ((fd = open(fname, O_RDONLY)) < 0)
|
||||
error("Can't open %s", fname);
|
||||
if (fd < 10) {
|
||||
fd2 = copyfd(fd, 10);
|
||||
close(fd);
|
||||
if (fd2 < 0)
|
||||
error("Out of file descriptors");
|
||||
fd = fd2;
|
||||
}
|
||||
setinputfd(fd, push);
|
||||
INTON;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Like setinputfile, but takes an open file descriptor. Call this with
|
||||
* interrupts off.
|
||||
*/
|
||||
|
||||
void
|
||||
setinputfd(int fd, int push)
|
||||
{
|
||||
(void) fcntl(fd, F_SETFD, FD_CLOEXEC);
|
||||
if (push) {
|
||||
pushfile();
|
||||
parsefile->buf = ckmalloc(BUFSIZ);
|
||||
}
|
||||
if (parsefile->fd > 0)
|
||||
close(parsefile->fd);
|
||||
parsefile->fd = fd;
|
||||
if (parsefile->buf == NULL)
|
||||
parsefile->buf = ckmalloc(BUFSIZ);
|
||||
parselleft = parsenleft = 0;
|
||||
plinno = 1;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Like setinputfile, but takes input from a string.
|
||||
*/
|
||||
|
||||
void
|
||||
setinputstring(char *string, int push)
|
||||
{
|
||||
INTOFF;
|
||||
if (push)
|
||||
pushfile();
|
||||
parsenextc = string;
|
||||
parselleft = parsenleft = strlen(string);
|
||||
parsefile->buf = NULL;
|
||||
plinno = 1;
|
||||
INTON;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* To handle the "." command, a stack of input files is used. Pushfile
|
||||
* adds a new entry to the stack and popfile restores the previous level.
|
||||
*/
|
||||
|
||||
STATIC void
|
||||
pushfile(void)
|
||||
{
|
||||
struct parsefile *pf;
|
||||
|
||||
parsefile->nleft = parsenleft;
|
||||
parsefile->lleft = parselleft;
|
||||
parsefile->nextc = parsenextc;
|
||||
parsefile->linno = plinno;
|
||||
pf = (struct parsefile *)ckmalloc(sizeof (struct parsefile));
|
||||
pf->prev = parsefile;
|
||||
pf->fd = -1;
|
||||
pf->strpush = NULL;
|
||||
pf->basestrpush.prev = NULL;
|
||||
parsefile = pf;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
popfile(void)
|
||||
{
|
||||
struct parsefile *pf = parsefile;
|
||||
|
||||
INTOFF;
|
||||
if (pf->fd >= 0)
|
||||
close(pf->fd);
|
||||
if (pf->buf)
|
||||
ckfree(pf->buf);
|
||||
while (pf->strpush)
|
||||
popstring();
|
||||
parsefile = pf->prev;
|
||||
ckfree(pf);
|
||||
parsenleft = parsefile->nleft;
|
||||
parselleft = parsefile->lleft;
|
||||
parsenextc = parsefile->nextc;
|
||||
plinno = parsefile->linno;
|
||||
INTON;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Return to top level.
|
||||
*/
|
||||
|
||||
void
|
||||
popallfiles(void)
|
||||
{
|
||||
while (parsefile != &basepf)
|
||||
popfile();
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Close the file(s) that the shell is reading commands from. Called
|
||||
* after a fork is done.
|
||||
*
|
||||
* Takes one arg, vfork, which tells it to not modify its global vars
|
||||
* as it is still running in the parent.
|
||||
*
|
||||
* This code is (probably) unnecessary as the 'close on exec' flag is
|
||||
* set and should be enough. In the vfork case it is definitely wrong
|
||||
* to close the fds as another fork() may be done later to feed data
|
||||
* from a 'here' document into a pipe and we don't want to close the
|
||||
* pipe!
|
||||
*/
|
||||
|
||||
void
|
||||
closescript(int vforked)
|
||||
{
|
||||
if (vforked)
|
||||
return;
|
||||
popallfiles();
|
||||
if (parsefile->fd > 0) {
|
||||
close(parsefile->fd);
|
||||
parsefile->fd = 0;
|
||||
}
|
||||
}
|
||||
63
sh/input.h
63
sh/input.h
|
|
@ -1,63 +0,0 @@
|
|||
/* $NetBSD: input.h,v 1.15 2003/08/07 09:05:33 agc Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1991, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to Berkeley by
|
||||
* Kenneth Almquist.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)input.h 8.2 (Berkeley) 5/4/95
|
||||
*/
|
||||
|
||||
/* PEOF (the end of file marker) is defined in syntax.h */
|
||||
|
||||
/*
|
||||
* The input line number. Input.c just defines this variable, and saves
|
||||
* and restores it when files are pushed and popped. The user of this
|
||||
* package must set its value.
|
||||
*/
|
||||
extern int plinno;
|
||||
extern int parsenleft; /* number of characters left in input buffer */
|
||||
extern char *parsenextc; /* next character in input buffer */
|
||||
extern int init_editline; /* 0 == not setup, 1 == OK, -1 == failed */
|
||||
|
||||
int in_interactive_mode();
|
||||
char *pfgets(char *, int);
|
||||
int pgetc(void);
|
||||
int preadbuffer(void);
|
||||
void pungetc(void);
|
||||
void pushstring(char *, int, void *);
|
||||
void popstring(void);
|
||||
void setinputfile(const char *, int);
|
||||
void setinputfd(int, int);
|
||||
void setinputstring(char *, int);
|
||||
void popfile(void);
|
||||
void popallfiles(void);
|
||||
void closescript(int);
|
||||
|
||||
#define pgetc_macro() (--parsenleft >= 0? *parsenextc++ : preadbuffer())
|
||||
106
sh/jobs.h
106
sh/jobs.h
|
|
@ -1,106 +0,0 @@
|
|||
/* $NetBSD: jobs.h,v 1.19 2003/11/27 21:16:14 dsl Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1991, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to Berkeley by
|
||||
* Kenneth Almquist.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)jobs.h 8.2 (Berkeley) 5/4/95
|
||||
*/
|
||||
|
||||
#include "output.h"
|
||||
|
||||
/* Mode argument to forkshell. Don't change FORK_FG or FORK_BG. */
|
||||
#define FORK_FG 0
|
||||
#define FORK_BG 1
|
||||
#define FORK_NOJOB 2
|
||||
|
||||
/* mode flags for showjob(s) */
|
||||
#define SHOW_PGID 0x01 /* only show pgid - for jobs -p */
|
||||
#define SHOW_MULTILINE 0x02 /* one line per process */
|
||||
#define SHOW_PID 0x04 /* include process pid */
|
||||
#define SHOW_CHANGED 0x08 /* only jobs whose state has changed */
|
||||
#define SHOW_SIGNALLED 0x10 /* only if stopped/exited on signal */
|
||||
#define SHOW_ISSIG 0x20 /* job was signalled */
|
||||
#define SHOW_NO_FREE 0x40 /* do not free job */
|
||||
|
||||
|
||||
/*
|
||||
* A job structure contains information about a job. A job is either a
|
||||
* single process or a set of processes contained in a pipeline. In the
|
||||
* latter case, pidlist will be non-NULL, and will point to a -1 terminated
|
||||
* array of pids.
|
||||
*/
|
||||
#define MAXCMDTEXT 200
|
||||
|
||||
struct procstat {
|
||||
pid_t pid; /* process id */
|
||||
int status; /* last process status from wait() */
|
||||
char cmd[MAXCMDTEXT];/* text of command being run */
|
||||
};
|
||||
|
||||
struct job {
|
||||
struct procstat ps0; /* status of process */
|
||||
struct procstat *ps; /* status or processes when more than one */
|
||||
int nprocs; /* number of processes */
|
||||
pid_t pgrp; /* process group of this job */
|
||||
char state;
|
||||
#define JOBRUNNING 0 /* at least one proc running */
|
||||
#define JOBSTOPPED 1 /* all procs are stopped */
|
||||
#define JOBDONE 2 /* all procs are completed */
|
||||
char used; /* true if this entry is in used */
|
||||
char changed; /* true if status has changed */
|
||||
#if JOBS
|
||||
char jobctl; /* job running under job control */
|
||||
int prev_job; /* previous job index */
|
||||
#endif
|
||||
};
|
||||
|
||||
extern pid_t backgndpid; /* pid of last background process */
|
||||
extern int job_warning; /* user was warned about stopped jobs */
|
||||
|
||||
void setjobctl(int);
|
||||
int fgcmd(int, char **);
|
||||
int bgcmd(int, char **);
|
||||
int jobscmd(int, char **);
|
||||
void showjobs(struct output *, int);
|
||||
int waitcmd(int, char **);
|
||||
int jobidcmd(int, char **);
|
||||
struct job *makejob(union node *, int);
|
||||
int forkshell(struct job *, union node *, int);
|
||||
void forkchild(struct job *, union node *, int, int);
|
||||
int forkparent(struct job *, union node *, int, pid_t);
|
||||
int waitforjob(struct job *);
|
||||
int stoppedjobs(void);
|
||||
void commandtext(struct procstat *, union node *);
|
||||
int getjobpgrp(const char *);
|
||||
|
||||
#if ! JOBS
|
||||
#define setjobctl(on) /* do nothing */
|
||||
#endif
|
||||
47
sh/machdep.h
47
sh/machdep.h
|
|
@ -1,47 +0,0 @@
|
|||
/* $NetBSD: machdep.h,v 1.11 2003/08/07 09:05:33 agc Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1991, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to Berkeley by
|
||||
* Kenneth Almquist.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)machdep.h 8.2 (Berkeley) 5/4/95
|
||||
*/
|
||||
|
||||
/*
|
||||
* Most machines require the value returned from malloc to be aligned
|
||||
* in some way. The following macro will get this right on many machines.
|
||||
*/
|
||||
|
||||
#define SHELL_SIZE (sizeof(union {int i; char *cp; double d; }) - 1)
|
||||
/*
|
||||
* It appears that grabstackstr() will barf with such alignments
|
||||
* because stalloc() will return a string allocated in a new stackblock.
|
||||
*/
|
||||
#define SHELL_ALIGN(nbytes) (((nbytes) + SHELL_SIZE) & ~SHELL_SIZE)
|
||||
394
sh/main.c
394
sh/main.c
|
|
@ -1,394 +0,0 @@
|
|||
/* $NetBSD: main.c,v 1.48 2003/09/14 12:09:29 jmmv Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1991, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to Berkeley by
|
||||
* Kenneth Almquist.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
#ifndef lint
|
||||
__COPYRIGHT("@(#) Copyright (c) 1991, 1993\n\
|
||||
The Regents of the University of California. All rights reserved.\n");
|
||||
#endif /* not lint */
|
||||
|
||||
#ifndef lint
|
||||
#if 0
|
||||
static char sccsid[] = "@(#)main.c 8.7 (Berkeley) 7/19/95";
|
||||
#else
|
||||
__RCSID("$NetBSD: main.c,v 1.48 2003/09/14 12:09:29 jmmv Exp $");
|
||||
#endif
|
||||
#endif /* not lint */
|
||||
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <signal.h>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
|
||||
#include "shell.h"
|
||||
#include "main.h"
|
||||
#include "options.h"
|
||||
#include "output.h"
|
||||
#include "parser.h"
|
||||
#include "nodes.h"
|
||||
#include "expand.h"
|
||||
#include "eval.h"
|
||||
#include "jobs.h"
|
||||
#include "input.h"
|
||||
#include "trap.h"
|
||||
#include "var.h"
|
||||
#include "show.h"
|
||||
#include "memalloc.h"
|
||||
#include "error.h"
|
||||
#include "init.h"
|
||||
#include "mystring.h"
|
||||
#include "exec.h"
|
||||
#include "cd.h"
|
||||
|
||||
#define PROFILE 0
|
||||
|
||||
int rootpid;
|
||||
int rootshell;
|
||||
STATIC union node *curcmd;
|
||||
STATIC union node *prevcmd;
|
||||
#if PROFILE
|
||||
short profile_buf[16384];
|
||||
extern int etext();
|
||||
#endif
|
||||
|
||||
STATIC void read_profile(const char *);
|
||||
STATIC char *find_dot_file(char *);
|
||||
int main(int, char **);
|
||||
|
||||
/*
|
||||
* Main routine. We initialize things, parse the arguments, execute
|
||||
* profiles if we're a login shell, and then call cmdloop to execute
|
||||
* commands. The setjmp call sets up the location to jump to when an
|
||||
* exception occurs. When an exception occurs the variable "state"
|
||||
* is used to figure out how far we had gotten.
|
||||
*/
|
||||
|
||||
int
|
||||
main(int argc, char **argv)
|
||||
{
|
||||
struct jmploc jmploc;
|
||||
struct stackmark smark;
|
||||
volatile int state;
|
||||
char *shinit;
|
||||
|
||||
#if PROFILE
|
||||
monitor(4, etext, profile_buf, sizeof profile_buf, 50);
|
||||
#endif
|
||||
state = 0;
|
||||
if (setjmp(jmploc.loc)) {
|
||||
/*
|
||||
* When a shell procedure is executed, we raise the
|
||||
* exception EXSHELLPROC to clean up before executing
|
||||
* the shell procedure.
|
||||
*/
|
||||
switch (exception) {
|
||||
case EXSHELLPROC:
|
||||
rootpid = getpid();
|
||||
rootshell = 1;
|
||||
minusc = NULL;
|
||||
state = 3;
|
||||
break;
|
||||
|
||||
case EXEXEC:
|
||||
exitstatus = exerrno;
|
||||
break;
|
||||
|
||||
case EXERROR:
|
||||
exitstatus = 2;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (exception != EXSHELLPROC) {
|
||||
if (state == 0 || iflag == 0 || ! rootshell)
|
||||
exitshell(exitstatus);
|
||||
}
|
||||
reset();
|
||||
if (exception == EXINT
|
||||
#if ATTY
|
||||
&& (! attyset() || equal(termval(), "emacs"))
|
||||
#endif
|
||||
) {
|
||||
out2c('\n');
|
||||
flushout(&errout);
|
||||
}
|
||||
popstackmark(&smark);
|
||||
FORCEINTON; /* enable interrupts */
|
||||
if (state == 1)
|
||||
goto state1;
|
||||
else if (state == 2)
|
||||
goto state2;
|
||||
else if (state == 3)
|
||||
goto state3;
|
||||
else
|
||||
goto state4;
|
||||
}
|
||||
handler = &jmploc;
|
||||
#ifdef DEBUG
|
||||
#if DEBUG == 2
|
||||
debug = 1;
|
||||
#endif
|
||||
opentrace();
|
||||
trputs("Shell args: "); trargs(argv);
|
||||
#endif
|
||||
rootpid = getpid();
|
||||
rootshell = 1;
|
||||
init();
|
||||
setstackmark(&smark);
|
||||
procargs(argc, argv);
|
||||
if (argv[0] && argv[0][0] == '-') {
|
||||
state = 1;
|
||||
read_profile("/etc/profile");
|
||||
state1:
|
||||
state = 2;
|
||||
read_profile(".profile");
|
||||
}
|
||||
state2:
|
||||
state = 3;
|
||||
if (getuid() == geteuid() && getgid() == getegid()) {
|
||||
if ((shinit = lookupvar("ENV")) != NULL && *shinit != '\0') {
|
||||
state = 3;
|
||||
read_profile(shinit);
|
||||
}
|
||||
}
|
||||
state3:
|
||||
state = 4;
|
||||
if (sflag == 0 || minusc) {
|
||||
static int sigs[] = {
|
||||
SIGINT, SIGQUIT, SIGHUP,
|
||||
#ifdef SIGTSTP
|
||||
SIGTSTP,
|
||||
#endif
|
||||
SIGPIPE
|
||||
};
|
||||
#define SIGSSIZE (sizeof(sigs)/sizeof(sigs[0]))
|
||||
int i;
|
||||
|
||||
for (i = 0; i < SIGSSIZE; i++)
|
||||
setsignal(sigs[i], 0);
|
||||
}
|
||||
|
||||
if (minusc)
|
||||
evalstring(minusc, 0);
|
||||
|
||||
if (sflag || minusc == NULL) {
|
||||
state4: /* XXX ??? - why isn't this before the "if" statement */
|
||||
cmdloop(1);
|
||||
}
|
||||
#if PROFILE
|
||||
monitor(0);
|
||||
#endif
|
||||
exitshell(exitstatus);
|
||||
/* NOTREACHED */
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Read and execute commands. "Top" is nonzero for the top level command
|
||||
* loop; it turns on prompting if the shell is interactive.
|
||||
*/
|
||||
|
||||
void
|
||||
cmdloop(int top)
|
||||
{
|
||||
union node *n;
|
||||
struct stackmark smark;
|
||||
int inter;
|
||||
int numeof = 0;
|
||||
|
||||
TRACE(("cmdloop(%d) called\n", top));
|
||||
setstackmark(&smark);
|
||||
for (;;) {
|
||||
if (pendingsigs)
|
||||
dotrap();
|
||||
inter = 0;
|
||||
if (iflag && top) {
|
||||
inter = 1;
|
||||
showjobs(out2, SHOW_CHANGED);
|
||||
flushout(&errout);
|
||||
}
|
||||
n = parsecmd(inter);
|
||||
/* showtree(n); DEBUG */
|
||||
if (n == NEOF) {
|
||||
if (!top || numeof >= 50)
|
||||
break;
|
||||
if (!stoppedjobs()) {
|
||||
if (!Iflag)
|
||||
break;
|
||||
out2str("\nUse \"exit\" to leave shell.\n");
|
||||
}
|
||||
numeof++;
|
||||
} else if (n != NULL && nflag == 0) {
|
||||
job_warning = (job_warning == 2) ? 1 : 0;
|
||||
numeof = 0;
|
||||
evaltree(n, 0);
|
||||
}
|
||||
popstackmark(&smark);
|
||||
setstackmark(&smark);
|
||||
if (evalskip == SKIPFILE) {
|
||||
evalskip = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
popstackmark(&smark);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Read /etc/profile or .profile. Return on error.
|
||||
*/
|
||||
|
||||
STATIC void
|
||||
read_profile(const char *name)
|
||||
{
|
||||
int fd;
|
||||
int xflag_set = 0;
|
||||
int vflag_set = 0;
|
||||
|
||||
INTOFF;
|
||||
if ((fd = open(name, O_RDONLY)) >= 0)
|
||||
setinputfd(fd, 1);
|
||||
INTON;
|
||||
if (fd < 0)
|
||||
return;
|
||||
/* -q turns off -x and -v just when executing init files */
|
||||
if (qflag) {
|
||||
if (xflag)
|
||||
xflag = 0, xflag_set = 1;
|
||||
if (vflag)
|
||||
vflag = 0, vflag_set = 1;
|
||||
}
|
||||
cmdloop(0);
|
||||
if (qflag) {
|
||||
if (xflag_set)
|
||||
xflag = 1;
|
||||
if (vflag_set)
|
||||
vflag = 1;
|
||||
}
|
||||
popfile();
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Read a file containing shell functions.
|
||||
*/
|
||||
|
||||
void
|
||||
readcmdfile(char *name)
|
||||
{
|
||||
int fd;
|
||||
|
||||
INTOFF;
|
||||
if ((fd = open(name, O_RDONLY)) >= 0)
|
||||
setinputfd(fd, 1);
|
||||
else
|
||||
error("Can't open %s", name);
|
||||
INTON;
|
||||
cmdloop(0);
|
||||
popfile();
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Take commands from a file. To be compatible we should do a path
|
||||
* search for the file, which is necessary to find sub-commands.
|
||||
*/
|
||||
|
||||
|
||||
STATIC char *
|
||||
find_dot_file(char *basename)
|
||||
{
|
||||
char *fullname;
|
||||
const char *path = pathval();
|
||||
struct stat statb;
|
||||
|
||||
/* don't try this for absolute or relative paths */
|
||||
if (strchr(basename, '/'))
|
||||
return basename;
|
||||
|
||||
while ((fullname = padvance(&path, basename)) != NULL) {
|
||||
if ((stat(fullname, &statb) == 0) && S_ISREG(statb.st_mode)) {
|
||||
/*
|
||||
* Don't bother freeing here, since it will
|
||||
* be freed by the caller.
|
||||
*/
|
||||
return fullname;
|
||||
}
|
||||
stunalloc(fullname);
|
||||
}
|
||||
|
||||
/* not found in the PATH */
|
||||
error("%s: not found", basename);
|
||||
/* NOTREACHED */
|
||||
}
|
||||
|
||||
int
|
||||
dotcmd(int argc, char **argv)
|
||||
{
|
||||
exitstatus = 0;
|
||||
|
||||
if (argc >= 2) { /* That's what SVR2 does */
|
||||
char *fullname;
|
||||
struct stackmark smark;
|
||||
|
||||
setstackmark(&smark);
|
||||
fullname = find_dot_file(argv[1]);
|
||||
setinputfile(fullname, 1);
|
||||
commandname = fullname;
|
||||
cmdloop(0);
|
||||
popfile();
|
||||
popstackmark(&smark);
|
||||
}
|
||||
return exitstatus;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
exitcmd(int argc, char **argv)
|
||||
{
|
||||
if (stoppedjobs())
|
||||
return 0;
|
||||
if (argc > 1)
|
||||
exitstatus = number(argv[1]);
|
||||
exitshell(exitstatus);
|
||||
/* NOTREACHED */
|
||||
}
|
||||
43
sh/main.h
43
sh/main.h
|
|
@ -1,43 +0,0 @@
|
|||
/* $NetBSD: main.h,v 1.10 2003/08/07 09:05:34 agc Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1991, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to Berkeley by
|
||||
* Kenneth Almquist.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)main.h 8.2 (Berkeley) 5/4/95
|
||||
*/
|
||||
|
||||
extern int rootpid; /* pid of main shell */
|
||||
extern int rootshell; /* true if we aren't a child of the main shell */
|
||||
|
||||
void readcmdfile(char *);
|
||||
void cmdloop(int);
|
||||
int dotcmd(int, char **);
|
||||
int exitcmd(int, char **);
|
||||
307
sh/memalloc.c
307
sh/memalloc.c
|
|
@ -1,307 +0,0 @@
|
|||
/* $NetBSD: memalloc.c,v 1.28 2003/08/07 09:05:34 agc Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1991, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to Berkeley by
|
||||
* Kenneth Almquist.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
#ifndef lint
|
||||
#if 0
|
||||
static char sccsid[] = "@(#)memalloc.c 8.3 (Berkeley) 5/4/95";
|
||||
#else
|
||||
__RCSID("$NetBSD: memalloc.c,v 1.28 2003/08/07 09:05:34 agc Exp $");
|
||||
#endif
|
||||
#endif /* not lint */
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "shell.h"
|
||||
#include "output.h"
|
||||
#include "memalloc.h"
|
||||
#include "error.h"
|
||||
#include "machdep.h"
|
||||
#include "mystring.h"
|
||||
|
||||
/*
|
||||
* Like malloc, but returns an error when out of space.
|
||||
*/
|
||||
|
||||
pointer
|
||||
ckmalloc(int nbytes)
|
||||
{
|
||||
pointer p;
|
||||
|
||||
p = malloc(nbytes);
|
||||
if (p == NULL)
|
||||
error("Out of space");
|
||||
return p;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Same for realloc.
|
||||
*/
|
||||
|
||||
pointer
|
||||
ckrealloc(pointer p, int nbytes)
|
||||
{
|
||||
p = realloc(p, nbytes);
|
||||
if (p == NULL)
|
||||
error("Out of space");
|
||||
return p;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Make a copy of a string in safe storage.
|
||||
*/
|
||||
|
||||
char *
|
||||
savestr(const char *s)
|
||||
{
|
||||
char *p;
|
||||
|
||||
p = ckmalloc(strlen(s) + 1);
|
||||
scopy(s, p);
|
||||
return p;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Parse trees for commands are allocated in lifo order, so we use a stack
|
||||
* to make this more efficient, and also to avoid all sorts of exception
|
||||
* handling code to handle interrupts in the middle of a parse.
|
||||
*
|
||||
* The size 504 was chosen because the Ultrix malloc handles that size
|
||||
* well.
|
||||
*/
|
||||
|
||||
#define MINSIZE 504 /* minimum size of a block */
|
||||
|
||||
struct stack_block {
|
||||
struct stack_block *prev;
|
||||
char space[MINSIZE];
|
||||
};
|
||||
|
||||
struct stack_block stackbase;
|
||||
struct stack_block *stackp = &stackbase;
|
||||
struct stackmark *markp;
|
||||
char *stacknxt = stackbase.space;
|
||||
int stacknleft = MINSIZE;
|
||||
int sstrnleft;
|
||||
int herefd = -1;
|
||||
|
||||
pointer
|
||||
stalloc(int nbytes)
|
||||
{
|
||||
char *p;
|
||||
|
||||
nbytes = SHELL_ALIGN(nbytes);
|
||||
if (nbytes > stacknleft) {
|
||||
int blocksize;
|
||||
struct stack_block *sp;
|
||||
|
||||
blocksize = nbytes;
|
||||
if (blocksize < MINSIZE)
|
||||
blocksize = MINSIZE;
|
||||
INTOFF;
|
||||
sp = ckmalloc(sizeof(struct stack_block) - MINSIZE + blocksize);
|
||||
sp->prev = stackp;
|
||||
stacknxt = sp->space;
|
||||
stacknleft = blocksize;
|
||||
stackp = sp;
|
||||
INTON;
|
||||
}
|
||||
p = stacknxt;
|
||||
stacknxt += nbytes;
|
||||
stacknleft -= nbytes;
|
||||
return p;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
stunalloc(pointer p)
|
||||
{
|
||||
if (p == NULL) { /*DEBUG */
|
||||
write(2, "stunalloc\n", 10);
|
||||
abort();
|
||||
}
|
||||
stacknleft += stacknxt - (char *)p;
|
||||
stacknxt = p;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
setstackmark(struct stackmark *mark)
|
||||
{
|
||||
mark->stackp = stackp;
|
||||
mark->stacknxt = stacknxt;
|
||||
mark->stacknleft = stacknleft;
|
||||
mark->marknext = markp;
|
||||
markp = mark;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
popstackmark(struct stackmark *mark)
|
||||
{
|
||||
struct stack_block *sp;
|
||||
|
||||
INTOFF;
|
||||
markp = mark->marknext;
|
||||
while (stackp != mark->stackp) {
|
||||
sp = stackp;
|
||||
stackp = sp->prev;
|
||||
ckfree(sp);
|
||||
}
|
||||
stacknxt = mark->stacknxt;
|
||||
stacknleft = mark->stacknleft;
|
||||
INTON;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* When the parser reads in a string, it wants to stick the string on the
|
||||
* stack and only adjust the stack pointer when it knows how big the
|
||||
* string is. Stackblock (defined in stack.h) returns a pointer to a block
|
||||
* of space on top of the stack and stackblocklen returns the length of
|
||||
* this block. Growstackblock will grow this space by at least one byte,
|
||||
* possibly moving it (like realloc). Grabstackblock actually allocates the
|
||||
* part of the block that has been used.
|
||||
*/
|
||||
|
||||
void
|
||||
growstackblock(void)
|
||||
{
|
||||
int newlen = SHELL_ALIGN(stacknleft * 2 + 100);
|
||||
|
||||
if (stacknxt == stackp->space && stackp != &stackbase) {
|
||||
struct stack_block *oldstackp;
|
||||
struct stackmark *xmark;
|
||||
struct stack_block *sp;
|
||||
|
||||
INTOFF;
|
||||
oldstackp = stackp;
|
||||
sp = stackp;
|
||||
stackp = sp->prev;
|
||||
sp = ckrealloc((pointer)sp,
|
||||
sizeof(struct stack_block) - MINSIZE + newlen);
|
||||
sp->prev = stackp;
|
||||
stackp = sp;
|
||||
stacknxt = sp->space;
|
||||
stacknleft = newlen;
|
||||
|
||||
/*
|
||||
* Stack marks pointing to the start of the old block
|
||||
* must be relocated to point to the new block
|
||||
*/
|
||||
xmark = markp;
|
||||
while (xmark != NULL && xmark->stackp == oldstackp) {
|
||||
xmark->stackp = stackp;
|
||||
xmark->stacknxt = stacknxt;
|
||||
xmark->stacknleft = stacknleft;
|
||||
xmark = xmark->marknext;
|
||||
}
|
||||
INTON;
|
||||
} else {
|
||||
char *oldspace = stacknxt;
|
||||
int oldlen = stacknleft;
|
||||
char *p = stalloc(newlen);
|
||||
|
||||
(void)memcpy(p, oldspace, oldlen);
|
||||
stacknxt = p; /* free the space */
|
||||
stacknleft += newlen; /* we just allocated */
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
grabstackblock(int len)
|
||||
{
|
||||
len = SHELL_ALIGN(len);
|
||||
stacknxt += len;
|
||||
stacknleft -= len;
|
||||
}
|
||||
|
||||
/*
|
||||
* The following routines are somewhat easier to use than the above.
|
||||
* The user declares a variable of type STACKSTR, which may be declared
|
||||
* to be a register. The macro STARTSTACKSTR initializes things. Then
|
||||
* the user uses the macro STPUTC to add characters to the string. In
|
||||
* effect, STPUTC(c, p) is the same as *p++ = c except that the stack is
|
||||
* grown as necessary. When the user is done, she can just leave the
|
||||
* string there and refer to it using stackblock(). Or she can allocate
|
||||
* the space for it using grabstackstr(). If it is necessary to allow
|
||||
* someone else to use the stack temporarily and then continue to grow
|
||||
* the string, the user should use grabstack to allocate the space, and
|
||||
* then call ungrabstr(p) to return to the previous mode of operation.
|
||||
*
|
||||
* USTPUTC is like STPUTC except that it doesn't check for overflow.
|
||||
* CHECKSTACKSPACE can be called before USTPUTC to ensure that there
|
||||
* is space for at least one character.
|
||||
*/
|
||||
|
||||
char *
|
||||
growstackstr(void)
|
||||
{
|
||||
int len = stackblocksize();
|
||||
if (herefd >= 0 && len >= 1024) {
|
||||
xwrite(herefd, stackblock(), len);
|
||||
sstrnleft = len - 1;
|
||||
return stackblock();
|
||||
}
|
||||
growstackblock();
|
||||
sstrnleft = stackblocksize() - len - 1;
|
||||
return stackblock() + len;
|
||||
}
|
||||
|
||||
/*
|
||||
* Called from CHECKSTRSPACE.
|
||||
*/
|
||||
|
||||
char *
|
||||
makestrspace(void)
|
||||
{
|
||||
int len = stackblocksize() - sstrnleft;
|
||||
growstackblock();
|
||||
sstrnleft = stackblocksize() - len;
|
||||
return stackblock() + len;
|
||||
}
|
||||
|
||||
void
|
||||
ungrabstackstr(char *s, char *p)
|
||||
{
|
||||
stacknleft += stacknxt - s;
|
||||
stacknxt = s;
|
||||
sstrnleft = stacknleft - (p - s);
|
||||
|
||||
}
|
||||
|
|
@ -1,77 +0,0 @@
|
|||
/* $NetBSD: memalloc.h,v 1.14 2003/08/07 09:05:34 agc Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1991, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to Berkeley by
|
||||
* Kenneth Almquist.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)memalloc.h 8.2 (Berkeley) 5/4/95
|
||||
*/
|
||||
|
||||
struct stackmark {
|
||||
struct stack_block *stackp;
|
||||
char *stacknxt;
|
||||
int stacknleft;
|
||||
struct stackmark *marknext;
|
||||
};
|
||||
|
||||
|
||||
extern char *stacknxt;
|
||||
extern int stacknleft;
|
||||
extern int sstrnleft;
|
||||
extern int herefd;
|
||||
|
||||
pointer ckmalloc(int);
|
||||
pointer ckrealloc(pointer, int);
|
||||
char *savestr(const char *);
|
||||
pointer stalloc(int);
|
||||
void stunalloc(pointer);
|
||||
void setstackmark(struct stackmark *);
|
||||
void popstackmark(struct stackmark *);
|
||||
void growstackblock(void);
|
||||
void grabstackblock(int);
|
||||
char *growstackstr(void);
|
||||
char *makestrspace(void);
|
||||
void ungrabstackstr(char *, char *);
|
||||
|
||||
|
||||
|
||||
#define stackblock() stacknxt
|
||||
#define stackblocksize() stacknleft
|
||||
#define STARTSTACKSTR(p) p = stackblock(), sstrnleft = stackblocksize()
|
||||
#define STPUTC(c, p) (--sstrnleft >= 0? (*p++ = (c)) : (p = growstackstr(), *p++ = (c)))
|
||||
#define CHECKSTRSPACE(n, p) { if (sstrnleft < n) p = makestrspace(); }
|
||||
#define USTPUTC(c, p) (--sstrnleft, *p++ = (c))
|
||||
#define STACKSTRNUL(p) (sstrnleft == 0? (p = growstackstr(), *p = '\0') : (*p = '\0'))
|
||||
#define STUNPUTC(p) (++sstrnleft, --p)
|
||||
#define STTOPC(p) p[-1]
|
||||
#define STADJUST(amount, p) (p += (amount), sstrnleft -= (amount))
|
||||
#define grabstackstr(p) stalloc(stackblocksize() - sstrnleft)
|
||||
|
||||
#define ckfree(p) free((pointer)(p))
|
||||
445
sh/miscbltin.c
445
sh/miscbltin.c
|
|
@ -1,445 +0,0 @@
|
|||
/* $NetBSD: miscbltin.c,v 1.34.2.1 2005/04/07 11:34:20 tron Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1991, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to Berkeley by
|
||||
* Kenneth Almquist.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
#ifndef lint
|
||||
#if 0
|
||||
static char sccsid[] = "@(#)miscbltin.c 8.4 (Berkeley) 5/4/95";
|
||||
#else
|
||||
__RCSID("$NetBSD: miscbltin.c,v 1.34.2.1 2005/04/07 11:34:20 tron Exp $");
|
||||
#endif
|
||||
#endif /* not lint */
|
||||
|
||||
/*
|
||||
* Miscelaneous builtins.
|
||||
*/
|
||||
|
||||
#include <sys/types.h> /* quad_t */
|
||||
#include <sys/param.h> /* BSD4_4 */
|
||||
#include <sys/stat.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/resource.h>
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
#include <ctype.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include "shell.h"
|
||||
#include "options.h"
|
||||
#include "var.h"
|
||||
#include "output.h"
|
||||
#include "memalloc.h"
|
||||
#include "error.h"
|
||||
#include "miscbltin.h"
|
||||
#include "mystring.h"
|
||||
|
||||
#undef rflag
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* The read builtin.
|
||||
* Backslahes escape the next char unless -r is specified.
|
||||
*
|
||||
* This uses unbuffered input, which may be avoidable in some cases.
|
||||
*
|
||||
* Note that if IFS=' :' then read x y should work so that:
|
||||
* 'a b' x='a', y='b'
|
||||
* ' a b ' x='a', y='b'
|
||||
* ':b' x='', y='b'
|
||||
* ':' x='', y=''
|
||||
* '::' x='', y=''
|
||||
* ': :' x='', y=''
|
||||
* ':::' x='', y='::'
|
||||
* ':b c:' x='', y='b c:'
|
||||
*/
|
||||
|
||||
int
|
||||
readcmd(int argc, char **argv)
|
||||
{
|
||||
char **ap;
|
||||
char c;
|
||||
int rflag;
|
||||
char *prompt;
|
||||
const char *ifs;
|
||||
char *p;
|
||||
int startword;
|
||||
int status;
|
||||
int i;
|
||||
int is_ifs;
|
||||
int saveall = 0;
|
||||
|
||||
rflag = 0;
|
||||
prompt = NULL;
|
||||
while ((i = nextopt("p:r")) != '\0') {
|
||||
if (i == 'p')
|
||||
prompt = optionarg;
|
||||
else
|
||||
rflag = 1;
|
||||
}
|
||||
|
||||
if (prompt && isatty(0)) {
|
||||
out2str(prompt);
|
||||
flushall();
|
||||
}
|
||||
|
||||
if (*(ap = argptr) == NULL)
|
||||
error("arg count");
|
||||
|
||||
if ((ifs = bltinlookup("IFS", 1)) == NULL)
|
||||
ifs = " \t\n";
|
||||
|
||||
status = 0;
|
||||
startword = 2;
|
||||
STARTSTACKSTR(p);
|
||||
for (;;) {
|
||||
if (read(0, &c, 1) != 1) {
|
||||
status = 1;
|
||||
break;
|
||||
}
|
||||
if (c == '\0')
|
||||
continue;
|
||||
if (c == '\\' && !rflag) {
|
||||
if (read(0, &c, 1) != 1) {
|
||||
status = 1;
|
||||
break;
|
||||
}
|
||||
if (c != '\n')
|
||||
STPUTC(c, p);
|
||||
continue;
|
||||
}
|
||||
if (c == '\n')
|
||||
break;
|
||||
if (strchr(ifs, c))
|
||||
is_ifs = strchr(" \t\n", c) ? 1 : 2;
|
||||
else
|
||||
is_ifs = 0;
|
||||
|
||||
if (startword != 0) {
|
||||
if (is_ifs == 1) {
|
||||
/* Ignore leading IFS whitespace */
|
||||
if (saveall)
|
||||
STPUTC(c, p);
|
||||
continue;
|
||||
}
|
||||
if (is_ifs == 2 && startword == 1) {
|
||||
/* Only one non-whitespace IFS per word */
|
||||
startword = 2;
|
||||
if (saveall)
|
||||
STPUTC(c, p);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (is_ifs == 0) {
|
||||
/* append this character to the current variable */
|
||||
startword = 0;
|
||||
if (saveall)
|
||||
/* Not just a spare terminator */
|
||||
saveall++;
|
||||
STPUTC(c, p);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* end of variable... */
|
||||
startword = is_ifs;
|
||||
|
||||
if (ap[1] == NULL) {
|
||||
/* Last variable needs all IFS chars */
|
||||
saveall++;
|
||||
STPUTC(c, p);
|
||||
continue;
|
||||
}
|
||||
|
||||
STACKSTRNUL(p);
|
||||
setvar(*ap, stackblock(), 0);
|
||||
ap++;
|
||||
STARTSTACKSTR(p);
|
||||
}
|
||||
STACKSTRNUL(p);
|
||||
|
||||
/* Remove trailing IFS chars */
|
||||
for (; stackblock() <= --p; *p = 0) {
|
||||
if (!strchr(ifs, *p))
|
||||
break;
|
||||
if (strchr(" \t\n", *p))
|
||||
/* Always remove whitespace */
|
||||
continue;
|
||||
if (saveall > 1)
|
||||
/* Don't remove non-whitespace unless it was naked */
|
||||
break;
|
||||
}
|
||||
setvar(*ap, stackblock(), 0);
|
||||
|
||||
/* Set any remaining args to "" */
|
||||
while (*++ap != NULL)
|
||||
setvar(*ap, nullstr, 0);
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int
|
||||
umaskcmd(int argc, char **argv)
|
||||
{
|
||||
char *ap;
|
||||
int mask;
|
||||
int i;
|
||||
int symbolic_mode = 0;
|
||||
|
||||
while ((i = nextopt("S")) != '\0') {
|
||||
symbolic_mode = 1;
|
||||
}
|
||||
|
||||
INTOFF;
|
||||
mask = umask(0);
|
||||
umask(mask);
|
||||
INTON;
|
||||
|
||||
if ((ap = *argptr) == NULL) {
|
||||
if (symbolic_mode) {
|
||||
char u[4], g[4], o[4];
|
||||
|
||||
i = 0;
|
||||
if ((mask & S_IRUSR) == 0)
|
||||
u[i++] = 'r';
|
||||
if ((mask & S_IWUSR) == 0)
|
||||
u[i++] = 'w';
|
||||
if ((mask & S_IXUSR) == 0)
|
||||
u[i++] = 'x';
|
||||
u[i] = '\0';
|
||||
|
||||
i = 0;
|
||||
if ((mask & S_IRGRP) == 0)
|
||||
g[i++] = 'r';
|
||||
if ((mask & S_IWGRP) == 0)
|
||||
g[i++] = 'w';
|
||||
if ((mask & S_IXGRP) == 0)
|
||||
g[i++] = 'x';
|
||||
g[i] = '\0';
|
||||
|
||||
i = 0;
|
||||
if ((mask & S_IROTH) == 0)
|
||||
o[i++] = 'r';
|
||||
if ((mask & S_IWOTH) == 0)
|
||||
o[i++] = 'w';
|
||||
if ((mask & S_IXOTH) == 0)
|
||||
o[i++] = 'x';
|
||||
o[i] = '\0';
|
||||
|
||||
out1fmt("u=%s,g=%s,o=%s\n", u, g, o);
|
||||
} else {
|
||||
out1fmt("%.4o\n", mask);
|
||||
}
|
||||
} else {
|
||||
if (isdigit((unsigned char)*ap)) {
|
||||
mask = 0;
|
||||
do {
|
||||
if (*ap >= '8' || *ap < '0')
|
||||
error("Illegal number: %s", argv[1]);
|
||||
mask = (mask << 3) + (*ap - '0');
|
||||
} while (*++ap != '\0');
|
||||
umask(mask);
|
||||
} else
|
||||
error("Illegal mode: %s", ap);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if 1
|
||||
/*
|
||||
* ulimit builtin
|
||||
*
|
||||
* This code, originally by Doug Gwyn, Doug Kingston, Eric Gisin, and
|
||||
* Michael Rendell was ripped from pdksh 5.0.8 and hacked for use with
|
||||
* ash by J.T. Conklin.
|
||||
*
|
||||
* Public domain.
|
||||
*/
|
||||
|
||||
struct limits {
|
||||
const char *name;
|
||||
int cmd;
|
||||
int factor; /* multiply by to get rlim_{cur,max} values */
|
||||
char option;
|
||||
};
|
||||
|
||||
static const struct limits limits[] = {
|
||||
#ifdef RLIMIT_CPU
|
||||
{ "time(seconds)", RLIMIT_CPU, 1, 't' },
|
||||
#endif
|
||||
#ifdef RLIMIT_FSIZE
|
||||
{ "file(blocks)", RLIMIT_FSIZE, 512, 'f' },
|
||||
#endif
|
||||
#ifdef RLIMIT_DATA
|
||||
{ "data(kbytes)", RLIMIT_DATA, 1024, 'd' },
|
||||
#endif
|
||||
#ifdef RLIMIT_STACK
|
||||
{ "stack(kbytes)", RLIMIT_STACK, 1024, 's' },
|
||||
#endif
|
||||
#ifdef RLIMIT_CORE
|
||||
{ "coredump(blocks)", RLIMIT_CORE, 512, 'c' },
|
||||
#endif
|
||||
#ifdef RLIMIT_RSS
|
||||
{ "memory(kbytes)", RLIMIT_RSS, 1024, 'm' },
|
||||
#endif
|
||||
#ifdef RLIMIT_MEMLOCK
|
||||
{ "locked memory(kbytes)", RLIMIT_MEMLOCK, 1024, 'l' },
|
||||
#endif
|
||||
#ifdef RLIMIT_NPROC
|
||||
{ "process(processes)", RLIMIT_NPROC, 1, 'p' },
|
||||
#endif
|
||||
#ifdef RLIMIT_NOFILE
|
||||
{ "nofiles(descriptors)", RLIMIT_NOFILE, 1, 'n' },
|
||||
#endif
|
||||
#ifdef RLIMIT_VMEM
|
||||
{ "vmemory(kbytes)", RLIMIT_VMEM, 1024, 'v' },
|
||||
#endif
|
||||
#ifdef RLIMIT_SWAP
|
||||
{ "swap(kbytes)", RLIMIT_SWAP, 1024, 'w' },
|
||||
#endif
|
||||
#ifdef RLIMIT_SBSIZE
|
||||
{ "sbsize(bytes)", RLIMIT_SBSIZE, 1, 'b' },
|
||||
#endif
|
||||
{ (char *) 0, 0, 0, '\0' }
|
||||
};
|
||||
|
||||
int
|
||||
ulimitcmd(int argc, char **argv)
|
||||
{
|
||||
int c;
|
||||
rlim_t val = 0;
|
||||
enum { SOFT = 0x1, HARD = 0x2 }
|
||||
how = SOFT | HARD;
|
||||
const struct limits *l;
|
||||
int set, all = 0;
|
||||
int optc, what;
|
||||
struct rlimit limit;
|
||||
|
||||
what = 'f';
|
||||
while ((optc = nextopt("HSabtfdsmcnpl")) != '\0')
|
||||
switch (optc) {
|
||||
case 'H':
|
||||
how = HARD;
|
||||
break;
|
||||
case 'S':
|
||||
how = SOFT;
|
||||
break;
|
||||
case 'a':
|
||||
all = 1;
|
||||
break;
|
||||
default:
|
||||
what = optc;
|
||||
}
|
||||
|
||||
for (l = limits; l->name && l->option != what; l++)
|
||||
;
|
||||
if (!l->name)
|
||||
error("internal error (%c)", what);
|
||||
|
||||
set = *argptr ? 1 : 0;
|
||||
if (set) {
|
||||
char *p = *argptr;
|
||||
|
||||
if (all || argptr[1])
|
||||
error("too many arguments");
|
||||
if (strcmp(p, "unlimited") == 0)
|
||||
val = RLIM_INFINITY;
|
||||
else {
|
||||
val = (rlim_t) 0;
|
||||
|
||||
while ((c = *p++) >= '0' && c <= '9')
|
||||
{
|
||||
val = (val * 10) + (long)(c - '0');
|
||||
if ((long)val < 0)
|
||||
break;
|
||||
}
|
||||
if (c)
|
||||
error("bad number");
|
||||
val *= l->factor;
|
||||
}
|
||||
}
|
||||
if (all) {
|
||||
for (l = limits; l->name; l++) {
|
||||
getrlimit(l->cmd, &limit);
|
||||
if (how & SOFT)
|
||||
val = limit.rlim_cur;
|
||||
else if (how & HARD)
|
||||
val = limit.rlim_max;
|
||||
|
||||
out1fmt("%-20s ", l->name);
|
||||
if (val == RLIM_INFINITY)
|
||||
out1fmt("unlimited\n");
|
||||
else
|
||||
{
|
||||
val /= l->factor;
|
||||
#ifdef BSD4_4
|
||||
out1fmt("%lld\n", (long long) val);
|
||||
#else
|
||||
out1fmt("%ld\n", (long) val);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
getrlimit(l->cmd, &limit);
|
||||
if (set) {
|
||||
if (how & HARD)
|
||||
limit.rlim_max = val;
|
||||
if (how & SOFT)
|
||||
limit.rlim_cur = val;
|
||||
if (setrlimit(l->cmd, &limit) < 0)
|
||||
error("error setting limit (%s)", strerror(errno));
|
||||
} else {
|
||||
if (how & SOFT)
|
||||
val = limit.rlim_cur;
|
||||
else if (how & HARD)
|
||||
val = limit.rlim_max;
|
||||
|
||||
if (val == RLIM_INFINITY)
|
||||
out1fmt("unlimited\n");
|
||||
else
|
||||
{
|
||||
val /= l->factor;
|
||||
#ifdef BSD4_4
|
||||
out1fmt("%lld\n", (long long) val);
|
||||
#else
|
||||
out1fmt("%ld\n", (long) val);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
|
@ -1,31 +0,0 @@
|
|||
/* $NetBSD: miscbltin.h,v 1.3 2003/08/21 17:57:53 christos Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1997 Christos Zoulas. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
int readcmd(int, char **);
|
||||
int umaskcmd(int, char **);
|
||||
int ulimitcmd(int, char **);
|
||||
136
sh/mkbuiltins
136
sh/mkbuiltins
|
|
@ -1,136 +0,0 @@
|
|||
#!/bin/sh -
|
||||
# $NetBSD: mkbuiltins,v 1.21 2004/06/06 07:03:11 christos Exp $
|
||||
#
|
||||
# Copyright (c) 1991, 1993
|
||||
# The Regents of the University of California. All rights reserved.
|
||||
#
|
||||
# This code is derived from software contributed to Berkeley by
|
||||
# Kenneth Almquist.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions
|
||||
# are met:
|
||||
# 1. Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# 2. Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in the
|
||||
# documentation and/or other materials provided with the distribution.
|
||||
# 3. Neither the name of the University nor the names of its contributors
|
||||
# may be used to endorse or promote products derived from this software
|
||||
# without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
# ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
# SUCH DAMAGE.
|
||||
#
|
||||
# @(#)mkbuiltins 8.2 (Berkeley) 5/4/95
|
||||
|
||||
havehist=1
|
||||
if [ "X$1" = "X-h" ]; then
|
||||
havehist=0
|
||||
shift
|
||||
fi
|
||||
|
||||
shell=$1
|
||||
builtins=$2
|
||||
objdir=$3
|
||||
|
||||
havejobs=0
|
||||
if grep '^#define JOBS[ ]*1' ${shell} > /dev/null
|
||||
then
|
||||
havejobs=1
|
||||
fi
|
||||
|
||||
exec <$builtins 3> ${objdir}/builtins.c 4> ${objdir}/builtins.h
|
||||
|
||||
echo '/*
|
||||
* This file was generated by the mkbuiltins program.
|
||||
*/
|
||||
|
||||
#include "shell.h"
|
||||
#include "builtins.h"
|
||||
|
||||
const struct builtincmd builtincmd[] = {
|
||||
' >&3
|
||||
|
||||
echo '/*
|
||||
* This file was generated by the mkbuiltins program.
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
|
||||
struct builtincmd {
|
||||
const char *name;
|
||||
int (*builtin)(int, char **);
|
||||
};
|
||||
|
||||
extern const struct builtincmd builtincmd[];
|
||||
extern const struct builtincmd splbltincmd[];
|
||||
|
||||
' >&4
|
||||
|
||||
specials=
|
||||
|
||||
while read line
|
||||
do
|
||||
set -- $line
|
||||
[ -z "$1" ] && continue
|
||||
case "$1" in
|
||||
\#if*|\#def*|\#end*)
|
||||
echo $line >&3
|
||||
echo $line >&4
|
||||
continue
|
||||
;;
|
||||
esac
|
||||
l1="${line###}"
|
||||
[ "$l1" != "$line" ] && continue
|
||||
|
||||
|
||||
func=$1
|
||||
shift
|
||||
[ x"$1" = x'-j' ] && {
|
||||
[ $havejobs = 0 ] && continue
|
||||
shift
|
||||
}
|
||||
[ x"$1" = x'-h' ] && {
|
||||
[ $havehist = 0 ] && continue
|
||||
shift
|
||||
}
|
||||
echo 'int '"$func"'(int, char **);' >&4
|
||||
while
|
||||
[ $# != 0 -a "$1" != '#' ]
|
||||
do
|
||||
[ "$1" = '-s' ] && {
|
||||
specials="$specials $2 $func"
|
||||
shift 2
|
||||
continue;
|
||||
}
|
||||
[ "$1" = '-u' ] && shift
|
||||
echo ' { "'$1'", '"$func"' },' >&3
|
||||
shift
|
||||
done
|
||||
done
|
||||
|
||||
echo ' { 0, 0 },' >&3
|
||||
echo '};' >&3
|
||||
echo >&3
|
||||
echo 'const struct builtincmd splbltincmd[] = {' >&3
|
||||
|
||||
set -- $specials
|
||||
while
|
||||
[ $# != 0 ]
|
||||
do
|
||||
echo ' { "'$1'", '"$2"' },' >&3
|
||||
shift 2
|
||||
done
|
||||
|
||||
echo ' { 0, 0 },' >&3
|
||||
echo "};" >&3
|
||||
197
sh/mkinit.sh
197
sh/mkinit.sh
|
|
@ -1,197 +0,0 @@
|
|||
#! /bin/sh
|
||||
# $NetBSD: mkinit.sh,v 1.2 2004/06/15 23:09:54 dsl Exp $
|
||||
|
||||
# Copyright (c) 2003 The NetBSD Foundation, Inc.
|
||||
# All rights reserved.
|
||||
#
|
||||
# This code is derived from software contributed to The NetBSD Foundation
|
||||
# by David Laight.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions
|
||||
# are met:
|
||||
# 1. Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# 2. Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in the
|
||||
# documentation and/or other materials provided with the distribution.
|
||||
# 3. Neither the name of The NetBSD Foundation nor the names of its
|
||||
# contributors may be used to endorse or promote products derived
|
||||
# from this software without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
|
||||
# ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
# TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
|
||||
# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
# POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
srcs="$*"
|
||||
|
||||
nl='
|
||||
'
|
||||
openparen='('
|
||||
backslash='\'
|
||||
|
||||
includes=' "shell.h" "mystring.h" "init.h" '
|
||||
defines=
|
||||
decles=
|
||||
event_init=
|
||||
event_reset=
|
||||
event_shellproc=
|
||||
|
||||
for src in $srcs; do
|
||||
exec <$src
|
||||
decnl="$nl"
|
||||
while IFS=; read -r line; do
|
||||
[ "$line" = x ]
|
||||
case "$line " in
|
||||
INIT["{ "]* ) event=init;;
|
||||
RESET["{ "]* ) event=reset;;
|
||||
SHELLPROC["{ "]* ) event=shellproc;;
|
||||
INCLUDE[\ \ ]* )
|
||||
IFS=' '
|
||||
set -- $line
|
||||
# ignore duplicates
|
||||
[ "${includes}" != "${includes%* $2 }" ] && continue
|
||||
includes="$includes$2 "
|
||||
continue
|
||||
;;
|
||||
MKINIT\ )
|
||||
# struct declaration
|
||||
decles="$decles$nl"
|
||||
while
|
||||
read -r line
|
||||
decles="${decles}${line}${nl}"
|
||||
[ "$line" != "};" ]
|
||||
do
|
||||
:
|
||||
done
|
||||
decnl="$nl"
|
||||
continue
|
||||
;;
|
||||
MKINIT["{ "]* )
|
||||
# strip initialiser
|
||||
def=${line#MKINIT}
|
||||
comment="${def#*;}"
|
||||
def="${def%;$comment}"
|
||||
def="${def%%=*}"
|
||||
def="${def% }"
|
||||
decles="${decles}${decnl}extern${def};${comment}${nl}"
|
||||
decnl=
|
||||
continue
|
||||
;;
|
||||
\#define[\ \ ]* )
|
||||
IFS=' '
|
||||
set -- $line
|
||||
# Ignore those with arguments
|
||||
[ "$2" = "${2##*$openparen}" ] || continue
|
||||
# and multiline definitions
|
||||
[ "$line" = "${line%$backslash}" ] || continue
|
||||
defines="${defines}#undef $2${nl}${line}${nl}"
|
||||
continue
|
||||
;;
|
||||
* ) continue;;
|
||||
esac
|
||||
# code for events
|
||||
ev="${nl} /* from $src: */${nl} {${nl}"
|
||||
while
|
||||
read -r line
|
||||
[ "$line" != "}" ]
|
||||
do
|
||||
# The C program indented by an extra 6 chars using
|
||||
# tabs then spaces. I need to compare the output :-(
|
||||
indent=6
|
||||
while
|
||||
l=${line# }
|
||||
[ "$l" != "$line" ]
|
||||
do
|
||||
indent=$(($indent + 8))
|
||||
line="$l"
|
||||
done
|
||||
while
|
||||
l=${line# }
|
||||
[ "$l" != "$line" ]
|
||||
do
|
||||
indent=$(($indent + 1))
|
||||
line="$l"
|
||||
done
|
||||
[ -z "$line" -o "$line" != "${line###}" ] && indent=0
|
||||
while
|
||||
[ $indent -ge 8 ]
|
||||
do
|
||||
ev="$ev "
|
||||
indent="$(($indent - 8))"
|
||||
done
|
||||
while
|
||||
[ $indent -gt 0 ]
|
||||
do
|
||||
ev="$ev "
|
||||
indent="$(($indent - 1))"
|
||||
done
|
||||
ev="${ev}${line}${nl}"
|
||||
done
|
||||
ev="${ev} }${nl}"
|
||||
eval event_$event=\"\$event_$event\$ev\"
|
||||
done
|
||||
done
|
||||
|
||||
exec >init.c.tmp
|
||||
|
||||
echo "/*"
|
||||
echo " * This file was generated by the mkinit program."
|
||||
echo " */"
|
||||
echo
|
||||
|
||||
IFS=' '
|
||||
for f in $includes; do
|
||||
echo "#include $f"
|
||||
done
|
||||
|
||||
echo
|
||||
echo
|
||||
echo
|
||||
echo "$defines"
|
||||
echo
|
||||
echo "$decles"
|
||||
echo
|
||||
echo
|
||||
echo "/*"
|
||||
echo " * Initialization code."
|
||||
echo " */"
|
||||
echo
|
||||
echo "void"
|
||||
echo "init() {"
|
||||
echo "${event_init%$nl}"
|
||||
echo "}"
|
||||
echo
|
||||
echo
|
||||
echo
|
||||
echo "/*"
|
||||
echo " * This routine is called when an error or an interrupt occurs in an"
|
||||
echo " * interactive shell and control is returned to the main command loop."
|
||||
echo " */"
|
||||
echo
|
||||
echo "void"
|
||||
echo "reset() {"
|
||||
echo "${event_reset%$nl}"
|
||||
echo "}"
|
||||
echo
|
||||
echo
|
||||
echo
|
||||
echo "/*"
|
||||
echo " * This routine is called to initialize the shell to run a shell procedure."
|
||||
echo " */"
|
||||
echo
|
||||
echo "void"
|
||||
echo "initshellproc() {"
|
||||
echo "${event_shellproc%$nl}"
|
||||
echo "}"
|
||||
|
||||
exec >&-
|
||||
mv init.c.tmp init.c
|
||||
217
sh/mknodes.sh
217
sh/mknodes.sh
|
|
@ -1,217 +0,0 @@
|
|||
#! /bin/sh
|
||||
# $NetBSD: mknodes.sh,v 1.1 2004/01/16 23:24:38 dsl Exp $
|
||||
|
||||
# Copyright (c) 2003 The NetBSD Foundation, Inc.
|
||||
# All rights reserved.
|
||||
#
|
||||
# This code is derived from software contributed to The NetBSD Foundation
|
||||
# by David Laight.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions
|
||||
# are met:
|
||||
# 1. Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# 2. Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in the
|
||||
# documentation and/or other materials provided with the distribution.
|
||||
# 3. Neither the name of The NetBSD Foundation nor the names of its
|
||||
# contributors may be used to endorse or promote products derived
|
||||
# from this software without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
|
||||
# ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
# TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
|
||||
# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
# POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
nodetypes=$1
|
||||
nodes_pat=$2
|
||||
objdir="$3"
|
||||
|
||||
exec <$nodetypes
|
||||
exec >$objdir/nodes.h.tmp
|
||||
|
||||
echo "/*"
|
||||
echo " * This file was generated by mknodes.sh"
|
||||
echo " */"
|
||||
echo
|
||||
|
||||
tagno=0
|
||||
while IFS=; read -r line; do
|
||||
line="${line%%#*}"
|
||||
IFS=' '
|
||||
set -- $line
|
||||
IFS=
|
||||
[ -z "$2" ] && continue
|
||||
case "$line" in
|
||||
[" "]* )
|
||||
IFS=' '
|
||||
[ $field = 0 ] && struct_list="$struct_list $struct"
|
||||
eval field_${struct}_$field=\"\$*\"
|
||||
eval numfld_$struct=\$field
|
||||
field=$(($field + 1))
|
||||
;;
|
||||
* )
|
||||
define=$1
|
||||
struct=$2
|
||||
echo "#define $define $tagno"
|
||||
tagno=$(($tagno + 1))
|
||||
eval define_$struct=\"\$define_$struct \$define\"
|
||||
struct_define="$struct_define $struct"
|
||||
field=0
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
echo
|
||||
|
||||
IFS=' '
|
||||
for struct in $struct_list; do
|
||||
echo
|
||||
echo
|
||||
echo "struct $struct {"
|
||||
field=0
|
||||
while
|
||||
eval line=\"\$field_${struct}_$field\"
|
||||
field=$(($field + 1))
|
||||
[ -n "$line" ]
|
||||
do
|
||||
IFS=' '
|
||||
set -- $line
|
||||
name=$1
|
||||
case $2 in
|
||||
nodeptr ) type="union node *";;
|
||||
nodelist ) type="struct nodelist *";;
|
||||
string ) type="char *";;
|
||||
int ) type="int ";;
|
||||
* ) name=; shift 2; type="$*";;
|
||||
esac
|
||||
echo " $type$name;"
|
||||
done
|
||||
echo "};"
|
||||
done
|
||||
|
||||
echo
|
||||
echo
|
||||
echo "union node {"
|
||||
echo " int type;"
|
||||
for struct in $struct_list; do
|
||||
echo " struct $struct $struct;"
|
||||
done
|
||||
echo "};"
|
||||
echo
|
||||
echo
|
||||
echo "struct nodelist {"
|
||||
echo " struct nodelist *next;"
|
||||
echo " union node *n;"
|
||||
echo "};"
|
||||
echo
|
||||
echo
|
||||
echo "union node *copyfunc(union node *);"
|
||||
echo "void freefunc(union node *);"
|
||||
|
||||
mv $objdir/nodes.h.tmp $objdir/nodes.h || exit 1
|
||||
|
||||
exec <$nodes_pat
|
||||
exec >$objdir/nodes.c.tmp
|
||||
|
||||
echo "/*"
|
||||
echo " * This file was generated by mknodes.sh"
|
||||
echo " */"
|
||||
echo
|
||||
|
||||
while IFS=; read -r line; do
|
||||
IFS=' '
|
||||
set -- $line
|
||||
IFS=
|
||||
case "$1" in
|
||||
'%SIZES' )
|
||||
echo "static const short nodesize[$tagno] = {"
|
||||
IFS=' '
|
||||
for struct in $struct_define; do
|
||||
echo " SHELL_ALIGN(sizeof (struct $struct)),"
|
||||
done
|
||||
echo "};"
|
||||
;;
|
||||
'%CALCSIZE' )
|
||||
echo " if (n == NULL)"
|
||||
echo " return;"
|
||||
echo " funcblocksize += nodesize[n->type];"
|
||||
echo " switch (n->type) {"
|
||||
IFS=' '
|
||||
for struct in $struct_list; do
|
||||
eval defines=\"\$define_$struct\"
|
||||
for define in $defines; do
|
||||
echo " case $define:"
|
||||
done
|
||||
eval field=\$numfld_$struct
|
||||
while
|
||||
[ $field != 0 ]
|
||||
do
|
||||
eval line=\"\$field_${struct}_$field\"
|
||||
field=$(($field - 1))
|
||||
IFS=' '
|
||||
set -- $line
|
||||
name=$1
|
||||
cl=")"
|
||||
case $2 in
|
||||
nodeptr ) fn=calcsize;;
|
||||
nodelist ) fn=sizenodelist;;
|
||||
string ) fn="funcstringsize += strlen"
|
||||
cl=") + 1";;
|
||||
* ) continue;;
|
||||
esac
|
||||
echo " ${fn}(n->$struct.$name${cl};"
|
||||
done
|
||||
echo " break;"
|
||||
done
|
||||
echo " };"
|
||||
;;
|
||||
'%COPY' )
|
||||
echo " if (n == NULL)"
|
||||
echo " return NULL;"
|
||||
echo " new = funcblock;"
|
||||
echo " funcblock = (char *) funcblock + nodesize[n->type];"
|
||||
echo " switch (n->type) {"
|
||||
IFS=' '
|
||||
for struct in $struct_list; do
|
||||
eval defines=\"\$define_$struct\"
|
||||
for define in $defines; do
|
||||
echo " case $define:"
|
||||
done
|
||||
eval field=\$numfld_$struct
|
||||
while
|
||||
[ $field != 0 ]
|
||||
do
|
||||
eval line=\"\$field_${struct}_$field\"
|
||||
field=$(($field - 1))
|
||||
IFS=' '
|
||||
set -- $line
|
||||
name=$1
|
||||
case $2 in
|
||||
nodeptr ) fn="copynode(";;
|
||||
nodelist ) fn="copynodelist(";;
|
||||
string ) fn="nodesavestr(";;
|
||||
int ) fn=;;
|
||||
* ) continue;;
|
||||
esac
|
||||
f="$struct.$name"
|
||||
echo " new->$f = ${fn}n->$f${fn:+)};"
|
||||
done
|
||||
echo " break;"
|
||||
done
|
||||
echo " };"
|
||||
echo " new->type = n->type;"
|
||||
;;
|
||||
* ) echo "$line";;
|
||||
esac
|
||||
done
|
||||
|
||||
mv $objdir/nodes.c.tmp $objdir/nodes.c || exit 1
|
||||
92
sh/mktokens
92
sh/mktokens
|
|
@ -1,92 +0,0 @@
|
|||
#!/bin/sh -
|
||||
# $NetBSD: mktokens,v 1.10 2003/08/22 11:22:23 agc Exp $
|
||||
#
|
||||
# Copyright (c) 1991, 1993
|
||||
# The Regents of the University of California. All rights reserved.
|
||||
#
|
||||
# This code is derived from software contributed to Berkeley by
|
||||
# Kenneth Almquist.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions
|
||||
# are met:
|
||||
# 1. Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# 2. Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in the
|
||||
# documentation and/or other materials provided with the distribution.
|
||||
# 3. Neither the name of the University nor the names of its contributors
|
||||
# may be used to endorse or promote products derived from this software
|
||||
# without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
# ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
# SUCH DAMAGE.
|
||||
#
|
||||
# @(#)mktokens 8.1 (Berkeley) 5/31/93
|
||||
|
||||
# The following is a list of tokens. The second column is nonzero if the
|
||||
# token marks the end of a list. The third column is the name to print in
|
||||
# error messages.
|
||||
|
||||
cat > /tmp/ka$$ <<\!
|
||||
TEOF 1 end of file
|
||||
TNL 0 newline
|
||||
TSEMI 0 ";"
|
||||
TBACKGND 0 "&"
|
||||
TAND 0 "&&"
|
||||
TOR 0 "||"
|
||||
TPIPE 0 "|"
|
||||
TLP 0 "("
|
||||
TRP 1 ")"
|
||||
TENDCASE 1 ";;"
|
||||
TENDBQUOTE 1 "`"
|
||||
TREDIR 0 redirection
|
||||
TWORD 0 word
|
||||
TIF 0 "if"
|
||||
TTHEN 1 "then"
|
||||
TELSE 1 "else"
|
||||
TELIF 1 "elif"
|
||||
TFI 1 "fi"
|
||||
TWHILE 0 "while"
|
||||
TUNTIL 0 "until"
|
||||
TFOR 0 "for"
|
||||
TDO 1 "do"
|
||||
TDONE 1 "done"
|
||||
TBEGIN 0 "{"
|
||||
TEND 1 "}"
|
||||
TCASE 0 "case"
|
||||
TESAC 1 "esac"
|
||||
TNOT 0 "!"
|
||||
!
|
||||
nl=`wc -l /tmp/ka$$`
|
||||
exec > token.h
|
||||
awk '{print "#define " $1 " " NR-1}' /tmp/ka$$
|
||||
echo '
|
||||
/* Array indicating which tokens mark the end of a list */
|
||||
const char tokendlist[] = {'
|
||||
awk '{print "\t" $2 ","}' /tmp/ka$$
|
||||
echo '};
|
||||
|
||||
const char *const tokname[] = {'
|
||||
sed -e 's/"/\\"/g' \
|
||||
-e 's/[^ ]*[ ][ ]*[^ ]*[ ][ ]*\(.*\)/ "\1",/' \
|
||||
/tmp/ka$$
|
||||
echo '};
|
||||
'
|
||||
sed 's/"//g' /tmp/ka$$ | awk '
|
||||
/TIF/{print "#define KWDOFFSET " NR-1; print "";
|
||||
print "const char *const parsekwd[] = {"}
|
||||
/TIF/,/neverfound/{print " \"" $3 "\","}'
|
||||
echo ' 0
|
||||
};'
|
||||
|
||||
rm /tmp/ka$$
|
||||
|
|
@ -1,49 +0,0 @@
|
|||
/* $NetBSD: myhistedit.h,v 1.10 2003/08/07 09:05:35 agc Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)myhistedit.h 8.2 (Berkeley) 5/4/95
|
||||
*/
|
||||
|
||||
#ifdef WITH_HISTORY
|
||||
#include <histedit.h>
|
||||
|
||||
extern History *hist;
|
||||
extern EditLine *el;
|
||||
extern int displayhist;
|
||||
|
||||
void histedit(void);
|
||||
void sethistsize(const char *);
|
||||
void setterm(const char *);
|
||||
int histcmd(int, char **);
|
||||
int inputrc(int, char **);
|
||||
int not_fcnumber(char *);
|
||||
int str_to_event(const char *, int);
|
||||
#endif
|
||||
|
||||
133
sh/mystring.c
133
sh/mystring.c
|
|
@ -1,133 +0,0 @@
|
|||
/* $NetBSD: mystring.c,v 1.16 2003/08/07 09:05:35 agc Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1991, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to Berkeley by
|
||||
* Kenneth Almquist.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
#ifndef lint
|
||||
#if 0
|
||||
static char sccsid[] = "@(#)mystring.c 8.2 (Berkeley) 5/4/95";
|
||||
#else
|
||||
__RCSID("$NetBSD: mystring.c,v 1.16 2003/08/07 09:05:35 agc Exp $");
|
||||
#endif
|
||||
#endif /* not lint */
|
||||
|
||||
/*
|
||||
* String functions.
|
||||
*
|
||||
* equal(s1, s2) Return true if strings are equal.
|
||||
* scopy(from, to) Copy a string.
|
||||
* scopyn(from, to, n) Like scopy, but checks for overflow.
|
||||
* number(s) Convert a string of digits to an integer.
|
||||
* is_number(s) Return true if s is a string of digits.
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include "shell.h"
|
||||
#include "syntax.h"
|
||||
#include "error.h"
|
||||
#include "mystring.h"
|
||||
|
||||
|
||||
char nullstr[1]; /* zero length string */
|
||||
|
||||
/*
|
||||
* equal - #defined in mystring.h
|
||||
*/
|
||||
|
||||
/*
|
||||
* scopy - #defined in mystring.h
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
* scopyn - copy a string from "from" to "to", truncating the string
|
||||
* if necessary. "To" is always nul terminated, even if
|
||||
* truncation is performed. "Size" is the size of "to".
|
||||
*/
|
||||
|
||||
void
|
||||
scopyn(const char *from, char *to, int size)
|
||||
{
|
||||
|
||||
while (--size > 0) {
|
||||
if ((*to++ = *from++) == '\0')
|
||||
return;
|
||||
}
|
||||
*to = '\0';
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* prefix -- see if pfx is a prefix of string.
|
||||
*/
|
||||
|
||||
int
|
||||
prefix(const char *pfx, const char *string)
|
||||
{
|
||||
while (*pfx) {
|
||||
if (*pfx++ != *string++)
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Convert a string of digits to an integer, printing an error message on
|
||||
* failure.
|
||||
*/
|
||||
|
||||
int
|
||||
number(const char *s)
|
||||
{
|
||||
|
||||
if (! is_number(s))
|
||||
error("Illegal number: %s", s);
|
||||
return atoi(s);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Check for a valid number. This should be elsewhere.
|
||||
*/
|
||||
|
||||
int
|
||||
is_number(const char *p)
|
||||
{
|
||||
do {
|
||||
if (! is_digit(*p))
|
||||
return 0;
|
||||
} while (*++p != '\0');
|
||||
return 1;
|
||||
}
|
||||
|
|
@ -1,45 +0,0 @@
|
|||
/* $NetBSD: mystring.h,v 1.11 2003/08/07 09:05:35 agc Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1991, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to Berkeley by
|
||||
* Kenneth Almquist.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)mystring.h 8.2 (Berkeley) 5/4/95
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
|
||||
void scopyn(const char *, char *, int);
|
||||
int prefix(const char *, const char *);
|
||||
int number(const char *);
|
||||
int is_number(const char *);
|
||||
|
||||
#define equal(s1, s2) (strcmp(s1, s2) == 0)
|
||||
#define scopy(s1, s2) ((void)strcpy(s2, s1))
|
||||
347
sh/nodes.c
347
sh/nodes.c
|
|
@ -1,347 +0,0 @@
|
|||
/*
|
||||
* This file was generated by mknodes.sh
|
||||
*/
|
||||
|
||||
/* $NetBSD: nodes.c.pat,v 1.12 2004/06/15 22:57:27 dsl Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1991, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to Berkeley by
|
||||
* Kenneth Almquist.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)nodes.c.pat 8.2 (Berkeley) 5/4/95
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
/*
|
||||
* Routine for dealing with parsed shell commands.
|
||||
*/
|
||||
|
||||
#include "shell.h"
|
||||
#include "nodes.h"
|
||||
#include "memalloc.h"
|
||||
#include "machdep.h"
|
||||
#include "mystring.h"
|
||||
|
||||
|
||||
int funcblocksize; /* size of structures in function */
|
||||
int funcstringsize; /* size of strings in node */
|
||||
pointer funcblock; /* block to allocate function from */
|
||||
char *funcstring; /* block to allocate strings from */
|
||||
|
||||
static const short nodesize[26] = {
|
||||
SHELL_ALIGN(sizeof (struct nbinary)),
|
||||
SHELL_ALIGN(sizeof (struct ncmd)),
|
||||
SHELL_ALIGN(sizeof (struct npipe)),
|
||||
SHELL_ALIGN(sizeof (struct nredir)),
|
||||
SHELL_ALIGN(sizeof (struct nredir)),
|
||||
SHELL_ALIGN(sizeof (struct nredir)),
|
||||
SHELL_ALIGN(sizeof (struct nbinary)),
|
||||
SHELL_ALIGN(sizeof (struct nbinary)),
|
||||
SHELL_ALIGN(sizeof (struct nif)),
|
||||
SHELL_ALIGN(sizeof (struct nbinary)),
|
||||
SHELL_ALIGN(sizeof (struct nbinary)),
|
||||
SHELL_ALIGN(sizeof (struct nfor)),
|
||||
SHELL_ALIGN(sizeof (struct ncase)),
|
||||
SHELL_ALIGN(sizeof (struct nclist)),
|
||||
SHELL_ALIGN(sizeof (struct narg)),
|
||||
SHELL_ALIGN(sizeof (struct narg)),
|
||||
SHELL_ALIGN(sizeof (struct nfile)),
|
||||
SHELL_ALIGN(sizeof (struct nfile)),
|
||||
SHELL_ALIGN(sizeof (struct nfile)),
|
||||
SHELL_ALIGN(sizeof (struct nfile)),
|
||||
SHELL_ALIGN(sizeof (struct nfile)),
|
||||
SHELL_ALIGN(sizeof (struct ndup)),
|
||||
SHELL_ALIGN(sizeof (struct ndup)),
|
||||
SHELL_ALIGN(sizeof (struct nhere)),
|
||||
SHELL_ALIGN(sizeof (struct nhere)),
|
||||
SHELL_ALIGN(sizeof (struct nnot)),
|
||||
};
|
||||
|
||||
|
||||
STATIC void calcsize(union node *);
|
||||
STATIC void sizenodelist(struct nodelist *);
|
||||
STATIC union node *copynode(union node *);
|
||||
STATIC struct nodelist *copynodelist(struct nodelist *);
|
||||
STATIC char *nodesavestr(char *);
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Make a copy of a parse tree.
|
||||
*/
|
||||
|
||||
union node *
|
||||
copyfunc(n)
|
||||
union node *n;
|
||||
{
|
||||
if (n == NULL)
|
||||
return NULL;
|
||||
funcblocksize = 0;
|
||||
funcstringsize = 0;
|
||||
calcsize(n);
|
||||
funcblock = ckmalloc(funcblocksize + funcstringsize);
|
||||
funcstring = (char *) funcblock + funcblocksize;
|
||||
return copynode(n);
|
||||
}
|
||||
|
||||
|
||||
|
||||
STATIC void
|
||||
calcsize(n)
|
||||
union node *n;
|
||||
{
|
||||
if (n == NULL)
|
||||
return;
|
||||
funcblocksize += nodesize[n->type];
|
||||
switch (n->type) {
|
||||
case NSEMI:
|
||||
case NAND:
|
||||
case NOR:
|
||||
case NWHILE:
|
||||
case NUNTIL:
|
||||
calcsize(n->nbinary.ch2);
|
||||
calcsize(n->nbinary.ch1);
|
||||
break;
|
||||
case NCMD:
|
||||
calcsize(n->ncmd.redirect);
|
||||
calcsize(n->ncmd.args);
|
||||
break;
|
||||
case NPIPE:
|
||||
sizenodelist(n->npipe.cmdlist);
|
||||
break;
|
||||
case NREDIR:
|
||||
case NBACKGND:
|
||||
case NSUBSHELL:
|
||||
calcsize(n->nredir.redirect);
|
||||
calcsize(n->nredir.n);
|
||||
break;
|
||||
case NIF:
|
||||
calcsize(n->nif.elsepart);
|
||||
calcsize(n->nif.ifpart);
|
||||
calcsize(n->nif.test);
|
||||
break;
|
||||
case NFOR:
|
||||
funcstringsize += strlen(n->nfor.var) + 1;
|
||||
calcsize(n->nfor.body);
|
||||
calcsize(n->nfor.args);
|
||||
break;
|
||||
case NCASE:
|
||||
calcsize(n->ncase.cases);
|
||||
calcsize(n->ncase.expr);
|
||||
break;
|
||||
case NCLIST:
|
||||
calcsize(n->nclist.body);
|
||||
calcsize(n->nclist.pattern);
|
||||
calcsize(n->nclist.next);
|
||||
break;
|
||||
case NDEFUN:
|
||||
case NARG:
|
||||
sizenodelist(n->narg.backquote);
|
||||
funcstringsize += strlen(n->narg.text) + 1;
|
||||
calcsize(n->narg.next);
|
||||
break;
|
||||
case NTO:
|
||||
case NCLOBBER:
|
||||
case NFROM:
|
||||
case NFROMTO:
|
||||
case NAPPEND:
|
||||
calcsize(n->nfile.fname);
|
||||
calcsize(n->nfile.next);
|
||||
break;
|
||||
case NTOFD:
|
||||
case NFROMFD:
|
||||
calcsize(n->ndup.vname);
|
||||
calcsize(n->ndup.next);
|
||||
break;
|
||||
case NHERE:
|
||||
case NXHERE:
|
||||
calcsize(n->nhere.doc);
|
||||
calcsize(n->nhere.next);
|
||||
break;
|
||||
case NNOT:
|
||||
calcsize(n->nnot.com);
|
||||
break;
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
|
||||
STATIC void
|
||||
sizenodelist(lp)
|
||||
struct nodelist *lp;
|
||||
{
|
||||
while (lp) {
|
||||
funcblocksize += SHELL_ALIGN(sizeof(struct nodelist));
|
||||
calcsize(lp->n);
|
||||
lp = lp->next;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
STATIC union node *
|
||||
copynode(n)
|
||||
union node *n;
|
||||
{
|
||||
union node *new;
|
||||
|
||||
if (n == NULL)
|
||||
return NULL;
|
||||
new = funcblock;
|
||||
funcblock = (char *) funcblock + nodesize[n->type];
|
||||
switch (n->type) {
|
||||
case NSEMI:
|
||||
case NAND:
|
||||
case NOR:
|
||||
case NWHILE:
|
||||
case NUNTIL:
|
||||
new->nbinary.ch2 = copynode(n->nbinary.ch2);
|
||||
new->nbinary.ch1 = copynode(n->nbinary.ch1);
|
||||
break;
|
||||
case NCMD:
|
||||
new->ncmd.redirect = copynode(n->ncmd.redirect);
|
||||
new->ncmd.args = copynode(n->ncmd.args);
|
||||
new->ncmd.backgnd = n->ncmd.backgnd;
|
||||
break;
|
||||
case NPIPE:
|
||||
new->npipe.cmdlist = copynodelist(n->npipe.cmdlist);
|
||||
new->npipe.backgnd = n->npipe.backgnd;
|
||||
break;
|
||||
case NREDIR:
|
||||
case NBACKGND:
|
||||
case NSUBSHELL:
|
||||
new->nredir.redirect = copynode(n->nredir.redirect);
|
||||
new->nredir.n = copynode(n->nredir.n);
|
||||
break;
|
||||
case NIF:
|
||||
new->nif.elsepart = copynode(n->nif.elsepart);
|
||||
new->nif.ifpart = copynode(n->nif.ifpart);
|
||||
new->nif.test = copynode(n->nif.test);
|
||||
break;
|
||||
case NFOR:
|
||||
new->nfor.var = nodesavestr(n->nfor.var);
|
||||
new->nfor.body = copynode(n->nfor.body);
|
||||
new->nfor.args = copynode(n->nfor.args);
|
||||
break;
|
||||
case NCASE:
|
||||
new->ncase.cases = copynode(n->ncase.cases);
|
||||
new->ncase.expr = copynode(n->ncase.expr);
|
||||
break;
|
||||
case NCLIST:
|
||||
new->nclist.body = copynode(n->nclist.body);
|
||||
new->nclist.pattern = copynode(n->nclist.pattern);
|
||||
new->nclist.next = copynode(n->nclist.next);
|
||||
break;
|
||||
case NDEFUN:
|
||||
case NARG:
|
||||
new->narg.backquote = copynodelist(n->narg.backquote);
|
||||
new->narg.text = nodesavestr(n->narg.text);
|
||||
new->narg.next = copynode(n->narg.next);
|
||||
break;
|
||||
case NTO:
|
||||
case NCLOBBER:
|
||||
case NFROM:
|
||||
case NFROMTO:
|
||||
case NAPPEND:
|
||||
new->nfile.fname = copynode(n->nfile.fname);
|
||||
new->nfile.fd = n->nfile.fd;
|
||||
new->nfile.next = copynode(n->nfile.next);
|
||||
break;
|
||||
case NTOFD:
|
||||
case NFROMFD:
|
||||
new->ndup.vname = copynode(n->ndup.vname);
|
||||
new->ndup.dupfd = n->ndup.dupfd;
|
||||
new->ndup.fd = n->ndup.fd;
|
||||
new->ndup.next = copynode(n->ndup.next);
|
||||
break;
|
||||
case NHERE:
|
||||
case NXHERE:
|
||||
new->nhere.doc = copynode(n->nhere.doc);
|
||||
new->nhere.fd = n->nhere.fd;
|
||||
new->nhere.next = copynode(n->nhere.next);
|
||||
break;
|
||||
case NNOT:
|
||||
new->nnot.com = copynode(n->nnot.com);
|
||||
break;
|
||||
};
|
||||
new->type = n->type;
|
||||
return new;
|
||||
}
|
||||
|
||||
|
||||
STATIC struct nodelist *
|
||||
copynodelist(lp)
|
||||
struct nodelist *lp;
|
||||
{
|
||||
struct nodelist *start;
|
||||
struct nodelist **lpp;
|
||||
|
||||
lpp = &start;
|
||||
while (lp) {
|
||||
*lpp = funcblock;
|
||||
funcblock = (char *) funcblock +
|
||||
SHELL_ALIGN(sizeof(struct nodelist));
|
||||
(*lpp)->n = copynode(lp->n);
|
||||
lp = lp->next;
|
||||
lpp = &(*lpp)->next;
|
||||
}
|
||||
*lpp = NULL;
|
||||
return start;
|
||||
}
|
||||
|
||||
|
||||
|
||||
STATIC char *
|
||||
nodesavestr(s)
|
||||
char *s;
|
||||
{
|
||||
register char *p = s;
|
||||
register char *q = funcstring;
|
||||
char *rtn = funcstring;
|
||||
|
||||
while ((*q++ = *p++) != 0)
|
||||
continue;
|
||||
funcstring = q;
|
||||
return rtn;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Free a parse tree.
|
||||
*/
|
||||
|
||||
void
|
||||
freefunc(n)
|
||||
union node *n;
|
||||
{
|
||||
if (n)
|
||||
ckfree(n);
|
||||
}
|
||||
166
sh/nodes.c.pat
166
sh/nodes.c.pat
|
|
@ -1,166 +0,0 @@
|
|||
/* $NetBSD: nodes.c.pat,v 1.12 2004/06/15 22:57:27 dsl Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1991, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to Berkeley by
|
||||
* Kenneth Almquist.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)nodes.c.pat 8.2 (Berkeley) 5/4/95
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
/*
|
||||
* Routine for dealing with parsed shell commands.
|
||||
*/
|
||||
|
||||
#include "shell.h"
|
||||
#include "nodes.h"
|
||||
#include "memalloc.h"
|
||||
#include "machdep.h"
|
||||
#include "mystring.h"
|
||||
|
||||
|
||||
int funcblocksize; /* size of structures in function */
|
||||
int funcstringsize; /* size of strings in node */
|
||||
pointer funcblock; /* block to allocate function from */
|
||||
char *funcstring; /* block to allocate strings from */
|
||||
|
||||
%SIZES
|
||||
|
||||
|
||||
STATIC void calcsize(union node *);
|
||||
STATIC void sizenodelist(struct nodelist *);
|
||||
STATIC union node *copynode(union node *);
|
||||
STATIC struct nodelist *copynodelist(struct nodelist *);
|
||||
STATIC char *nodesavestr(char *);
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Make a copy of a parse tree.
|
||||
*/
|
||||
|
||||
union node *
|
||||
copyfunc(n)
|
||||
union node *n;
|
||||
{
|
||||
if (n == NULL)
|
||||
return NULL;
|
||||
funcblocksize = 0;
|
||||
funcstringsize = 0;
|
||||
calcsize(n);
|
||||
funcblock = ckmalloc(funcblocksize + funcstringsize);
|
||||
funcstring = (char *) funcblock + funcblocksize;
|
||||
return copynode(n);
|
||||
}
|
||||
|
||||
|
||||
|
||||
STATIC void
|
||||
calcsize(n)
|
||||
union node *n;
|
||||
{
|
||||
%CALCSIZE
|
||||
}
|
||||
|
||||
|
||||
|
||||
STATIC void
|
||||
sizenodelist(lp)
|
||||
struct nodelist *lp;
|
||||
{
|
||||
while (lp) {
|
||||
funcblocksize += SHELL_ALIGN(sizeof(struct nodelist));
|
||||
calcsize(lp->n);
|
||||
lp = lp->next;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
STATIC union node *
|
||||
copynode(n)
|
||||
union node *n;
|
||||
{
|
||||
union node *new;
|
||||
|
||||
%COPY
|
||||
return new;
|
||||
}
|
||||
|
||||
|
||||
STATIC struct nodelist *
|
||||
copynodelist(lp)
|
||||
struct nodelist *lp;
|
||||
{
|
||||
struct nodelist *start;
|
||||
struct nodelist **lpp;
|
||||
|
||||
lpp = &start;
|
||||
while (lp) {
|
||||
*lpp = funcblock;
|
||||
funcblock = (char *) funcblock +
|
||||
SHELL_ALIGN(sizeof(struct nodelist));
|
||||
(*lpp)->n = copynode(lp->n);
|
||||
lp = lp->next;
|
||||
lpp = &(*lpp)->next;
|
||||
}
|
||||
*lpp = NULL;
|
||||
return start;
|
||||
}
|
||||
|
||||
|
||||
|
||||
STATIC char *
|
||||
nodesavestr(s)
|
||||
char *s;
|
||||
{
|
||||
register char *p = s;
|
||||
register char *q = funcstring;
|
||||
char *rtn = funcstring;
|
||||
|
||||
while ((*q++ = *p++) != 0)
|
||||
continue;
|
||||
funcstring = q;
|
||||
return rtn;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Free a parse tree.
|
||||
*/
|
||||
|
||||
void
|
||||
freefunc(n)
|
||||
union node *n;
|
||||
{
|
||||
if (n)
|
||||
ckfree(n);
|
||||
}
|
||||
159
sh/nodes.h
159
sh/nodes.h
|
|
@ -1,159 +0,0 @@
|
|||
/*
|
||||
* This file was generated by mknodes.sh
|
||||
*/
|
||||
|
||||
#define NSEMI 0
|
||||
#define NCMD 1
|
||||
#define NPIPE 2
|
||||
#define NREDIR 3
|
||||
#define NBACKGND 4
|
||||
#define NSUBSHELL 5
|
||||
#define NAND 6
|
||||
#define NOR 7
|
||||
#define NIF 8
|
||||
#define NWHILE 9
|
||||
#define NUNTIL 10
|
||||
#define NFOR 11
|
||||
#define NCASE 12
|
||||
#define NCLIST 13
|
||||
#define NDEFUN 14
|
||||
#define NARG 15
|
||||
#define NTO 16
|
||||
#define NCLOBBER 17
|
||||
#define NFROM 18
|
||||
#define NFROMTO 19
|
||||
#define NAPPEND 20
|
||||
#define NTOFD 21
|
||||
#define NFROMFD 22
|
||||
#define NHERE 23
|
||||
#define NXHERE 24
|
||||
#define NNOT 25
|
||||
|
||||
|
||||
|
||||
struct nbinary {
|
||||
int type;
|
||||
union node *ch1;
|
||||
union node *ch2;
|
||||
};
|
||||
|
||||
|
||||
struct ncmd {
|
||||
int type;
|
||||
int backgnd;
|
||||
union node *args;
|
||||
union node *redirect;
|
||||
};
|
||||
|
||||
|
||||
struct npipe {
|
||||
int type;
|
||||
int backgnd;
|
||||
struct nodelist *cmdlist;
|
||||
};
|
||||
|
||||
|
||||
struct nredir {
|
||||
int type;
|
||||
union node *n;
|
||||
union node *redirect;
|
||||
};
|
||||
|
||||
|
||||
struct nif {
|
||||
int type;
|
||||
union node *test;
|
||||
union node *ifpart;
|
||||
union node *elsepart;
|
||||
};
|
||||
|
||||
|
||||
struct nfor {
|
||||
int type;
|
||||
union node *args;
|
||||
union node *body;
|
||||
char *var;
|
||||
};
|
||||
|
||||
|
||||
struct ncase {
|
||||
int type;
|
||||
union node *expr;
|
||||
union node *cases;
|
||||
};
|
||||
|
||||
|
||||
struct nclist {
|
||||
int type;
|
||||
union node *next;
|
||||
union node *pattern;
|
||||
union node *body;
|
||||
};
|
||||
|
||||
|
||||
struct narg {
|
||||
int type;
|
||||
union node *next;
|
||||
char *text;
|
||||
struct nodelist *backquote;
|
||||
};
|
||||
|
||||
|
||||
struct nfile {
|
||||
int type;
|
||||
union node *next;
|
||||
int fd;
|
||||
union node *fname;
|
||||
char *expfname;
|
||||
};
|
||||
|
||||
|
||||
struct ndup {
|
||||
int type;
|
||||
union node *next;
|
||||
int fd;
|
||||
int dupfd;
|
||||
union node *vname;
|
||||
};
|
||||
|
||||
|
||||
struct nhere {
|
||||
int type;
|
||||
union node *next;
|
||||
int fd;
|
||||
union node *doc;
|
||||
};
|
||||
|
||||
|
||||
struct nnot {
|
||||
int type;
|
||||
union node *com;
|
||||
};
|
||||
|
||||
|
||||
union node {
|
||||
int type;
|
||||
struct nbinary nbinary;
|
||||
struct ncmd ncmd;
|
||||
struct npipe npipe;
|
||||
struct nredir nredir;
|
||||
struct nif nif;
|
||||
struct nfor nfor;
|
||||
struct ncase ncase;
|
||||
struct nclist nclist;
|
||||
struct narg narg;
|
||||
struct nfile nfile;
|
||||
struct ndup ndup;
|
||||
struct nhere nhere;
|
||||
struct nnot nnot;
|
||||
};
|
||||
|
||||
|
||||
struct nodelist {
|
||||
struct nodelist *next;
|
||||
union node *n;
|
||||
};
|
||||
|
||||
|
||||
union node *copyfunc(union node *);
|
||||
void freefunc(union node *);
|
||||
143
sh/nodetypes
143
sh/nodetypes
|
|
@ -1,143 +0,0 @@
|
|||
# $NetBSD: nodetypes,v 1.12 2003/08/22 11:22:23 agc Exp $
|
||||
# Copyright (c) 1991, 1993
|
||||
# The Regents of the University of California. All rights reserved.
|
||||
#
|
||||
# This code is derived from software contributed to Berkeley by
|
||||
# Kenneth Almquist.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions
|
||||
# are met:
|
||||
# 1. Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# 2. Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in the
|
||||
# documentation and/or other materials provided with the distribution.
|
||||
# 3. Neither the name of the University nor the names of its contributors
|
||||
# may be used to endorse or promote products derived from this software
|
||||
# without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
# ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
# SUCH DAMAGE.
|
||||
#
|
||||
# @(#)nodetypes 8.2 (Berkeley) 5/4/95
|
||||
|
||||
# This file describes the nodes used in parse trees. Unindented lines
|
||||
# contain a node type followed by a structure tag. Subsequent indented
|
||||
# lines specify the fields of the structure. Several node types can share
|
||||
# the same structure, in which case the fields of the structure should be
|
||||
# specified only once.
|
||||
#
|
||||
# A field of a structure is described by the name of the field followed
|
||||
# by a type. The currently implemented types are:
|
||||
# nodeptr - a pointer to a node
|
||||
# nodelist - a pointer to a list of nodes
|
||||
# string - a pointer to a nul terminated string
|
||||
# int - an integer
|
||||
# other - any type that can be copied by assignment
|
||||
# temp - a field that doesn't have to be copied when the node is copied
|
||||
# The last two types should be followed by the text of a C declaration for
|
||||
# the field.
|
||||
|
||||
NSEMI nbinary # two commands separated by a semicolon
|
||||
type int
|
||||
ch1 nodeptr # the first child
|
||||
ch2 nodeptr # the second child
|
||||
|
||||
NCMD ncmd # a simple command
|
||||
type int
|
||||
backgnd int # set to run command in background
|
||||
args nodeptr # the arguments
|
||||
redirect nodeptr # list of file redirections
|
||||
|
||||
NPIPE npipe # a pipeline
|
||||
type int
|
||||
backgnd int # set to run pipeline in background
|
||||
cmdlist nodelist # the commands in the pipeline
|
||||
|
||||
NREDIR nredir # redirection (of a complex command)
|
||||
type int
|
||||
n nodeptr # the command
|
||||
redirect nodeptr # list of file redirections
|
||||
|
||||
NBACKGND nredir # run command in background
|
||||
NSUBSHELL nredir # run command in a subshell
|
||||
|
||||
NAND nbinary # the && operator
|
||||
NOR nbinary # the || operator
|
||||
|
||||
NIF nif # the if statement. Elif clauses are handled
|
||||
type int # using multiple if nodes.
|
||||
test nodeptr # if test
|
||||
ifpart nodeptr # then ifpart
|
||||
elsepart nodeptr # else elsepart
|
||||
|
||||
NWHILE nbinary # the while statement. First child is the test
|
||||
NUNTIL nbinary # the until statement
|
||||
|
||||
NFOR nfor # the for statement
|
||||
type int
|
||||
args nodeptr # for var in args
|
||||
body nodeptr # do body; done
|
||||
var string # the for variable
|
||||
|
||||
NCASE ncase # a case statement
|
||||
type int
|
||||
expr nodeptr # the word to switch on
|
||||
cases nodeptr # the list of cases (NCLIST nodes)
|
||||
|
||||
NCLIST nclist # a case
|
||||
type int
|
||||
next nodeptr # the next case in list
|
||||
pattern nodeptr # list of patterns for this case
|
||||
body nodeptr # code to execute for this case
|
||||
|
||||
|
||||
NDEFUN narg # define a function. The "next" field contains
|
||||
# the body of the function.
|
||||
|
||||
NARG narg # represents a word
|
||||
type int
|
||||
next nodeptr # next word in list
|
||||
text string # the text of the word
|
||||
backquote nodelist # list of commands in back quotes
|
||||
|
||||
NTO nfile # fd> fname
|
||||
NCLOBBER nfile # fd>| fname
|
||||
NFROM nfile # fd< fname
|
||||
NFROMTO nfile # fd<> fname
|
||||
NAPPEND nfile # fd>> fname
|
||||
type int
|
||||
next nodeptr # next redirection in list
|
||||
fd int # file descriptor being redirected
|
||||
fname nodeptr # file name, in a NARG node
|
||||
expfname temp char *expfname # actual file name
|
||||
|
||||
NTOFD ndup # fd<&dupfd
|
||||
NFROMFD ndup # fd>&dupfd
|
||||
type int
|
||||
next nodeptr # next redirection in list
|
||||
fd int # file descriptor being redirected
|
||||
dupfd int # file descriptor to duplicate
|
||||
vname nodeptr # file name if fd>&$var
|
||||
|
||||
|
||||
NHERE nhere # fd<<\!
|
||||
NXHERE nhere # fd<<!
|
||||
type int
|
||||
next nodeptr # next redirection in list
|
||||
fd int # file descriptor being redirected
|
||||
doc nodeptr # input to command (NARG node)
|
||||
|
||||
NNOT nnot # ! command (actually pipeline)
|
||||
type int
|
||||
com nodeptr
|
||||
530
sh/options.c
530
sh/options.c
|
|
@ -1,530 +0,0 @@
|
|||
/* $NetBSD: options.c,v 1.37 2004/10/30 19:29:27 christos Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1991, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to Berkeley by
|
||||
* Kenneth Almquist.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
#ifndef lint
|
||||
#if 0
|
||||
static char sccsid[] = "@(#)options.c 8.2 (Berkeley) 5/4/95";
|
||||
#else
|
||||
__RCSID("$NetBSD: options.c,v 1.37 2004/10/30 19:29:27 christos Exp $");
|
||||
#endif
|
||||
#endif /* not lint */
|
||||
|
||||
#include <signal.h>
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "shell.h"
|
||||
#define DEFINE_OPTIONS
|
||||
#include "options.h"
|
||||
#undef DEFINE_OPTIONS
|
||||
#include "nodes.h" /* for other header files */
|
||||
#include "eval.h"
|
||||
#include "jobs.h"
|
||||
#include "input.h"
|
||||
#include "output.h"
|
||||
#include "trap.h"
|
||||
#include "var.h"
|
||||
#include "memalloc.h"
|
||||
#include "error.h"
|
||||
#include "mystring.h"
|
||||
#ifndef SMALL
|
||||
#include "myhistedit.h"
|
||||
#endif
|
||||
#include "show.h"
|
||||
|
||||
char *arg0; /* value of $0 */
|
||||
struct shparam shellparam; /* current positional parameters */
|
||||
char **argptr; /* argument list for builtin commands */
|
||||
char *optionarg; /* set by nextopt (like getopt) */
|
||||
char *optptr; /* used by nextopt */
|
||||
|
||||
char *minusc; /* argument to -c option */
|
||||
|
||||
|
||||
STATIC void options(int);
|
||||
STATIC void minus_o(char *, int);
|
||||
STATIC void setoption(int, int);
|
||||
STATIC int getopts(char *, char *, char **, char ***, char **);
|
||||
|
||||
|
||||
/*
|
||||
* Process the shell command line arguments.
|
||||
*/
|
||||
|
||||
void
|
||||
procargs(int argc, char **argv)
|
||||
{
|
||||
int i;
|
||||
|
||||
argptr = argv;
|
||||
if (argc > 0)
|
||||
argptr++;
|
||||
for (i = 0; i < NOPTS; i++)
|
||||
optlist[i].val = 2;
|
||||
options(1);
|
||||
if (*argptr == NULL && minusc == NULL)
|
||||
sflag = 1;
|
||||
if (iflag == 2 && sflag == 1 && isatty(0) && isatty(1))
|
||||
iflag = 1;
|
||||
if (mflag == 2)
|
||||
mflag = iflag;
|
||||
for (i = 0; i < NOPTS; i++)
|
||||
if (optlist[i].val == 2)
|
||||
optlist[i].val = 0;
|
||||
#if DEBUG == 2
|
||||
debug = 1;
|
||||
#endif
|
||||
arg0 = argv[0];
|
||||
if (sflag == 0 && minusc == NULL) {
|
||||
commandname = argv[0];
|
||||
arg0 = *argptr++;
|
||||
setinputfile(arg0, 0);
|
||||
commandname = arg0;
|
||||
}
|
||||
/* POSIX 1003.2: first arg after -c cmd is $0, remainder $1... */
|
||||
if (minusc != NULL) {
|
||||
if (argptr == NULL || *argptr == NULL)
|
||||
error("Bad -c option");
|
||||
minusc = *argptr++;
|
||||
if (*argptr != 0)
|
||||
arg0 = *argptr++;
|
||||
}
|
||||
|
||||
shellparam.p = argptr;
|
||||
shellparam.reset = 1;
|
||||
/* assert(shellparam.malloc == 0 && shellparam.nparam == 0); */
|
||||
while (*argptr) {
|
||||
shellparam.nparam++;
|
||||
argptr++;
|
||||
}
|
||||
optschanged();
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
optschanged(void)
|
||||
{
|
||||
setinteractive(iflag);
|
||||
#ifdef WITH_HISTORY
|
||||
histedit();
|
||||
#endif
|
||||
setjobctl(mflag);
|
||||
}
|
||||
|
||||
/*
|
||||
* Process shell options. The global variable argptr contains a pointer
|
||||
* to the argument list; we advance it past the options.
|
||||
*/
|
||||
|
||||
STATIC void
|
||||
options(int cmdline)
|
||||
{
|
||||
static char empty[] = "";
|
||||
char *p;
|
||||
int val;
|
||||
int c;
|
||||
|
||||
if (cmdline)
|
||||
minusc = NULL;
|
||||
while ((p = *argptr) != NULL) {
|
||||
argptr++;
|
||||
if ((c = *p++) == '-') {
|
||||
val = 1;
|
||||
if (p[0] == '\0' || (p[0] == '-' && p[1] == '\0')) {
|
||||
if (!cmdline) {
|
||||
/* "-" means turn off -x and -v */
|
||||
if (p[0] == '\0')
|
||||
xflag = vflag = 0;
|
||||
/* "--" means reset params */
|
||||
else if (*argptr == NULL)
|
||||
setparam(argptr);
|
||||
}
|
||||
break; /* "-" or "--" terminates options */
|
||||
}
|
||||
} else if (c == '+') {
|
||||
val = 0;
|
||||
} else {
|
||||
argptr--;
|
||||
break;
|
||||
}
|
||||
while ((c = *p++) != '\0') {
|
||||
if (c == 'c' && cmdline) {
|
||||
/* command is after shell args*/
|
||||
minusc = empty;
|
||||
} else if (c == 'o') {
|
||||
minus_o(*argptr, val);
|
||||
if (*argptr)
|
||||
argptr++;
|
||||
} else {
|
||||
setoption(c, val);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
set_opt_val(int i, int val)
|
||||
{
|
||||
int j;
|
||||
int flag;
|
||||
|
||||
if (val && (flag = optlist[i].opt_set)) {
|
||||
/* some options (eg vi/emacs) are mutually exclusive */
|
||||
for (j = 0; j < NOPTS; j++)
|
||||
if (optlist[j].opt_set == flag)
|
||||
optlist[j].val = 0;
|
||||
}
|
||||
optlist[i].val = val;
|
||||
#ifdef DEBUG
|
||||
if (&optlist[i].val == &debug)
|
||||
opentrace();
|
||||
#endif
|
||||
}
|
||||
|
||||
STATIC void
|
||||
minus_o(char *name, int val)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (name == NULL) {
|
||||
out1str("Current option settings\n");
|
||||
for (i = 0; i < NOPTS; i++)
|
||||
out1fmt("%-16s%s\n", optlist[i].name,
|
||||
optlist[i].val ? "on" : "off");
|
||||
} else {
|
||||
for (i = 0; i < NOPTS; i++)
|
||||
if (equal(name, optlist[i].name)) {
|
||||
set_opt_val(i, val);
|
||||
return;
|
||||
}
|
||||
error("Illegal option -o %s", name);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
STATIC void
|
||||
setoption(int flag, int val)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < NOPTS; i++)
|
||||
if (optlist[i].letter == flag) {
|
||||
set_opt_val( i, val );
|
||||
return;
|
||||
}
|
||||
error("Illegal option -%c", flag);
|
||||
/* NOTREACHED */
|
||||
}
|
||||
|
||||
|
||||
|
||||
#ifdef mkinit
|
||||
INCLUDE "options.h"
|
||||
|
||||
SHELLPROC {
|
||||
int i;
|
||||
|
||||
for (i = 0; optlist[i].name; i++)
|
||||
optlist[i].val = 0;
|
||||
optschanged();
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
* Set the shell parameters.
|
||||
*/
|
||||
|
||||
void
|
||||
setparam(char **argv)
|
||||
{
|
||||
char **newparam;
|
||||
char **ap;
|
||||
int nparam;
|
||||
|
||||
for (nparam = 0 ; argv[nparam] ; nparam++);
|
||||
ap = newparam = ckmalloc((nparam + 1) * sizeof *ap);
|
||||
while (*argv) {
|
||||
*ap++ = savestr(*argv++);
|
||||
}
|
||||
*ap = NULL;
|
||||
freeparam(&shellparam);
|
||||
shellparam.malloc = 1;
|
||||
shellparam.nparam = nparam;
|
||||
shellparam.p = newparam;
|
||||
shellparam.optnext = NULL;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Free the list of positional parameters.
|
||||
*/
|
||||
|
||||
void
|
||||
freeparam(volatile struct shparam *param)
|
||||
{
|
||||
char **ap;
|
||||
|
||||
if (param->malloc) {
|
||||
for (ap = param->p ; *ap ; ap++)
|
||||
ckfree(*ap);
|
||||
ckfree(param->p);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* The shift builtin command.
|
||||
*/
|
||||
|
||||
int
|
||||
shiftcmd(int argc, char **argv)
|
||||
{
|
||||
int n;
|
||||
char **ap1, **ap2;
|
||||
|
||||
n = 1;
|
||||
if (argc > 1)
|
||||
n = number(argv[1]);
|
||||
if (n > shellparam.nparam)
|
||||
error("can't shift that many");
|
||||
INTOFF;
|
||||
shellparam.nparam -= n;
|
||||
for (ap1 = shellparam.p ; --n >= 0 ; ap1++) {
|
||||
if (shellparam.malloc)
|
||||
ckfree(*ap1);
|
||||
}
|
||||
ap2 = shellparam.p;
|
||||
while ((*ap2++ = *ap1++) != NULL);
|
||||
shellparam.optnext = NULL;
|
||||
INTON;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* The set command builtin.
|
||||
*/
|
||||
|
||||
int
|
||||
setcmd(int argc, char **argv)
|
||||
{
|
||||
if (argc == 1)
|
||||
return showvars(0, 0, 1);
|
||||
INTOFF;
|
||||
options(0);
|
||||
optschanged();
|
||||
if (*argptr != NULL) {
|
||||
setparam(argptr);
|
||||
}
|
||||
INTON;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
getoptsreset(value)
|
||||
const char *value;
|
||||
{
|
||||
if (number(value) == 1) {
|
||||
shellparam.optnext = NULL;
|
||||
shellparam.reset = 1;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* The getopts builtin. Shellparam.optnext points to the next argument
|
||||
* to be processed. Shellparam.optptr points to the next character to
|
||||
* be processed in the current argument. If shellparam.optnext is NULL,
|
||||
* then it's the first time getopts has been called.
|
||||
*/
|
||||
|
||||
int
|
||||
getoptscmd(int argc, char **argv)
|
||||
{
|
||||
char **optbase;
|
||||
|
||||
if (argc < 3)
|
||||
error("usage: getopts optstring var [arg]");
|
||||
else if (argc == 3)
|
||||
optbase = shellparam.p;
|
||||
else
|
||||
optbase = &argv[3];
|
||||
|
||||
if (shellparam.reset == 1) {
|
||||
shellparam.optnext = optbase;
|
||||
shellparam.optptr = NULL;
|
||||
shellparam.reset = 0;
|
||||
}
|
||||
|
||||
return getopts(argv[1], argv[2], optbase, &shellparam.optnext,
|
||||
&shellparam.optptr);
|
||||
}
|
||||
|
||||
STATIC int
|
||||
getopts(char *optstr, char *optvar, char **optfirst, char ***optnext, char **optpptr)
|
||||
{
|
||||
char *p, *q;
|
||||
char c = '?';
|
||||
int done = 0;
|
||||
int ind = 0;
|
||||
int err = 0;
|
||||
char s[12];
|
||||
|
||||
if ((p = *optpptr) == NULL || *p == '\0') {
|
||||
/* Current word is done, advance */
|
||||
if (*optnext == NULL)
|
||||
return 1;
|
||||
p = **optnext;
|
||||
if (p == NULL || *p != '-' || *++p == '\0') {
|
||||
atend:
|
||||
ind = *optnext - optfirst + 1;
|
||||
*optnext = NULL;
|
||||
p = NULL;
|
||||
done = 1;
|
||||
goto out;
|
||||
}
|
||||
(*optnext)++;
|
||||
if (p[0] == '-' && p[1] == '\0') /* check for "--" */
|
||||
goto atend;
|
||||
}
|
||||
|
||||
c = *p++;
|
||||
for (q = optstr; *q != c; ) {
|
||||
if (*q == '\0') {
|
||||
if (optstr[0] == ':') {
|
||||
s[0] = c;
|
||||
s[1] = '\0';
|
||||
err |= setvarsafe("OPTARG", s, 0);
|
||||
} else {
|
||||
outfmt(&errout, "Illegal option -%c\n", c);
|
||||
(void) unsetvar("OPTARG", 0);
|
||||
}
|
||||
c = '?';
|
||||
goto bad;
|
||||
}
|
||||
if (*++q == ':')
|
||||
q++;
|
||||
}
|
||||
|
||||
if (*++q == ':') {
|
||||
if (*p == '\0' && (p = **optnext) == NULL) {
|
||||
if (optstr[0] == ':') {
|
||||
s[0] = c;
|
||||
s[1] = '\0';
|
||||
err |= setvarsafe("OPTARG", s, 0);
|
||||
c = ':';
|
||||
} else {
|
||||
outfmt(&errout, "No arg for -%c option\n", c);
|
||||
(void) unsetvar("OPTARG", 0);
|
||||
c = '?';
|
||||
}
|
||||
goto bad;
|
||||
}
|
||||
|
||||
if (p == **optnext)
|
||||
(*optnext)++;
|
||||
err |= setvarsafe("OPTARG", p, 0);
|
||||
p = NULL;
|
||||
} else
|
||||
err |= setvarsafe("OPTARG", "", 0);
|
||||
ind = *optnext - optfirst + 1;
|
||||
goto out;
|
||||
|
||||
bad:
|
||||
ind = 1;
|
||||
*optnext = NULL;
|
||||
p = NULL;
|
||||
out:
|
||||
*optpptr = p;
|
||||
fmtstr(s, sizeof(s), "%d", ind);
|
||||
err |= setvarsafe("OPTIND", s, VNOFUNC);
|
||||
s[0] = c;
|
||||
s[1] = '\0';
|
||||
err |= setvarsafe(optvar, s, 0);
|
||||
if (err) {
|
||||
*optnext = NULL;
|
||||
*optpptr = NULL;
|
||||
flushall();
|
||||
exraise(EXERROR);
|
||||
}
|
||||
return done;
|
||||
}
|
||||
|
||||
/*
|
||||
* XXX - should get rid of. have all builtins use getopt(3). the
|
||||
* library getopt must have the BSD extension static variable "optreset"
|
||||
* otherwise it can't be used within the shell safely.
|
||||
*
|
||||
* Standard option processing (a la getopt) for builtin routines. The
|
||||
* only argument that is passed to nextopt is the option string; the
|
||||
* other arguments are unnecessary. It return the character, or '\0' on
|
||||
* end of input.
|
||||
*/
|
||||
|
||||
int
|
||||
nextopt(const char *optstring)
|
||||
{
|
||||
char *p;
|
||||
const char *q;
|
||||
char c;
|
||||
|
||||
if ((p = optptr) == NULL || *p == '\0') {
|
||||
p = *argptr;
|
||||
if (p == NULL || *p != '-' || *++p == '\0')
|
||||
return '\0';
|
||||
argptr++;
|
||||
if (p[0] == '-' && p[1] == '\0') /* check for "--" */
|
||||
return '\0';
|
||||
}
|
||||
c = *p++;
|
||||
for (q = optstring ; *q != c ; ) {
|
||||
if (*q == '\0')
|
||||
error("Illegal option -%c", c);
|
||||
if (*++q == ':')
|
||||
q++;
|
||||
}
|
||||
if (*++q == ':') {
|
||||
if (*p == '\0' && (p = *argptr++) == NULL)
|
||||
error("No arg for -%c option", c);
|
||||
optionarg = p;
|
||||
p = NULL;
|
||||
}
|
||||
optptr = p;
|
||||
return c;
|
||||
}
|
||||
131
sh/options.h
131
sh/options.h
|
|
@ -1,131 +0,0 @@
|
|||
/* $NetBSD: options.h,v 1.17 2003/08/07 09:05:36 agc Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1991, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to Berkeley by
|
||||
* Kenneth Almquist.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)options.h 8.2 (Berkeley) 5/4/95
|
||||
*/
|
||||
|
||||
struct shparam {
|
||||
int nparam; /* # of positional parameters (without $0) */
|
||||
unsigned char malloc; /* if parameter list dynamically allocated */
|
||||
unsigned char reset; /* if getopts has been reset */
|
||||
char **p; /* parameter list */
|
||||
char **optnext; /* next parameter to be processed by getopts */
|
||||
char *optptr; /* used by getopts */
|
||||
};
|
||||
|
||||
|
||||
struct optent {
|
||||
const char *name; /* for set -o <name> */
|
||||
const char letter; /* set [+/-]<letter> and $- */
|
||||
const char opt_set; /* mutually exclusive option set */
|
||||
char val; /* value of <letter>flag */
|
||||
};
|
||||
|
||||
/* Those marked [U] are required by posix, but have no effect! */
|
||||
|
||||
#ifdef DEFINE_OPTIONS
|
||||
#define DEF_OPTS(name, letter, opt_set) {name, letter, opt_set, 0},
|
||||
struct optent optlist[] = {
|
||||
#else
|
||||
#define DEF_OPTS(name, letter, opt_set)
|
||||
#endif
|
||||
#define DEF_OPT(name,letter) DEF_OPTS(name, letter, 0)
|
||||
|
||||
DEF_OPT( "errexit", 'e' ) /* exit on error */
|
||||
#define eflag optlist[0].val
|
||||
DEF_OPT( "noglob", 'f' ) /* no pathname expansion */
|
||||
#define fflag optlist[1].val
|
||||
DEF_OPT( "ignoreeof", 'I' ) /* do not exit on EOF */
|
||||
#define Iflag optlist[2].val
|
||||
DEF_OPT( "interactive",'i' ) /* interactive shell */
|
||||
#define iflag optlist[3].val
|
||||
DEF_OPT( "monitor", 'm' ) /* job control */
|
||||
#define mflag optlist[4].val
|
||||
DEF_OPT( "noexec", 'n' ) /* [U] do not exec commands */
|
||||
#define nflag optlist[5].val
|
||||
DEF_OPT( "stdin", 's' ) /* read from stdin */
|
||||
#define sflag optlist[6].val
|
||||
DEF_OPT( "xtrace", 'x' ) /* trace after expansion */
|
||||
#define xflag optlist[7].val
|
||||
DEF_OPT( "verbose", 'v' ) /* trace read input */
|
||||
#define vflag optlist[8].val
|
||||
DEF_OPTS( "vi", 'V', 'V' ) /* vi style editing */
|
||||
#define Vflag optlist[9].val
|
||||
DEF_OPTS( "emacs", 'E', 'V' ) /* emacs style editing */
|
||||
#define Eflag optlist[10].val
|
||||
DEF_OPT( "noclobber", 'C' ) /* do not overwrite files with > */
|
||||
#define Cflag optlist[11].val
|
||||
DEF_OPT( "allexport", 'a' ) /* export all variables */
|
||||
#define aflag optlist[12].val
|
||||
DEF_OPT( "notify", 'b' ) /* [U] report completion of background jobs */
|
||||
#define bflag optlist[13].val
|
||||
DEF_OPT( "nounset", 'u' ) /* error expansion of unset variables */
|
||||
#define uflag optlist[14].val
|
||||
DEF_OPT( "quietprofile", 'q' )
|
||||
#define qflag optlist[15].val
|
||||
DEF_OPT( "nolog", 0 ) /* [U] no functon defs in command history */
|
||||
#define nolog optlist[16].val
|
||||
DEF_OPT( "cdprint", 0 ) /* always print result of cd */
|
||||
#define cdprint optlist[17].val
|
||||
#ifdef DEBUG
|
||||
DEF_OPT( "debug", 0 ) /* enable debug prints */
|
||||
#define debug optlist[18].val
|
||||
#endif
|
||||
|
||||
#ifdef DEFINE_OPTIONS
|
||||
{ 0, 0, 0, 0 },
|
||||
};
|
||||
#define NOPTS (sizeof optlist / sizeof optlist[0] - 1)
|
||||
int sizeof_optlist = sizeof optlist;
|
||||
#else
|
||||
extern struct optent optlist[];
|
||||
extern int sizeof_optlist;
|
||||
#endif
|
||||
|
||||
|
||||
extern char *minusc; /* argument to -c option */
|
||||
extern char *arg0; /* $0 */
|
||||
extern struct shparam shellparam; /* $@ */
|
||||
extern char **argptr; /* argument list for builtin commands */
|
||||
extern char *optionarg; /* set by nextopt */
|
||||
extern char *optptr; /* used by nextopt */
|
||||
|
||||
void procargs(int, char **);
|
||||
void optschanged(void);
|
||||
void setparam(char **);
|
||||
void freeparam(volatile struct shparam *);
|
||||
int shiftcmd(int, char **);
|
||||
int setcmd(int, char **);
|
||||
int getoptscmd(int, char **);
|
||||
int nextopt(const char *);
|
||||
void getoptsreset(const char *);
|
||||
516
sh/output.c
516
sh/output.c
|
|
@ -1,516 +0,0 @@
|
|||
/* $NetBSD: output.c,v 1.28 2003/08/07 09:05:36 agc Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1991, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to Berkeley by
|
||||
* Kenneth Almquist.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
#ifndef lint
|
||||
#if 0
|
||||
static char sccsid[] = "@(#)output.c 8.2 (Berkeley) 5/4/95";
|
||||
#else
|
||||
__RCSID("$NetBSD: output.c,v 1.28 2003/08/07 09:05:36 agc Exp $");
|
||||
#endif
|
||||
#endif /* not lint */
|
||||
|
||||
/*
|
||||
* Shell output routines. We use our own output routines because:
|
||||
* When a builtin command is interrupted we have to discard
|
||||
* any pending output.
|
||||
* When a builtin command appears in back quotes, we want to
|
||||
* save the output of the command in a region obtained
|
||||
* via malloc, rather than doing a fork and reading the
|
||||
* output of the command via a pipe.
|
||||
* Our output routines may be smaller than the stdio routines.
|
||||
*/
|
||||
|
||||
#include <sys/types.h> /* quad_t */
|
||||
#include <sys/param.h> /* BSD4_4 */
|
||||
#include <sys/ioctl.h>
|
||||
|
||||
#include <stdio.h> /* defines BUFSIZ */
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "shell.h"
|
||||
#include "syntax.h"
|
||||
#include "output.h"
|
||||
#include "memalloc.h"
|
||||
#include "error.h"
|
||||
|
||||
|
||||
#define OUTBUFSIZ BUFSIZ
|
||||
#define BLOCK_OUT -2 /* output to a fixed block of memory */
|
||||
#define MEM_OUT -3 /* output to dynamically allocated memory */
|
||||
#define OUTPUT_ERR 01 /* error occurred on output */
|
||||
|
||||
|
||||
struct output output = {NULL, 0, NULL, OUTBUFSIZ, 1, 0};
|
||||
struct output errout = {NULL, 0, NULL, 100, 2, 0};
|
||||
struct output memout = {NULL, 0, NULL, 0, MEM_OUT, 0};
|
||||
struct output *out1 = &output;
|
||||
struct output *out2 = &errout;
|
||||
|
||||
|
||||
|
||||
#ifdef mkinit
|
||||
|
||||
INCLUDE "output.h"
|
||||
INCLUDE "memalloc.h"
|
||||
|
||||
RESET {
|
||||
out1 = &output;
|
||||
out2 = &errout;
|
||||
if (memout.buf != NULL) {
|
||||
ckfree(memout.buf);
|
||||
memout.buf = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef notdef /* no longer used */
|
||||
/*
|
||||
* Set up an output file to write to memory rather than a file.
|
||||
*/
|
||||
|
||||
void
|
||||
open_mem(char *block, int length, struct output *file)
|
||||
{
|
||||
file->nextc = block;
|
||||
file->nleft = --length;
|
||||
file->fd = BLOCK_OUT;
|
||||
file->flags = 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
void
|
||||
out1str(const char *p)
|
||||
{
|
||||
outstr(p, out1);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
out2str(const char *p)
|
||||
{
|
||||
outstr(p, out2);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
outstr(const char *p, struct output *file)
|
||||
{
|
||||
while (*p)
|
||||
outc(*p++, file);
|
||||
if (file == out2)
|
||||
flushout(file);
|
||||
}
|
||||
|
||||
|
||||
char out_junk[16];
|
||||
|
||||
|
||||
void
|
||||
emptyoutbuf(struct output *dest)
|
||||
{
|
||||
int offset;
|
||||
|
||||
if (dest->fd == BLOCK_OUT) {
|
||||
dest->nextc = out_junk;
|
||||
dest->nleft = sizeof out_junk;
|
||||
dest->flags |= OUTPUT_ERR;
|
||||
} else if (dest->buf == NULL) {
|
||||
INTOFF;
|
||||
dest->buf = ckmalloc(dest->bufsize);
|
||||
dest->nextc = dest->buf;
|
||||
dest->nleft = dest->bufsize;
|
||||
INTON;
|
||||
} else if (dest->fd == MEM_OUT) {
|
||||
offset = dest->bufsize;
|
||||
INTOFF;
|
||||
dest->bufsize <<= 1;
|
||||
dest->buf = ckrealloc(dest->buf, dest->bufsize);
|
||||
dest->nleft = dest->bufsize - offset;
|
||||
dest->nextc = dest->buf + offset;
|
||||
INTON;
|
||||
} else {
|
||||
flushout(dest);
|
||||
}
|
||||
dest->nleft--;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
flushall(void)
|
||||
{
|
||||
flushout(&output);
|
||||
flushout(&errout);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
flushout(struct output *dest)
|
||||
{
|
||||
|
||||
if (dest->buf == NULL || dest->nextc == dest->buf || dest->fd < 0)
|
||||
return;
|
||||
if (xwrite(dest->fd, dest->buf, dest->nextc - dest->buf) < 0)
|
||||
dest->flags |= OUTPUT_ERR;
|
||||
dest->nextc = dest->buf;
|
||||
dest->nleft = dest->bufsize;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
freestdout(void)
|
||||
{
|
||||
INTOFF;
|
||||
if (output.buf) {
|
||||
ckfree(output.buf);
|
||||
output.buf = NULL;
|
||||
output.nleft = 0;
|
||||
}
|
||||
INTON;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
outfmt(struct output *file, const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, fmt);
|
||||
doformat(file, fmt, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
out1fmt(const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, fmt);
|
||||
doformat(out1, fmt, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
void
|
||||
dprintf(const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, fmt);
|
||||
doformat(out2, fmt, ap);
|
||||
va_end(ap);
|
||||
flushout(out2);
|
||||
}
|
||||
|
||||
void
|
||||
fmtstr(char *outbuf, size_t length, const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
struct output strout;
|
||||
|
||||
va_start(ap, fmt);
|
||||
strout.nextc = outbuf;
|
||||
strout.nleft = length;
|
||||
strout.fd = BLOCK_OUT;
|
||||
strout.flags = 0;
|
||||
doformat(&strout, fmt, ap);
|
||||
outc('\0', &strout);
|
||||
if (strout.flags & OUTPUT_ERR)
|
||||
outbuf[length - 1] = '\0';
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
/*
|
||||
* Formatted output. This routine handles a subset of the printf formats:
|
||||
* - Formats supported: d, u, o, p, X, s, and c.
|
||||
* - The x format is also accepted but is treated like X.
|
||||
* - The l, ll and q modifiers are accepted.
|
||||
* - The - and # flags are accepted; # only works with the o format.
|
||||
* - Width and precision may be specified with any format except c.
|
||||
* - An * may be given for the width or precision.
|
||||
* - The obsolete practice of preceding the width with a zero to get
|
||||
* zero padding is not supported; use the precision field.
|
||||
* - A % may be printed by writing %% in the format string.
|
||||
*/
|
||||
|
||||
#define TEMPSIZE 24
|
||||
|
||||
#ifdef BSD4_4
|
||||
#define HAVE_VASPRINTF 1
|
||||
#endif
|
||||
|
||||
void
|
||||
doformat(struct output *dest, const char *f, va_list ap)
|
||||
{
|
||||
#if HAVE_VASPRINTF
|
||||
char *s;
|
||||
|
||||
vasprintf(&s, f, ap);
|
||||
outstr(s, dest);
|
||||
free(s);
|
||||
#else /* !HAVE_VASPRINTF */
|
||||
static const char digit[] = "0123456789ABCDEF";
|
||||
char c;
|
||||
char temp[TEMPSIZE];
|
||||
int flushleft;
|
||||
int sharp;
|
||||
int width;
|
||||
int prec;
|
||||
int islong;
|
||||
int isquad;
|
||||
char *p;
|
||||
int sign;
|
||||
#ifdef BSD4_4
|
||||
quad_t l;
|
||||
u_quad_t num;
|
||||
#else
|
||||
long l;
|
||||
u_long num;
|
||||
#endif
|
||||
unsigned base;
|
||||
int len;
|
||||
int size;
|
||||
int pad;
|
||||
|
||||
while ((c = *f++) != '\0') {
|
||||
if (c != '%') {
|
||||
outc(c, dest);
|
||||
continue;
|
||||
}
|
||||
flushleft = 0;
|
||||
sharp = 0;
|
||||
width = 0;
|
||||
prec = -1;
|
||||
islong = 0;
|
||||
isquad = 0;
|
||||
for (;;) {
|
||||
if (*f == '-')
|
||||
flushleft++;
|
||||
else if (*f == '#')
|
||||
sharp++;
|
||||
else
|
||||
break;
|
||||
f++;
|
||||
}
|
||||
if (*f == '*') {
|
||||
width = va_arg(ap, int);
|
||||
f++;
|
||||
} else {
|
||||
while (is_digit(*f)) {
|
||||
width = 10 * width + digit_val(*f++);
|
||||
}
|
||||
}
|
||||
if (*f == '.') {
|
||||
if (*++f == '*') {
|
||||
prec = va_arg(ap, int);
|
||||
f++;
|
||||
} else {
|
||||
prec = 0;
|
||||
while (is_digit(*f)) {
|
||||
prec = 10 * prec + digit_val(*f++);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (*f == 'l') {
|
||||
f++;
|
||||
if (*f == 'l') {
|
||||
isquad++;
|
||||
f++;
|
||||
} else
|
||||
islong++;
|
||||
} else if (*f == 'q') {
|
||||
isquad++;
|
||||
f++;
|
||||
}
|
||||
switch (*f) {
|
||||
case 'd':
|
||||
#ifdef BSD4_4
|
||||
if (isquad)
|
||||
l = va_arg(ap, quad_t);
|
||||
else
|
||||
#endif
|
||||
if (islong)
|
||||
l = va_arg(ap, long);
|
||||
else
|
||||
l = va_arg(ap, int);
|
||||
sign = 0;
|
||||
num = l;
|
||||
if (l < 0) {
|
||||
num = -l;
|
||||
sign = 1;
|
||||
}
|
||||
base = 10;
|
||||
goto number;
|
||||
case 'u':
|
||||
base = 10;
|
||||
goto uns_number;
|
||||
case 'o':
|
||||
base = 8;
|
||||
goto uns_number;
|
||||
case 'p':
|
||||
outc('0', dest);
|
||||
outc('x', dest);
|
||||
/*FALLTHROUGH*/
|
||||
case 'x':
|
||||
/* we don't implement 'x'; treat like 'X' */
|
||||
case 'X':
|
||||
base = 16;
|
||||
uns_number: /* an unsigned number */
|
||||
sign = 0;
|
||||
#ifdef BSD4_4
|
||||
if (isquad)
|
||||
num = va_arg(ap, u_quad_t);
|
||||
else
|
||||
#endif
|
||||
if (islong)
|
||||
num = va_arg(ap, unsigned long);
|
||||
else
|
||||
num = va_arg(ap, unsigned int);
|
||||
number: /* process a number */
|
||||
p = temp + TEMPSIZE - 1;
|
||||
*p = '\0';
|
||||
while (num) {
|
||||
*--p = digit[num % base];
|
||||
num /= base;
|
||||
}
|
||||
len = (temp + TEMPSIZE - 1) - p;
|
||||
if (prec < 0)
|
||||
prec = 1;
|
||||
if (sharp && *f == 'o' && prec <= len)
|
||||
prec = len + 1;
|
||||
pad = 0;
|
||||
if (width) {
|
||||
size = len;
|
||||
if (size < prec)
|
||||
size = prec;
|
||||
size += sign;
|
||||
pad = width - size;
|
||||
if (flushleft == 0) {
|
||||
while (--pad >= 0)
|
||||
outc(' ', dest);
|
||||
}
|
||||
}
|
||||
if (sign)
|
||||
outc('-', dest);
|
||||
prec -= len;
|
||||
while (--prec >= 0)
|
||||
outc('0', dest);
|
||||
while (*p)
|
||||
outc(*p++, dest);
|
||||
while (--pad >= 0)
|
||||
outc(' ', dest);
|
||||
break;
|
||||
case 's':
|
||||
p = va_arg(ap, char *);
|
||||
pad = 0;
|
||||
if (width) {
|
||||
len = strlen(p);
|
||||
if (prec >= 0 && len > prec)
|
||||
len = prec;
|
||||
pad = width - len;
|
||||
if (flushleft == 0) {
|
||||
while (--pad >= 0)
|
||||
outc(' ', dest);
|
||||
}
|
||||
}
|
||||
prec++;
|
||||
while (--prec != 0 && *p)
|
||||
outc(*p++, dest);
|
||||
while (--pad >= 0)
|
||||
outc(' ', dest);
|
||||
break;
|
||||
case 'c':
|
||||
c = va_arg(ap, int);
|
||||
outc(c, dest);
|
||||
break;
|
||||
default:
|
||||
outc(*f, dest);
|
||||
break;
|
||||
}
|
||||
f++;
|
||||
}
|
||||
#endif /* !HAVE_VASPRINTF */
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Version of write which resumes after a signal is caught.
|
||||
*/
|
||||
|
||||
int
|
||||
xwrite(int fd, char *buf, int nbytes)
|
||||
{
|
||||
int ntry;
|
||||
int i;
|
||||
int n;
|
||||
|
||||
n = nbytes;
|
||||
ntry = 0;
|
||||
for (;;) {
|
||||
i = write(fd, buf, n);
|
||||
if (i > 0) {
|
||||
if ((n -= i) <= 0)
|
||||
return nbytes;
|
||||
buf += i;
|
||||
ntry = 0;
|
||||
} else if (i == 0) {
|
||||
if (++ntry > 10)
|
||||
return nbytes - n;
|
||||
} else if (errno != EINTR) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Version of ioctl that retries after a signal is caught.
|
||||
* XXX unused function
|
||||
*/
|
||||
|
||||
int
|
||||
xioctl(int fd, unsigned long request, char *arg)
|
||||
{
|
||||
int i;
|
||||
|
||||
while ((i = ioctl(fd, request, arg)) == -1 && errno == EINTR);
|
||||
return i;
|
||||
}
|
||||
81
sh/output.h
81
sh/output.h
|
|
@ -1,81 +0,0 @@
|
|||
/* $NetBSD: output.h,v 1.17 2003/08/07 09:05:36 agc Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1991, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to Berkeley by
|
||||
* Kenneth Almquist.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)output.h 8.2 (Berkeley) 5/4/95
|
||||
*/
|
||||
|
||||
#ifndef OUTPUT_INCL
|
||||
|
||||
#include <stdarg.h>
|
||||
|
||||
struct output {
|
||||
char *nextc;
|
||||
int nleft;
|
||||
char *buf;
|
||||
int bufsize;
|
||||
short fd;
|
||||
short flags;
|
||||
};
|
||||
|
||||
extern struct output output;
|
||||
extern struct output errout;
|
||||
extern struct output memout;
|
||||
extern struct output *out1;
|
||||
extern struct output *out2;
|
||||
|
||||
void open_mem(char *, int, struct output *);
|
||||
void out1str(const char *);
|
||||
void out2str(const char *);
|
||||
void outstr(const char *, struct output *);
|
||||
void emptyoutbuf(struct output *);
|
||||
void flushall(void);
|
||||
void flushout(struct output *);
|
||||
void freestdout(void);
|
||||
void outfmt(struct output *, const char *, ...)
|
||||
__attribute__((__format__(__printf__,2,3)));
|
||||
void out1fmt(const char *, ...)
|
||||
__attribute__((__format__(__printf__,1,2)));
|
||||
void dprintf(const char *, ...)
|
||||
__attribute__((__format__(__printf__,1,2)));
|
||||
void fmtstr(char *, size_t, const char *, ...)
|
||||
__attribute__((__format__(__printf__,3,4)));
|
||||
void doformat(struct output *, const char *, va_list);
|
||||
int xwrite(int, char *, int);
|
||||
int xioctl(int, unsigned long, char *);
|
||||
|
||||
#define outc(c, file) (--(file)->nleft < 0? (emptyoutbuf(file), *(file)->nextc++ = (c)) : (*(file)->nextc++ = (c)))
|
||||
#define out1c(c) outc(c, out1);
|
||||
#define out2c(c) outc(c, out2);
|
||||
|
||||
#define OUTPUT_INCL
|
||||
#endif
|
||||
1654
sh/parser.c
1654
sh/parser.c
File diff suppressed because it is too large
Load diff
82
sh/parser.h
82
sh/parser.h
|
|
@ -1,82 +0,0 @@
|
|||
/* $NetBSD: parser.h,v 1.17 2004/06/26 22:09:49 dsl Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1991, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to Berkeley by
|
||||
* Kenneth Almquist.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)parser.h 8.3 (Berkeley) 5/4/95
|
||||
*/
|
||||
|
||||
/* control characters in argument strings */
|
||||
#define CTL_FIRST '\201' /* first 'special' character */
|
||||
#define CTLESC '\201' /* escape next character */
|
||||
#define CTLVAR '\202' /* variable defn */
|
||||
#define CTLENDVAR '\203'
|
||||
#define CTLBACKQ '\204'
|
||||
#define CTLQUOTE 01 /* ored with CTLBACKQ code if in quotes */
|
||||
/* CTLBACKQ | CTLQUOTE == '\205' */
|
||||
#define CTLARI '\206' /* arithmetic expression */
|
||||
#define CTLENDARI '\207'
|
||||
#define CTLQUOTEMARK '\210'
|
||||
#define CTLQUOTEEND '\211' /* only inside ${...} */
|
||||
#define CTL_LAST '\211' /* last 'special' character */
|
||||
|
||||
/* variable substitution byte (follows CTLVAR) */
|
||||
#define VSTYPE 0x0f /* type of variable substitution */
|
||||
#define VSNUL 0x10 /* colon--treat the empty string as unset */
|
||||
#define VSQUOTE 0x80 /* inside double quotes--suppress splitting */
|
||||
|
||||
/* values of VSTYPE field */
|
||||
#define VSNORMAL 0x1 /* normal variable: $var or ${var} */
|
||||
#define VSMINUS 0x2 /* ${var-text} */
|
||||
#define VSPLUS 0x3 /* ${var+text} */
|
||||
#define VSQUESTION 0x4 /* ${var?message} */
|
||||
#define VSASSIGN 0x5 /* ${var=text} */
|
||||
#define VSTRIMLEFT 0x6 /* ${var#pattern} */
|
||||
#define VSTRIMLEFTMAX 0x7 /* ${var##pattern} */
|
||||
#define VSTRIMRIGHT 0x8 /* ${var%pattern} */
|
||||
#define VSTRIMRIGHTMAX 0x9 /* ${var%%pattern} */
|
||||
#define VSLENGTH 0xa /* ${#var} */
|
||||
|
||||
|
||||
/*
|
||||
* NEOF is returned by parsecmd when it encounters an end of file. It
|
||||
* must be distinct from NULL, so we use the address of a variable that
|
||||
* happens to be handy.
|
||||
*/
|
||||
extern int tokpushback;
|
||||
#define NEOF ((union node *)&tokpushback)
|
||||
extern int whichprompt; /* 1 == PS1, 2 == PS2 */
|
||||
|
||||
|
||||
union node *parsecmd(int);
|
||||
void fixredir(union node *, const char *, int);
|
||||
int goodname(char *);
|
||||
const char *getprompt(void *);
|
||||
389
sh/redir.c
389
sh/redir.c
|
|
@ -1,389 +0,0 @@
|
|||
/* $NetBSD: redir.c,v 1.29 2004/07/08 03:57:33 christos Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1991, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to Berkeley by
|
||||
* Kenneth Almquist.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
#ifndef lint
|
||||
#if 0
|
||||
static char sccsid[] = "@(#)redir.c 8.2 (Berkeley) 5/4/95";
|
||||
#else
|
||||
__RCSID("$NetBSD: redir.c,v 1.29 2004/07/08 03:57:33 christos Exp $");
|
||||
#endif
|
||||
#endif /* not lint */
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/param.h> /* PIPE_BUF */
|
||||
#include <signal.h>
|
||||
#include <string.h>
|
||||
#include <fcntl.h>
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
/*
|
||||
* Code for dealing with input/output redirection.
|
||||
*/
|
||||
|
||||
#include "main.h"
|
||||
#include "shell.h"
|
||||
#include "nodes.h"
|
||||
#include "jobs.h"
|
||||
#include "options.h"
|
||||
#include "expand.h"
|
||||
#include "redir.h"
|
||||
#include "output.h"
|
||||
#include "memalloc.h"
|
||||
#include "error.h"
|
||||
|
||||
|
||||
#define EMPTY -2 /* marks an unused slot in redirtab */
|
||||
#ifndef PIPE_BUF
|
||||
# define PIPESIZE 4096 /* amount of buffering in a pipe */
|
||||
#else
|
||||
# define PIPESIZE PIPE_BUF
|
||||
#endif
|
||||
|
||||
#define signal bsd_signal
|
||||
|
||||
MKINIT
|
||||
struct redirtab {
|
||||
struct redirtab *next;
|
||||
short renamed[10];
|
||||
};
|
||||
|
||||
|
||||
MKINIT struct redirtab *redirlist;
|
||||
|
||||
/*
|
||||
* We keep track of whether or not fd0 has been redirected. This is for
|
||||
* background commands, where we want to redirect fd0 to /dev/null only
|
||||
* if it hasn't already been redirected.
|
||||
*/
|
||||
int fd0_redirected = 0;
|
||||
|
||||
STATIC void openredirect(union node *, char[10], int);
|
||||
STATIC int openhere(union node *);
|
||||
|
||||
|
||||
/*
|
||||
* Process a list of redirection commands. If the REDIR_PUSH flag is set,
|
||||
* old file descriptors are stashed away so that the redirection can be
|
||||
* undone by calling popredir. If the REDIR_BACKQ flag is set, then the
|
||||
* standard output, and the standard error if it becomes a duplicate of
|
||||
* stdout, is saved in memory.
|
||||
*/
|
||||
|
||||
void
|
||||
redirect(union node *redir, int flags)
|
||||
{
|
||||
union node *n;
|
||||
struct redirtab *sv = NULL;
|
||||
int i;
|
||||
int fd;
|
||||
int try;
|
||||
char memory[10]; /* file descriptors to write to memory */
|
||||
|
||||
for (i = 10 ; --i >= 0 ; )
|
||||
memory[i] = 0;
|
||||
memory[1] = flags & REDIR_BACKQ;
|
||||
if (flags & REDIR_PUSH) {
|
||||
/* We don't have to worry about REDIR_VFORK here, as
|
||||
* flags & REDIR_PUSH is never true if REDIR_VFORK is set.
|
||||
*/
|
||||
sv = ckmalloc(sizeof (struct redirtab));
|
||||
for (i = 0 ; i < 10 ; i++)
|
||||
sv->renamed[i] = EMPTY;
|
||||
sv->next = redirlist;
|
||||
redirlist = sv;
|
||||
}
|
||||
for (n = redir ; n ; n = n->nfile.next) {
|
||||
fd = n->nfile.fd;
|
||||
try = 0;
|
||||
if ((n->nfile.type == NTOFD || n->nfile.type == NFROMFD) &&
|
||||
n->ndup.dupfd == fd)
|
||||
continue; /* redirect from/to same file descriptor */
|
||||
|
||||
if ((flags & REDIR_PUSH) && sv->renamed[fd] == EMPTY) {
|
||||
INTOFF;
|
||||
again:
|
||||
if ((i = fcntl(fd, F_DUPFD, 10)) == -1) {
|
||||
switch (errno) {
|
||||
case EBADF:
|
||||
if (!try) {
|
||||
openredirect(n, memory, flags);
|
||||
try++;
|
||||
goto again;
|
||||
}
|
||||
/* FALLTHROUGH*/
|
||||
default:
|
||||
INTON;
|
||||
error("%d: %s", fd, strerror(errno));
|
||||
/* NOTREACHED */
|
||||
}
|
||||
}
|
||||
if (!try) {
|
||||
sv->renamed[fd] = i;
|
||||
close(fd);
|
||||
}
|
||||
INTON;
|
||||
} else {
|
||||
close(fd);
|
||||
}
|
||||
if (fd == 0)
|
||||
fd0_redirected++;
|
||||
if (!try)
|
||||
openredirect(n, memory, flags);
|
||||
}
|
||||
if (memory[1])
|
||||
out1 = &memout;
|
||||
if (memory[2])
|
||||
out2 = &memout;
|
||||
}
|
||||
|
||||
|
||||
STATIC void
|
||||
openredirect(union node *redir, char memory[10], int flags)
|
||||
{
|
||||
int fd = redir->nfile.fd;
|
||||
char *fname;
|
||||
int f;
|
||||
int oflags = O_WRONLY|O_CREAT|O_TRUNC, eflags;
|
||||
|
||||
/*
|
||||
* We suppress interrupts so that we won't leave open file
|
||||
* descriptors around. This may not be such a good idea because
|
||||
* an open of a device or a fifo can block indefinitely.
|
||||
*/
|
||||
INTOFF;
|
||||
memory[fd] = 0;
|
||||
switch (redir->nfile.type) {
|
||||
case NFROM:
|
||||
fname = redir->nfile.expfname;
|
||||
if (flags & REDIR_VFORK)
|
||||
eflags = O_NONBLOCK;
|
||||
else
|
||||
eflags = 0;
|
||||
if ((f = open(fname, O_RDONLY|eflags)) < 0)
|
||||
goto eopen;
|
||||
if (eflags)
|
||||
(void)fcntl(f, F_SETFL, fcntl(f, F_GETFL, 0) & ~eflags);
|
||||
break;
|
||||
case NFROMTO:
|
||||
fname = redir->nfile.expfname;
|
||||
if ((f = open(fname, O_RDWR|O_CREAT|O_TRUNC, 0666)) < 0)
|
||||
goto ecreate;
|
||||
break;
|
||||
case NTO:
|
||||
if (Cflag)
|
||||
oflags |= O_EXCL;
|
||||
/* FALLTHROUGH */
|
||||
case NCLOBBER:
|
||||
fname = redir->nfile.expfname;
|
||||
if ((f = open(fname, oflags, 0666)) < 0)
|
||||
goto ecreate;
|
||||
break;
|
||||
case NAPPEND:
|
||||
fname = redir->nfile.expfname;
|
||||
if ((f = open(fname, O_WRONLY|O_CREAT|O_APPEND, 0666)) < 0)
|
||||
goto ecreate;
|
||||
break;
|
||||
case NTOFD:
|
||||
case NFROMFD:
|
||||
if (redir->ndup.dupfd >= 0) { /* if not ">&-" */
|
||||
if (memory[redir->ndup.dupfd])
|
||||
memory[fd] = 1;
|
||||
else
|
||||
copyfd(redir->ndup.dupfd, fd);
|
||||
}
|
||||
INTON;
|
||||
return;
|
||||
case NHERE:
|
||||
case NXHERE:
|
||||
f = openhere(redir);
|
||||
break;
|
||||
default:
|
||||
abort();
|
||||
}
|
||||
|
||||
if (f != fd) {
|
||||
copyfd(f, fd);
|
||||
close(f);
|
||||
}
|
||||
INTON;
|
||||
return;
|
||||
ecreate:
|
||||
error("cannot create %s: %s", fname, errmsg(errno, E_CREAT));
|
||||
eopen:
|
||||
error("cannot open %s: %s", fname, errmsg(errno, E_OPEN));
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Handle here documents. Normally we fork off a process to write the
|
||||
* data to a pipe. If the document is short, we can stuff the data in
|
||||
* the pipe without forking.
|
||||
*/
|
||||
|
||||
STATIC int
|
||||
openhere(union node *redir)
|
||||
{
|
||||
int pip[2];
|
||||
int len = 0;
|
||||
|
||||
if (pipe(pip) < 0)
|
||||
error("Pipe call failed");
|
||||
if (redir->type == NHERE) {
|
||||
len = strlen(redir->nhere.doc->narg.text);
|
||||
if (len <= PIPESIZE) {
|
||||
xwrite(pip[1], redir->nhere.doc->narg.text, len);
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
if (forkshell((struct job *)NULL, (union node *)NULL, FORK_NOJOB) == 0) {
|
||||
close(pip[0]);
|
||||
signal(SIGINT, SIG_IGN);
|
||||
signal(SIGQUIT, SIG_IGN);
|
||||
signal(SIGHUP, SIG_IGN);
|
||||
#ifdef SIGTSTP
|
||||
signal(SIGTSTP, SIG_IGN);
|
||||
#endif
|
||||
signal(SIGPIPE, SIG_DFL);
|
||||
if (redir->type == NHERE)
|
||||
xwrite(pip[1], redir->nhere.doc->narg.text, len);
|
||||
else
|
||||
expandhere(redir->nhere.doc, pip[1]);
|
||||
_exit(0);
|
||||
}
|
||||
out:
|
||||
close(pip[1]);
|
||||
return pip[0];
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Undo the effects of the last redirection.
|
||||
*/
|
||||
|
||||
void
|
||||
popredir(void)
|
||||
{
|
||||
struct redirtab *rp = redirlist;
|
||||
int i;
|
||||
|
||||
for (i = 0 ; i < 10 ; i++) {
|
||||
if (rp->renamed[i] != EMPTY) {
|
||||
if (i == 0)
|
||||
fd0_redirected--;
|
||||
close(i);
|
||||
if (rp->renamed[i] >= 0) {
|
||||
copyfd(rp->renamed[i], i);
|
||||
close(rp->renamed[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
INTOFF;
|
||||
redirlist = rp->next;
|
||||
ckfree(rp);
|
||||
INTON;
|
||||
}
|
||||
|
||||
/*
|
||||
* Undo all redirections. Called on error or interrupt.
|
||||
*/
|
||||
|
||||
#ifdef mkinit
|
||||
|
||||
INCLUDE "redir.h"
|
||||
|
||||
RESET {
|
||||
while (redirlist)
|
||||
popredir();
|
||||
}
|
||||
|
||||
SHELLPROC {
|
||||
clearredir(0);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/* Return true if fd 0 has already been redirected at least once. */
|
||||
int
|
||||
fd0_redirected_p () {
|
||||
return fd0_redirected != 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Discard all saved file descriptors.
|
||||
*/
|
||||
|
||||
void
|
||||
clearredir(vforked)
|
||||
int vforked;
|
||||
{
|
||||
struct redirtab *rp;
|
||||
int i;
|
||||
|
||||
for (rp = redirlist ; rp ; rp = rp->next) {
|
||||
for (i = 0 ; i < 10 ; i++) {
|
||||
if (rp->renamed[i] >= 0) {
|
||||
close(rp->renamed[i]);
|
||||
}
|
||||
if (!vforked)
|
||||
rp->renamed[i] = EMPTY;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Copy a file descriptor to be >= to. Returns -1
|
||||
* if the source file descriptor is closed, EMPTY if there are no unused
|
||||
* file descriptors left.
|
||||
*/
|
||||
|
||||
int
|
||||
copyfd(int from, int to)
|
||||
{
|
||||
int newfd;
|
||||
|
||||
newfd = fcntl(from, F_DUPFD, to);
|
||||
if (newfd < 0) {
|
||||
if (errno == EMFILE)
|
||||
return EMPTY;
|
||||
else
|
||||
error("%d: %s", from, strerror(errno));
|
||||
}
|
||||
return newfd;
|
||||
}
|
||||
48
sh/redir.h
48
sh/redir.h
|
|
@ -1,48 +0,0 @@
|
|||
/* $NetBSD: redir.h,v 1.15 2003/08/07 09:05:37 agc Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1991, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to Berkeley by
|
||||
* Kenneth Almquist.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)redir.h 8.2 (Berkeley) 5/4/95
|
||||
*/
|
||||
|
||||
/* flags passed to redirect */
|
||||
#define REDIR_PUSH 01 /* save previous values of file descriptors */
|
||||
#define REDIR_BACKQ 02 /* save the command output in memory */
|
||||
#define REDIR_VFORK 04 /* running under vfork(2), be careful */
|
||||
|
||||
union node;
|
||||
void redirect(union node *, int);
|
||||
void popredir(void);
|
||||
int fd0_redirected_p(void);
|
||||
void clearredir(int);
|
||||
int copyfd(int, int);
|
||||
|
||||
83
sh/shell.h
83
sh/shell.h
|
|
@ -1,83 +0,0 @@
|
|||
/* $NetBSD: shell.h,v 1.17 2003/08/07 09:05:38 agc Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1991, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to Berkeley by
|
||||
* Kenneth Almquist.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)shell.h 8.2 (Berkeley) 5/4/95
|
||||
*/
|
||||
|
||||
/*
|
||||
* The follow should be set to reflect the type of system you have:
|
||||
* JOBS -> 1 if you have Berkeley job control, 0 otherwise.
|
||||
* SHORTNAMES -> 1 if your linker cannot handle long names.
|
||||
* define BSD if you are running 4.2 BSD or later.
|
||||
* define SYSV if you are running under System V.
|
||||
* define DEBUG=1 to compile in debugging ('set -o debug' to turn on)
|
||||
* define DEBUG=2 to compile in and turn on debugging.
|
||||
* define DO_SHAREDVFORK to indicate that vfork(2) shares its address
|
||||
* with its parent.
|
||||
*
|
||||
* When debugging is on, debugging info will be written to ./trace and
|
||||
* a quit signal will generate a core dump.
|
||||
*/
|
||||
|
||||
#include <sys/param.h>
|
||||
|
||||
#define JOBS 1
|
||||
#ifndef BSD
|
||||
#define BSD 1
|
||||
#endif
|
||||
|
||||
#ifndef DO_SHAREDVFORK
|
||||
#if __NetBSD_Version__ >= 104000000
|
||||
#define DO_SHAREDVFORK
|
||||
#endif
|
||||
#endif
|
||||
|
||||
typedef void *pointer;
|
||||
#ifndef NULL
|
||||
#define NULL (void *)0
|
||||
#endif
|
||||
#define STATIC /* empty */
|
||||
#define MKINIT /* empty */
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
|
||||
extern char nullstr[1]; /* null string */
|
||||
|
||||
|
||||
#ifdef DEBUG
|
||||
#define TRACE(param) trace param
|
||||
#define TRACEV(param) tracev param
|
||||
#else
|
||||
#define TRACE(param)
|
||||
#define TRACEV(param)
|
||||
#endif
|
||||
425
sh/show.c
425
sh/show.c
|
|
@ -1,425 +0,0 @@
|
|||
/* $NetBSD: show.c,v 1.26 2003/11/14 10:46:13 dsl Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1991, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to Berkeley by
|
||||
* Kenneth Almquist.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
#ifndef lint
|
||||
#if 0
|
||||
static char sccsid[] = "@(#)show.c 8.3 (Berkeley) 5/4/95";
|
||||
#else
|
||||
__RCSID("$NetBSD: show.c,v 1.26 2003/11/14 10:46:13 dsl Exp $");
|
||||
#endif
|
||||
#endif /* not lint */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "shell.h"
|
||||
#include "parser.h"
|
||||
#include "nodes.h"
|
||||
#include "mystring.h"
|
||||
#include "show.h"
|
||||
#include "options.h"
|
||||
|
||||
|
||||
#ifdef DEBUG
|
||||
static void shtree(union node *, int, char *, FILE*);
|
||||
static void shcmd(union node *, FILE *);
|
||||
static void sharg(union node *, FILE *);
|
||||
static void indent(int, char *, FILE *);
|
||||
static void trstring(char *);
|
||||
|
||||
|
||||
void
|
||||
showtree(union node *n)
|
||||
{
|
||||
trputs("showtree called\n");
|
||||
shtree(n, 1, NULL, stdout);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
shtree(union node *n, int ind, char *pfx, FILE *fp)
|
||||
{
|
||||
struct nodelist *lp;
|
||||
const char *s;
|
||||
|
||||
if (n == NULL)
|
||||
return;
|
||||
|
||||
indent(ind, pfx, fp);
|
||||
switch(n->type) {
|
||||
case NSEMI:
|
||||
s = "; ";
|
||||
goto binop;
|
||||
case NAND:
|
||||
s = " && ";
|
||||
goto binop;
|
||||
case NOR:
|
||||
s = " || ";
|
||||
binop:
|
||||
shtree(n->nbinary.ch1, ind, NULL, fp);
|
||||
/* if (ind < 0) */
|
||||
fputs(s, fp);
|
||||
shtree(n->nbinary.ch2, ind, NULL, fp);
|
||||
break;
|
||||
case NCMD:
|
||||
shcmd(n, fp);
|
||||
if (ind >= 0)
|
||||
putc('\n', fp);
|
||||
break;
|
||||
case NPIPE:
|
||||
for (lp = n->npipe.cmdlist ; lp ; lp = lp->next) {
|
||||
shcmd(lp->n, fp);
|
||||
if (lp->next)
|
||||
fputs(" | ", fp);
|
||||
}
|
||||
if (n->npipe.backgnd)
|
||||
fputs(" &", fp);
|
||||
if (ind >= 0)
|
||||
putc('\n', fp);
|
||||
break;
|
||||
default:
|
||||
fprintf(fp, "<node type %d>", n->type);
|
||||
if (ind >= 0)
|
||||
putc('\n', fp);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void
|
||||
shcmd(union node *cmd, FILE *fp)
|
||||
{
|
||||
union node *np;
|
||||
int first;
|
||||
const char *s;
|
||||
int dftfd;
|
||||
|
||||
first = 1;
|
||||
for (np = cmd->ncmd.args ; np ; np = np->narg.next) {
|
||||
if (! first)
|
||||
putchar(' ');
|
||||
sharg(np, fp);
|
||||
first = 0;
|
||||
}
|
||||
for (np = cmd->ncmd.redirect ; np ; np = np->nfile.next) {
|
||||
if (! first)
|
||||
putchar(' ');
|
||||
switch (np->nfile.type) {
|
||||
case NTO: s = ">"; dftfd = 1; break;
|
||||
case NCLOBBER: s = ">|"; dftfd = 1; break;
|
||||
case NAPPEND: s = ">>"; dftfd = 1; break;
|
||||
case NTOFD: s = ">&"; dftfd = 1; break;
|
||||
case NFROM: s = "<"; dftfd = 0; break;
|
||||
case NFROMFD: s = "<&"; dftfd = 0; break;
|
||||
case NFROMTO: s = "<>"; dftfd = 0; break;
|
||||
default: s = "*error*"; dftfd = 0; break;
|
||||
}
|
||||
if (np->nfile.fd != dftfd)
|
||||
fprintf(fp, "%d", np->nfile.fd);
|
||||
fputs(s, fp);
|
||||
if (np->nfile.type == NTOFD || np->nfile.type == NFROMFD) {
|
||||
fprintf(fp, "%d", np->ndup.dupfd);
|
||||
} else {
|
||||
sharg(np->nfile.fname, fp);
|
||||
}
|
||||
first = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void
|
||||
sharg(union node *arg, FILE *fp)
|
||||
{
|
||||
char *p;
|
||||
struct nodelist *bqlist;
|
||||
int subtype;
|
||||
|
||||
if (arg->type != NARG) {
|
||||
printf("<node type %d>\n", arg->type);
|
||||
abort();
|
||||
}
|
||||
bqlist = arg->narg.backquote;
|
||||
for (p = arg->narg.text ; *p ; p++) {
|
||||
switch (*p) {
|
||||
case CTLESC:
|
||||
putc(*++p, fp);
|
||||
break;
|
||||
case CTLVAR:
|
||||
putc('$', fp);
|
||||
putc('{', fp);
|
||||
subtype = *++p;
|
||||
if (subtype == VSLENGTH)
|
||||
putc('#', fp);
|
||||
|
||||
while (*p != '=')
|
||||
putc(*p++, fp);
|
||||
|
||||
if (subtype & VSNUL)
|
||||
putc(':', fp);
|
||||
|
||||
switch (subtype & VSTYPE) {
|
||||
case VSNORMAL:
|
||||
putc('}', fp);
|
||||
break;
|
||||
case VSMINUS:
|
||||
putc('-', fp);
|
||||
break;
|
||||
case VSPLUS:
|
||||
putc('+', fp);
|
||||
break;
|
||||
case VSQUESTION:
|
||||
putc('?', fp);
|
||||
break;
|
||||
case VSASSIGN:
|
||||
putc('=', fp);
|
||||
break;
|
||||
case VSTRIMLEFT:
|
||||
putc('#', fp);
|
||||
break;
|
||||
case VSTRIMLEFTMAX:
|
||||
putc('#', fp);
|
||||
putc('#', fp);
|
||||
break;
|
||||
case VSTRIMRIGHT:
|
||||
putc('%', fp);
|
||||
break;
|
||||
case VSTRIMRIGHTMAX:
|
||||
putc('%', fp);
|
||||
putc('%', fp);
|
||||
break;
|
||||
case VSLENGTH:
|
||||
break;
|
||||
default:
|
||||
printf("<subtype %d>", subtype);
|
||||
}
|
||||
break;
|
||||
case CTLENDVAR:
|
||||
putc('}', fp);
|
||||
break;
|
||||
case CTLBACKQ:
|
||||
case CTLBACKQ|CTLQUOTE:
|
||||
putc('$', fp);
|
||||
putc('(', fp);
|
||||
shtree(bqlist->n, -1, NULL, fp);
|
||||
putc(')', fp);
|
||||
break;
|
||||
default:
|
||||
putc(*p, fp);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
indent(int amount, char *pfx, FILE *fp)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0 ; i < amount ; i++) {
|
||||
if (pfx && i == amount - 1)
|
||||
fputs(pfx, fp);
|
||||
putc('\t', fp);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Debugging stuff.
|
||||
*/
|
||||
|
||||
|
||||
FILE *tracefile;
|
||||
|
||||
|
||||
#ifdef DEBUG
|
||||
void
|
||||
trputc(int c)
|
||||
{
|
||||
if (debug != 1)
|
||||
return;
|
||||
putc(c, tracefile);
|
||||
}
|
||||
#endif
|
||||
|
||||
void
|
||||
trace(const char *fmt, ...)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
va_list va;
|
||||
|
||||
if (debug != 1)
|
||||
return;
|
||||
va_start(va, fmt);
|
||||
(void) vfprintf(tracefile, fmt, va);
|
||||
va_end(va);
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
tracev(const char *fmt, va_list va)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
if (debug != 1)
|
||||
return;
|
||||
(void) vfprintf(tracefile, fmt, va);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
#ifdef DEBUG
|
||||
void
|
||||
trputs(const char *s)
|
||||
{
|
||||
if (debug != 1)
|
||||
return;
|
||||
fputs(s, tracefile);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
trstring(char *s)
|
||||
{
|
||||
char *p;
|
||||
char c;
|
||||
|
||||
if (debug != 1)
|
||||
return;
|
||||
putc('"', tracefile);
|
||||
for (p = s ; *p ; p++) {
|
||||
switch (*p) {
|
||||
case '\n': c = 'n'; goto backslash;
|
||||
case '\t': c = 't'; goto backslash;
|
||||
case '\r': c = 'r'; goto backslash;
|
||||
case '"': c = '"'; goto backslash;
|
||||
case '\\': c = '\\'; goto backslash;
|
||||
case CTLESC: c = 'e'; goto backslash;
|
||||
case CTLVAR: c = 'v'; goto backslash;
|
||||
case CTLVAR+CTLQUOTE: c = 'V'; goto backslash;
|
||||
case CTLBACKQ: c = 'q'; goto backslash;
|
||||
case CTLBACKQ+CTLQUOTE: c = 'Q'; goto backslash;
|
||||
backslash: putc('\\', tracefile);
|
||||
putc(c, tracefile);
|
||||
break;
|
||||
default:
|
||||
if (*p >= ' ' && *p <= '~')
|
||||
putc(*p, tracefile);
|
||||
else {
|
||||
putc('\\', tracefile);
|
||||
putc(*p >> 6 & 03, tracefile);
|
||||
putc(*p >> 3 & 07, tracefile);
|
||||
putc(*p & 07, tracefile);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
putc('"', tracefile);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
void
|
||||
trargs(char **ap)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
if (debug != 1)
|
||||
return;
|
||||
while (*ap) {
|
||||
trstring(*ap++);
|
||||
if (*ap)
|
||||
putc(' ', tracefile);
|
||||
else
|
||||
putc('\n', tracefile);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
#ifdef DEBUG
|
||||
void
|
||||
opentrace(void)
|
||||
{
|
||||
char s[100];
|
||||
#ifdef O_APPEND
|
||||
int flags;
|
||||
#endif
|
||||
|
||||
if (debug != 1) {
|
||||
if (tracefile)
|
||||
fflush(tracefile);
|
||||
/* leave open because libedit might be using it */
|
||||
return;
|
||||
}
|
||||
#ifdef not_this_way
|
||||
{
|
||||
char *p;
|
||||
if ((p = getenv("HOME")) == NULL) {
|
||||
if (geteuid() == 0)
|
||||
p = "/";
|
||||
else
|
||||
p = "/tmp";
|
||||
}
|
||||
scopy(p, s);
|
||||
strcat(s, "/trace");
|
||||
}
|
||||
#else
|
||||
scopy("./trace", s);
|
||||
#endif /* not_this_way */
|
||||
if (tracefile) {
|
||||
if (!freopen(s, "a", tracefile)) {
|
||||
fprintf(stderr, "Can't re-open %s\n", s);
|
||||
debug = 0;
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
if ((tracefile = fopen(s, "a")) == NULL) {
|
||||
fprintf(stderr, "Can't open %s\n", s);
|
||||
debug = 0;
|
||||
return;
|
||||
}
|
||||
}
|
||||
#ifdef O_APPEND
|
||||
if ((flags = fcntl(fileno(tracefile), F_GETFL, 0)) >= 0)
|
||||
fcntl(fileno(tracefile), F_SETFL, flags | O_APPEND);
|
||||
#endif
|
||||
setlinebuf(tracefile);
|
||||
fputs("\nTracing started.\n", tracefile);
|
||||
}
|
||||
#endif /* DEBUG */
|
||||
45
sh/show.h
45
sh/show.h
|
|
@ -1,45 +0,0 @@
|
|||
/* $NetBSD: show.h,v 1.7 2003/08/07 09:05:38 agc Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1995
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)show.h 1.1 (Berkeley) 5/4/95
|
||||
*/
|
||||
|
||||
#include <stdarg.h>
|
||||
|
||||
union node;
|
||||
void showtree(union node *);
|
||||
void trace(const char *, ...);
|
||||
void tracev(const char *, va_list);
|
||||
void trargs(char **);
|
||||
#ifdef DEBUG
|
||||
void trputc(int);
|
||||
void trputs(const char *);
|
||||
void opentrace(void);
|
||||
#endif
|
||||
102
sh/syntax.c
102
sh/syntax.c
|
|
@ -1,102 +0,0 @@
|
|||
/* $NetBSD: syntax.c,v 1.1 2004/01/17 17:38:12 dsl Exp $ */
|
||||
|
||||
#include "shell.h"
|
||||
#include "syntax.h"
|
||||
#include "parser.h"
|
||||
#include <limits.h>
|
||||
|
||||
#if CWORD != 0
|
||||
#error initialisation assumes 'CWORD' is zero
|
||||
#endif
|
||||
|
||||
#define ndx(ch) (ch + 1 - CHAR_MIN)
|
||||
#define set(ch, val) [ndx(ch)] = val,
|
||||
#define set_range(s, e, val) [ndx(s) ... ndx(e)] = val,
|
||||
|
||||
/* syntax table used when not in quotes */
|
||||
const char basesyntax[257] = { CEOF,
|
||||
set_range(CTL_FIRST, CTL_LAST, CCTL)
|
||||
set('\n', CNL)
|
||||
set('\\', CBACK)
|
||||
set('\'', CSQUOTE)
|
||||
set('"', CDQUOTE)
|
||||
set('`', CBQUOTE)
|
||||
set('$', CVAR)
|
||||
set('}', CENDVAR)
|
||||
set('<', CSPCL)
|
||||
set('>', CSPCL)
|
||||
set('(', CSPCL)
|
||||
set(')', CSPCL)
|
||||
set(';', CSPCL)
|
||||
set('&', CSPCL)
|
||||
set('|', CSPCL)
|
||||
set(' ', CSPCL)
|
||||
set('\t', CSPCL)
|
||||
};
|
||||
|
||||
/* syntax table used when in double quotes */
|
||||
const char dqsyntax[257] = { CEOF,
|
||||
set_range(CTL_FIRST, CTL_LAST, CCTL)
|
||||
set('\n', CNL)
|
||||
set('\\', CBACK)
|
||||
set('"', CDQUOTE)
|
||||
set('`', CBQUOTE)
|
||||
set('$', CVAR)
|
||||
set('}', CENDVAR)
|
||||
/* ':/' for tilde expansion, '-' for [a\-x] pattern ranges */
|
||||
set('!', CCTL)
|
||||
set('*', CCTL)
|
||||
set('?', CCTL)
|
||||
set('[', CCTL)
|
||||
set('=', CCTL)
|
||||
set('~', CCTL)
|
||||
set(':', CCTL)
|
||||
set('/', CCTL)
|
||||
set('-', CCTL)
|
||||
};
|
||||
|
||||
/* syntax table used when in single quotes */
|
||||
const char sqsyntax[257] = { CEOF,
|
||||
set_range(CTL_FIRST, CTL_LAST, CCTL)
|
||||
set('\n', CNL)
|
||||
set('\'', CSQUOTE)
|
||||
/* ':/' for tilde expansion, '-' for [a\-x] pattern ranges */
|
||||
set('!', CCTL)
|
||||
set('*', CCTL)
|
||||
set('?', CCTL)
|
||||
set('[', CCTL)
|
||||
set('=', CCTL)
|
||||
set('~', CCTL)
|
||||
set(':', CCTL)
|
||||
set('/', CCTL)
|
||||
set('-', CCTL)
|
||||
};
|
||||
|
||||
/* syntax table used when in arithmetic */
|
||||
const char arisyntax[257] = { CEOF,
|
||||
set_range(CTL_FIRST, CTL_LAST, CCTL)
|
||||
set('\n', CNL)
|
||||
set('\\', CBACK)
|
||||
set('`', CBQUOTE)
|
||||
set('\'', CSQUOTE)
|
||||
set('"', CDQUOTE)
|
||||
set('$', CVAR)
|
||||
set('}', CENDVAR)
|
||||
set('(', CLP)
|
||||
set(')', CRP)
|
||||
};
|
||||
|
||||
/* character classification table */
|
||||
const char is_type[257] = { 0,
|
||||
set_range('0', '9', ISDIGIT)
|
||||
set_range('a', 'z', ISLOWER)
|
||||
set_range('A', 'Z', ISUPPER)
|
||||
set('_', ISUNDER)
|
||||
set('#', ISSPECL)
|
||||
set('?', ISSPECL)
|
||||
set('$', ISSPECL)
|
||||
set('!', ISSPECL)
|
||||
set('-', ISSPECL)
|
||||
set('*', ISSPECL)
|
||||
set('@', ISSPECL)
|
||||
};
|
||||
83
sh/syntax.h
83
sh/syntax.h
|
|
@ -1,83 +0,0 @@
|
|||
/* $NetBSD: syntax.h,v 1.2 2004/01/17 17:38:12 dsl Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1991, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to Berkeley by
|
||||
* Kenneth Almquist.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
#include <ctype.h>
|
||||
|
||||
/* Syntax classes */
|
||||
#define CWORD 0 /* character is nothing special */
|
||||
#define CNL 1 /* newline character */
|
||||
#define CBACK 2 /* a backslash character */
|
||||
#define CSQUOTE 3 /* single quote */
|
||||
#define CDQUOTE 4 /* double quote */
|
||||
#define CBQUOTE 5 /* backwards single quote */
|
||||
#define CVAR 6 /* a dollar sign */
|
||||
#define CENDVAR 7 /* a '}' character */
|
||||
#define CLP 8 /* a left paren in arithmetic */
|
||||
#define CRP 9 /* a right paren in arithmetic */
|
||||
#define CEOF 10 /* end of file */
|
||||
#define CCTL 11 /* like CWORD, except it must be escaped */
|
||||
#define CSPCL 12 /* these terminate a word */
|
||||
|
||||
/* Syntax classes for is_ functions */
|
||||
#define ISDIGIT 01 /* a digit */
|
||||
#define ISUPPER 02 /* an upper case letter */
|
||||
#define ISLOWER 04 /* a lower case letter */
|
||||
#define ISUNDER 010 /* an underscore */
|
||||
#define ISSPECL 020 /* the name of a special parameter */
|
||||
|
||||
#define PEOF (CHAR_MIN - 1)
|
||||
#define SYNBASE (-PEOF)
|
||||
/* XXX UPEOF is CHAR_MAX, so is a valid 'char' value... */
|
||||
#define UPEOF ((char)PEOF)
|
||||
|
||||
|
||||
#define BASESYNTAX (basesyntax + SYNBASE)
|
||||
#define DQSYNTAX (dqsyntax + SYNBASE)
|
||||
#define SQSYNTAX (sqsyntax + SYNBASE)
|
||||
#define ARISYNTAX (arisyntax + SYNBASE)
|
||||
|
||||
/* These defines assume that the digits are contiguous */
|
||||
#define is_digit(c) ((unsigned)((c) - '0') <= 9)
|
||||
#define is_alpha(c) (((char)(c)) != UPEOF && ((c) < CTL_FIRST || (c) > CTL_LAST) && isalpha((unsigned char)(c)))
|
||||
#define is_name(c) (((char)(c)) != UPEOF && ((c) < CTL_FIRST || (c) > CTL_LAST) && ((c) == '_' || isalpha((unsigned char)(c))))
|
||||
#define is_in_name(c) (((char)(c)) != UPEOF && ((c) < CTL_FIRST || (c) > CTL_LAST) && ((c) == '_' || isalnum((unsigned char)(c))))
|
||||
#define is_special(c) ((is_type+SYNBASE)[c] & (ISSPECL|ISDIGIT))
|
||||
#define digit_val(c) ((c) - '0')
|
||||
|
||||
extern const char basesyntax[];
|
||||
extern const char dqsyntax[];
|
||||
extern const char sqsyntax[];
|
||||
extern const char arisyntax[];
|
||||
extern const char is_type[];
|
||||
112
sh/token.h
112
sh/token.h
|
|
@ -1,112 +0,0 @@
|
|||
#define TEOF 0
|
||||
#define TNL 1
|
||||
#define TSEMI 2
|
||||
#define TBACKGND 3
|
||||
#define TAND 4
|
||||
#define TOR 5
|
||||
#define TPIPE 6
|
||||
#define TLP 7
|
||||
#define TRP 8
|
||||
#define TENDCASE 9
|
||||
#define TENDBQUOTE 10
|
||||
#define TREDIR 11
|
||||
#define TWORD 12
|
||||
#define TIF 13
|
||||
#define TTHEN 14
|
||||
#define TELSE 15
|
||||
#define TELIF 16
|
||||
#define TFI 17
|
||||
#define TWHILE 18
|
||||
#define TUNTIL 19
|
||||
#define TFOR 20
|
||||
#define TDO 21
|
||||
#define TDONE 22
|
||||
#define TBEGIN 23
|
||||
#define TEND 24
|
||||
#define TCASE 25
|
||||
#define TESAC 26
|
||||
#define TNOT 27
|
||||
|
||||
/* Array indicating which tokens mark the end of a list */
|
||||
const char tokendlist[] = {
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
1,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
};
|
||||
|
||||
const char *const tokname[] = {
|
||||
"end of file",
|
||||
"newline",
|
||||
"\";\"",
|
||||
"\"&\"",
|
||||
"\"&&\"",
|
||||
"\"||\"",
|
||||
"\"|\"",
|
||||
"\"(\"",
|
||||
"\")\"",
|
||||
"\";;\"",
|
||||
"\"`\"",
|
||||
"redirection",
|
||||
"word",
|
||||
"\"if\"",
|
||||
"\"then\"",
|
||||
"\"else\"",
|
||||
"\"elif\"",
|
||||
"\"fi\"",
|
||||
"\"while\"",
|
||||
"\"until\"",
|
||||
"\"for\"",
|
||||
"\"do\"",
|
||||
"\"done\"",
|
||||
"\"{\"",
|
||||
"\"}\"",
|
||||
"\"case\"",
|
||||
"\"esac\"",
|
||||
"\"!\"",
|
||||
};
|
||||
|
||||
#define KWDOFFSET 13
|
||||
|
||||
const char *const parsekwd[] = {
|
||||
"if",
|
||||
"then",
|
||||
"else",
|
||||
"elif",
|
||||
"fi",
|
||||
"while",
|
||||
"until",
|
||||
"for",
|
||||
"do",
|
||||
"done",
|
||||
"{",
|
||||
"}",
|
||||
"case",
|
||||
"esac",
|
||||
"!",
|
||||
0
|
||||
};
|
||||
456
sh/trap.c
456
sh/trap.c
|
|
@ -1,456 +0,0 @@
|
|||
/* $NetBSD: trap.c,v 1.31 2005/01/11 19:38:57 christos Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1991, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to Berkeley by
|
||||
* Kenneth Almquist.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
#ifndef lint
|
||||
#if 0
|
||||
static char sccsid[] = "@(#)trap.c 8.5 (Berkeley) 6/5/95";
|
||||
#else
|
||||
__RCSID("$NetBSD: trap.c,v 1.31 2005/01/11 19:38:57 christos Exp $");
|
||||
#endif
|
||||
#endif /* not lint */
|
||||
|
||||
#include <signal.h>
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "shell.h"
|
||||
#include "main.h"
|
||||
#include "nodes.h" /* for other headers */
|
||||
#include "eval.h"
|
||||
#include "jobs.h"
|
||||
#include "show.h"
|
||||
#include "options.h"
|
||||
#include "syntax.h"
|
||||
#include "output.h"
|
||||
#include "memalloc.h"
|
||||
#include "error.h"
|
||||
#include "trap.h"
|
||||
#include "mystring.h"
|
||||
#include "var.h"
|
||||
|
||||
/*
|
||||
* Sigmode records the current value of the signal handlers for the various
|
||||
* modes. A value of zero means that the current handler is not known.
|
||||
* S_HARD_IGN indicates that the signal was ignored on entry to the shell,
|
||||
*/
|
||||
|
||||
#define S_DFL 1 /* default signal handling (SIG_DFL) */
|
||||
#define S_CATCH 2 /* signal is caught */
|
||||
#define S_IGN 3 /* signal is ignored (SIG_IGN) */
|
||||
#define S_HARD_IGN 4 /* signal is ignored permenantly */
|
||||
#define S_RESET 5 /* temporary - to reset a hard ignored sig */
|
||||
|
||||
|
||||
char *trap[NSIG+1]; /* trap handler commands */
|
||||
MKINIT char sigmode[NSIG]; /* current value of signal */
|
||||
char gotsig[NSIG]; /* indicates specified signal received */
|
||||
int pendingsigs; /* indicates some signal received */
|
||||
|
||||
static int getsigaction(int, sig_t *);
|
||||
|
||||
/*
|
||||
* return the signal number described by `p' (as a number or a name)
|
||||
* or -1 if it isn't one
|
||||
*/
|
||||
|
||||
static int
|
||||
signame_to_signum(const char *p)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (is_number(p))
|
||||
return number(p);
|
||||
|
||||
if (strcasecmp(p, "exit") == 0 )
|
||||
return 0;
|
||||
|
||||
if (strncasecmp(p, "sig", 3) == 0)
|
||||
p += 3;
|
||||
|
||||
for (i = 0; i < NSIG; ++i)
|
||||
if (sys_signame[i] && (strcasecmp (p, sys_signame[i]) == 0))
|
||||
return i;
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Print a list of valid signal names
|
||||
*/
|
||||
static void
|
||||
printsignals(void)
|
||||
{
|
||||
int n;
|
||||
|
||||
out1str("EXIT ");
|
||||
|
||||
for (n = 1; n < NSIG; n++) {
|
||||
out1fmt("%s", sys_signame[n]);
|
||||
if ((n == NSIG/2) || n == (NSIG - 1))
|
||||
out1str("\n");
|
||||
else
|
||||
out1c(' ');
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* The trap builtin.
|
||||
*/
|
||||
|
||||
int
|
||||
trapcmd(int argc, char **argv)
|
||||
{
|
||||
char *action;
|
||||
char **ap;
|
||||
int signo;
|
||||
|
||||
if (argc <= 1) {
|
||||
for (signo = 0 ; signo <= NSIG ; signo++)
|
||||
if (trap[signo] != NULL) {
|
||||
out1fmt("trap -- ");
|
||||
print_quoted(trap[signo]);
|
||||
out1fmt(" %s\n",
|
||||
(signo) ? sys_signame[signo] : "EXIT");
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
ap = argv + 1;
|
||||
|
||||
action = NULL;
|
||||
|
||||
if (strcmp(*ap, "--") == 0)
|
||||
if (*++ap == NULL)
|
||||
return 0;
|
||||
|
||||
if (signame_to_signum(*ap) == -1) {
|
||||
if ((*ap)[0] == '-') {
|
||||
if ((*ap)[1] == '\0')
|
||||
ap++;
|
||||
else if ((*ap)[1] == 'l' && (*ap)[2] == '\0') {
|
||||
printsignals();
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
error("bad option %s\n", *ap);
|
||||
}
|
||||
else
|
||||
action = *ap++;
|
||||
}
|
||||
|
||||
while (*ap) {
|
||||
if (is_number(*ap))
|
||||
signo = number(*ap);
|
||||
else
|
||||
signo = signame_to_signum(*ap);
|
||||
|
||||
if (signo < 0 || signo > NSIG)
|
||||
error("%s: bad trap", *ap);
|
||||
|
||||
INTOFF;
|
||||
if (action)
|
||||
action = savestr(action);
|
||||
|
||||
if (trap[signo])
|
||||
ckfree(trap[signo]);
|
||||
|
||||
trap[signo] = action;
|
||||
|
||||
if (signo != 0)
|
||||
setsignal(signo, 0);
|
||||
INTON;
|
||||
ap++;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Clear traps on a fork or vfork.
|
||||
* Takes one arg vfork, to tell it to not be destructive of
|
||||
* the parents variables.
|
||||
*/
|
||||
|
||||
void
|
||||
clear_traps(int vforked)
|
||||
{
|
||||
char **tp;
|
||||
|
||||
for (tp = trap ; tp <= &trap[NSIG] ; tp++) {
|
||||
if (*tp && **tp) { /* trap not NULL or SIG_IGN */
|
||||
INTOFF;
|
||||
if (!vforked) {
|
||||
ckfree(*tp);
|
||||
*tp = NULL;
|
||||
}
|
||||
if (tp != &trap[0])
|
||||
setsignal(tp - trap, vforked);
|
||||
INTON;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Set the signal handler for the specified signal. The routine figures
|
||||
* out what it should be set to.
|
||||
*/
|
||||
|
||||
long
|
||||
setsignal(int signo, int vforked)
|
||||
{
|
||||
int action;
|
||||
sig_t sigact = SIG_DFL;
|
||||
struct sigaction act, oact;
|
||||
char *t, tsig;
|
||||
|
||||
if ((t = trap[signo]) == NULL)
|
||||
action = S_DFL;
|
||||
else if (*t != '\0')
|
||||
action = S_CATCH;
|
||||
else
|
||||
action = S_IGN;
|
||||
if (rootshell && !vforked && action == S_DFL) {
|
||||
switch (signo) {
|
||||
case SIGINT:
|
||||
if (iflag || minusc || sflag == 0)
|
||||
action = S_CATCH;
|
||||
break;
|
||||
case SIGQUIT:
|
||||
#ifdef DEBUG
|
||||
if (debug)
|
||||
break;
|
||||
#endif
|
||||
/* FALLTHROUGH */
|
||||
case SIGTERM:
|
||||
if (iflag)
|
||||
action = S_IGN;
|
||||
break;
|
||||
#if JOBS
|
||||
case SIGTSTP:
|
||||
case SIGTTOU:
|
||||
if (mflag)
|
||||
action = S_IGN;
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
t = &sigmode[signo - 1];
|
||||
tsig = *t;
|
||||
if (tsig == 0) {
|
||||
/*
|
||||
* current setting unknown
|
||||
*/
|
||||
if (!getsigaction(signo, &sigact)) {
|
||||
/*
|
||||
* Pretend it worked; maybe we should give a warning
|
||||
* here, but other shells don't. We don't alter
|
||||
* sigmode, so that we retry every time.
|
||||
*/
|
||||
return 0;
|
||||
}
|
||||
if (sigact == SIG_IGN) {
|
||||
if (mflag && (signo == SIGTSTP ||
|
||||
signo == SIGTTIN || signo == SIGTTOU)) {
|
||||
tsig = S_IGN; /* don't hard ignore these */
|
||||
} else
|
||||
tsig = S_HARD_IGN;
|
||||
} else {
|
||||
tsig = S_RESET; /* force to be set */
|
||||
}
|
||||
}
|
||||
if (tsig == S_HARD_IGN || tsig == action)
|
||||
return 0;
|
||||
switch (action) {
|
||||
case S_DFL: sigact = SIG_DFL; break;
|
||||
case S_CATCH: sigact = onsig; break;
|
||||
case S_IGN: sigact = SIG_IGN; break;
|
||||
}
|
||||
if (!vforked)
|
||||
*t = action;
|
||||
act.sa_handler = sigact;
|
||||
sigemptyset(&act.sa_mask);
|
||||
act.sa_flags = 0;
|
||||
#ifdef SA_INTERRUPT
|
||||
act.sa_flags |= SA_INTERRUPT;
|
||||
#endif
|
||||
if(sigaction(signo, &act, &oact) < 0)
|
||||
return (long) SIG_ERR;
|
||||
return (long) oact.sa_handler;
|
||||
}
|
||||
|
||||
/*
|
||||
* Return the current setting for sig w/o changing it.
|
||||
*/
|
||||
static int
|
||||
getsigaction(int signo, sig_t *sigact)
|
||||
{
|
||||
struct sigaction sa;
|
||||
|
||||
if (sigaction(signo, (struct sigaction *)0, &sa) == -1)
|
||||
return 0;
|
||||
*sigact = (sig_t) sa.sa_handler;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Ignore a signal.
|
||||
*/
|
||||
|
||||
void
|
||||
ignoresig(int signo, int vforked)
|
||||
{
|
||||
if (sigmode[signo - 1] != S_IGN && sigmode[signo - 1] != S_HARD_IGN)
|
||||
bsd_signal(signo, SIG_IGN);
|
||||
if (!vforked)
|
||||
sigmode[signo - 1] = S_HARD_IGN;
|
||||
}
|
||||
|
||||
|
||||
#ifdef mkinit
|
||||
INCLUDE <signal.h>
|
||||
INCLUDE "trap.h"
|
||||
|
||||
SHELLPROC {
|
||||
char *sm;
|
||||
|
||||
clear_traps(0);
|
||||
for (sm = sigmode ; sm < sigmode + NSIG ; sm++) {
|
||||
if (*sm == S_IGN)
|
||||
*sm = S_HARD_IGN;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Signal handler.
|
||||
*/
|
||||
|
||||
void
|
||||
onsig(int signo)
|
||||
{
|
||||
bsd_signal(signo, onsig);
|
||||
if (signo == SIGINT && trap[SIGINT] == NULL) {
|
||||
onint();
|
||||
return;
|
||||
}
|
||||
gotsig[signo - 1] = 1;
|
||||
pendingsigs++;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Called to execute a trap. Perhaps we should avoid entering new trap
|
||||
* handlers while we are executing a trap handler.
|
||||
*/
|
||||
|
||||
void
|
||||
dotrap(void)
|
||||
{
|
||||
int i;
|
||||
int savestatus;
|
||||
|
||||
for (;;) {
|
||||
for (i = 1 ; ; i++) {
|
||||
if (gotsig[i - 1])
|
||||
break;
|
||||
if (i >= NSIG)
|
||||
goto done;
|
||||
}
|
||||
gotsig[i - 1] = 0;
|
||||
savestatus=exitstatus;
|
||||
evalstring(trap[i], 0);
|
||||
exitstatus=savestatus;
|
||||
}
|
||||
done:
|
||||
pendingsigs = 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Controls whether the shell is interactive or not.
|
||||
*/
|
||||
|
||||
|
||||
void
|
||||
setinteractive(int on)
|
||||
{
|
||||
static int is_interactive;
|
||||
|
||||
if (on == is_interactive)
|
||||
return;
|
||||
setsignal(SIGINT, 0);
|
||||
setsignal(SIGQUIT, 0);
|
||||
setsignal(SIGTERM, 0);
|
||||
is_interactive = on;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Called to exit the shell.
|
||||
*/
|
||||
|
||||
void
|
||||
exitshell(int status)
|
||||
{
|
||||
struct jmploc loc1, loc2;
|
||||
char *p;
|
||||
|
||||
TRACE(("pid %d, exitshell(%d)\n", getpid(), status));
|
||||
if (setjmp(loc1.loc)) {
|
||||
goto l1;
|
||||
}
|
||||
if (setjmp(loc2.loc)) {
|
||||
goto l2;
|
||||
}
|
||||
handler = &loc1;
|
||||
if ((p = trap[0]) != NULL && *p != '\0') {
|
||||
trap[0] = NULL;
|
||||
evalstring(p, 0);
|
||||
}
|
||||
l1: handler = &loc2; /* probably unnecessary */
|
||||
flushall();
|
||||
#if JOBS
|
||||
setjobctl(0);
|
||||
#endif
|
||||
l2: _exit(status);
|
||||
/* NOTREACHED */
|
||||
}
|
||||
46
sh/trap.h
46
sh/trap.h
|
|
@ -1,46 +0,0 @@
|
|||
/* $NetBSD: trap.h,v 1.17 2003/08/07 09:05:39 agc Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1991, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to Berkeley by
|
||||
* Kenneth Almquist.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)trap.h 8.3 (Berkeley) 6/5/95
|
||||
*/
|
||||
|
||||
extern int pendingsigs;
|
||||
|
||||
int trapcmd(int, char **);
|
||||
void clear_traps(int);
|
||||
long setsignal(int, int);
|
||||
void ignoresig(int, int);
|
||||
void onsig(int);
|
||||
void dotrap(void);
|
||||
void setinteractive(int);
|
||||
void exitshell(int) __attribute__((__noreturn__));
|
||||
825
sh/var.c
825
sh/var.c
|
|
@ -1,825 +0,0 @@
|
|||
/* $NetBSD: var.c,v 1.36 2004/10/06 10:23:43 enami Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1991, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to Berkeley by
|
||||
* Kenneth Almquist.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
#ifndef lint
|
||||
#if 0
|
||||
static char sccsid[] = "@(#)var.c 8.3 (Berkeley) 5/4/95";
|
||||
#else
|
||||
__RCSID("$NetBSD: var.c,v 1.36 2004/10/06 10:23:43 enami Exp $");
|
||||
#endif
|
||||
#endif /* not lint */
|
||||
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
#include <paths.h>
|
||||
|
||||
/*
|
||||
* Shell variables.
|
||||
*/
|
||||
|
||||
#include "shell.h"
|
||||
#include "output.h"
|
||||
#include "expand.h"
|
||||
#include "nodes.h" /* for other headers */
|
||||
#include "eval.h" /* defines cmdenviron */
|
||||
#include "exec.h"
|
||||
#include "syntax.h"
|
||||
#include "options.h"
|
||||
#include "var.h"
|
||||
#include "memalloc.h"
|
||||
#include "error.h"
|
||||
#include "mystring.h"
|
||||
#include "parser.h"
|
||||
#include "show.h"
|
||||
#ifndef SMALL
|
||||
#include "myhistedit.h"
|
||||
#endif
|
||||
|
||||
#ifdef SMALL
|
||||
#define VTABSIZE 39
|
||||
#else
|
||||
#define VTABSIZE 517
|
||||
#endif
|
||||
|
||||
|
||||
struct varinit {
|
||||
struct var *var;
|
||||
int flags;
|
||||
const char *text;
|
||||
void (*func)(const char *);
|
||||
};
|
||||
|
||||
|
||||
#if ATTY
|
||||
struct var vatty;
|
||||
#endif
|
||||
#ifdef WITH_HISTORY
|
||||
struct var vhistsize;
|
||||
struct var vterm;
|
||||
#endif
|
||||
struct var vifs;
|
||||
struct var vmpath;
|
||||
struct var vpath;
|
||||
struct var vps1;
|
||||
struct var vps2;
|
||||
struct var vps4;
|
||||
struct var vvers;
|
||||
struct var voptind;
|
||||
|
||||
const struct varinit varinit[] = {
|
||||
#if ATTY
|
||||
{ &vatty, VSTRFIXED|VTEXTFIXED|VUNSET, "ATTY=",
|
||||
NULL },
|
||||
#endif
|
||||
#ifdef WITH_HISTORY
|
||||
{ &vhistsize, VSTRFIXED|VTEXTFIXED|VUNSET, "HISTSIZE=",
|
||||
sethistsize },
|
||||
#endif
|
||||
{ &vifs, VSTRFIXED|VTEXTFIXED, "IFS= \t\n",
|
||||
NULL },
|
||||
{ &vmpath, VSTRFIXED|VTEXTFIXED|VUNSET, "MAILPATH=",
|
||||
NULL },
|
||||
{ &vpath, VSTRFIXED|VTEXTFIXED, "PATH=" _PATH_DEFPATH,
|
||||
changepath },
|
||||
/*
|
||||
* vps1 depends on uid
|
||||
*/
|
||||
{ &vps2, VSTRFIXED|VTEXTFIXED, "PS2=> ",
|
||||
NULL },
|
||||
{ &vps4, VSTRFIXED|VTEXTFIXED, "PS4=+ ",
|
||||
NULL },
|
||||
#ifdef WITH_HISTORY
|
||||
{ &vterm, VSTRFIXED|VTEXTFIXED|VUNSET, "TERM=",
|
||||
setterm },
|
||||
#endif
|
||||
{ &voptind, VSTRFIXED|VTEXTFIXED|VNOFUNC, "OPTIND=1",
|
||||
getoptsreset },
|
||||
{ NULL, 0, NULL,
|
||||
NULL }
|
||||
};
|
||||
|
||||
struct var *vartab[VTABSIZE];
|
||||
|
||||
STATIC int strequal(const char *, const char *);
|
||||
STATIC struct var *find_var(const char *, struct var ***, int *);
|
||||
|
||||
/*
|
||||
* Initialize the varable symbol tables and import the environment
|
||||
*/
|
||||
|
||||
#ifdef mkinit
|
||||
INCLUDE "var.h"
|
||||
MKINIT char **environ;
|
||||
INIT {
|
||||
char **envp;
|
||||
|
||||
initvar();
|
||||
for (envp = environ ; *envp ; envp++) {
|
||||
if (strchr(*envp, '=')) {
|
||||
setvareq(*envp, VEXPORT|VTEXTFIXED);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
* This routine initializes the builtin variables. It is called when the
|
||||
* shell is initialized and again when a shell procedure is spawned.
|
||||
*/
|
||||
|
||||
void
|
||||
initvar(void)
|
||||
{
|
||||
const struct varinit *ip;
|
||||
struct var *vp;
|
||||
struct var **vpp;
|
||||
|
||||
for (ip = varinit ; (vp = ip->var) != NULL ; ip++) {
|
||||
if (find_var(ip->text, &vpp, &vp->name_len) != NULL)
|
||||
continue;
|
||||
vp->next = *vpp;
|
||||
*vpp = vp;
|
||||
vp->text = strdup(ip->text);
|
||||
vp->flags = ip->flags;
|
||||
vp->func = ip->func;
|
||||
}
|
||||
/*
|
||||
* PS1 depends on uid
|
||||
*/
|
||||
if (find_var("PS1", &vpp, &vps1.name_len) == NULL) {
|
||||
vps1.next = *vpp;
|
||||
*vpp = &vps1;
|
||||
vps1.text = strdup(geteuid() ? "PS1=$ " : "PS1=# ");
|
||||
vps1.flags = VSTRFIXED|VTEXTFIXED;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Safe version of setvar, returns 1 on success 0 on failure.
|
||||
*/
|
||||
|
||||
int
|
||||
setvarsafe(const char *name, const char *val, int flags)
|
||||
{
|
||||
struct jmploc jmploc;
|
||||
struct jmploc *volatile savehandler = handler;
|
||||
int err = 0;
|
||||
#ifdef __GNUC__
|
||||
(void) &err;
|
||||
#endif
|
||||
|
||||
if (setjmp(jmploc.loc))
|
||||
err = 1;
|
||||
else {
|
||||
handler = &jmploc;
|
||||
setvar(name, val, flags);
|
||||
}
|
||||
handler = savehandler;
|
||||
return err;
|
||||
}
|
||||
|
||||
/*
|
||||
* Set the value of a variable. The flags argument is ored with the
|
||||
* flags of the variable. If val is NULL, the variable is unset.
|
||||
*/
|
||||
|
||||
void
|
||||
setvar(const char *name, const char *val, int flags)
|
||||
{
|
||||
const char *p;
|
||||
const char *q;
|
||||
char *d;
|
||||
int len;
|
||||
int namelen;
|
||||
char *nameeq;
|
||||
int isbad;
|
||||
|
||||
isbad = 0;
|
||||
p = name;
|
||||
if (! is_name(*p))
|
||||
isbad = 1;
|
||||
p++;
|
||||
for (;;) {
|
||||
if (! is_in_name(*p)) {
|
||||
if (*p == '\0' || *p == '=')
|
||||
break;
|
||||
isbad = 1;
|
||||
}
|
||||
p++;
|
||||
}
|
||||
namelen = p - name;
|
||||
if (isbad)
|
||||
error("%.*s: bad variable name", namelen, name);
|
||||
len = namelen + 2; /* 2 is space for '=' and '\0' */
|
||||
if (val == NULL) {
|
||||
flags |= VUNSET;
|
||||
} else {
|
||||
len += strlen(val);
|
||||
}
|
||||
d = nameeq = ckmalloc(len);
|
||||
q = name;
|
||||
while (--namelen >= 0)
|
||||
*d++ = *q++;
|
||||
*d++ = '=';
|
||||
*d = '\0';
|
||||
if (val)
|
||||
scopy(val, d);
|
||||
setvareq(nameeq, flags);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Same as setvar except that the variable and value are passed in
|
||||
* the first argument as name=value. Since the first argument will
|
||||
* be actually stored in the table, it should not be a string that
|
||||
* will go away.
|
||||
*/
|
||||
|
||||
void
|
||||
setvareq(char *s, int flags)
|
||||
{
|
||||
struct var *vp, **vpp;
|
||||
int nlen;
|
||||
|
||||
if (aflag)
|
||||
flags |= VEXPORT;
|
||||
vp = find_var(s, &vpp, &nlen);
|
||||
if (vp != NULL) {
|
||||
if (vp->flags & VREADONLY)
|
||||
error("%.*s: is read only", vp->name_len, s);
|
||||
if (flags & VNOSET)
|
||||
return;
|
||||
INTOFF;
|
||||
|
||||
if (vp->func && (flags & VNOFUNC) == 0)
|
||||
(*vp->func)(s + vp->name_len + 1);
|
||||
|
||||
if ((vp->flags & (VTEXTFIXED|VSTACK)) == 0)
|
||||
ckfree(vp->text);
|
||||
|
||||
vp->flags &= ~(VTEXTFIXED|VSTACK|VUNSET);
|
||||
vp->flags |= flags & ~VNOFUNC;
|
||||
vp->text = s;
|
||||
|
||||
INTON;
|
||||
return;
|
||||
}
|
||||
/* not found */
|
||||
if (flags & VNOSET)
|
||||
return;
|
||||
vp = ckmalloc(sizeof (*vp));
|
||||
vp->flags = flags & ~VNOFUNC;
|
||||
vp->text = s;
|
||||
vp->name_len = nlen;
|
||||
vp->next = *vpp;
|
||||
vp->func = NULL;
|
||||
*vpp = vp;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Process a linked list of variable assignments.
|
||||
*/
|
||||
|
||||
void
|
||||
listsetvar(struct strlist *list, int flags)
|
||||
{
|
||||
struct strlist *lp;
|
||||
|
||||
INTOFF;
|
||||
for (lp = list ; lp ; lp = lp->next) {
|
||||
setvareq(savestr(lp->text), flags);
|
||||
}
|
||||
INTON;
|
||||
}
|
||||
|
||||
void
|
||||
listmklocal(struct strlist *list, int flags)
|
||||
{
|
||||
struct strlist *lp;
|
||||
|
||||
for (lp = list ; lp ; lp = lp->next)
|
||||
mklocal(lp->text, flags);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Find the value of a variable. Returns NULL if not set.
|
||||
*/
|
||||
|
||||
char *
|
||||
lookupvar(const char *name)
|
||||
{
|
||||
struct var *v;
|
||||
|
||||
v = find_var(name, NULL, NULL);
|
||||
if (v == NULL || v->flags & VUNSET)
|
||||
return NULL;
|
||||
return v->text + v->name_len + 1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Search the environment of a builtin command. If the second argument
|
||||
* is nonzero, return the value of a variable even if it hasn't been
|
||||
* exported.
|
||||
*/
|
||||
|
||||
char *
|
||||
bltinlookup(const char *name, int doall)
|
||||
{
|
||||
struct strlist *sp;
|
||||
struct var *v;
|
||||
|
||||
for (sp = cmdenviron ; sp ; sp = sp->next) {
|
||||
if (strequal(sp->text, name))
|
||||
return strchr(sp->text, '=') + 1;
|
||||
}
|
||||
|
||||
v = find_var(name, NULL, NULL);
|
||||
|
||||
if (v == NULL || v->flags & VUNSET || (!doall && !(v->flags & VEXPORT)))
|
||||
return NULL;
|
||||
return v->text + v->name_len + 1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Generate a list of exported variables. This routine is used to construct
|
||||
* the third argument to execve when executing a program.
|
||||
*/
|
||||
|
||||
char **
|
||||
environment(void)
|
||||
{
|
||||
int nenv;
|
||||
struct var **vpp;
|
||||
struct var *vp;
|
||||
char **env;
|
||||
char **ep;
|
||||
|
||||
nenv = 0;
|
||||
for (vpp = vartab ; vpp < vartab + VTABSIZE ; vpp++) {
|
||||
for (vp = *vpp ; vp ; vp = vp->next)
|
||||
if (vp->flags & VEXPORT)
|
||||
nenv++;
|
||||
}
|
||||
ep = env = stalloc((nenv + 1) * sizeof *env);
|
||||
for (vpp = vartab ; vpp < vartab + VTABSIZE ; vpp++) {
|
||||
for (vp = *vpp ; vp ; vp = vp->next)
|
||||
if (vp->flags & VEXPORT)
|
||||
*ep++ = vp->text;
|
||||
}
|
||||
*ep = NULL;
|
||||
return env;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Called when a shell procedure is invoked to clear out nonexported
|
||||
* variables. It is also necessary to reallocate variables of with
|
||||
* VSTACK set since these are currently allocated on the stack.
|
||||
*/
|
||||
|
||||
#ifdef mkinit
|
||||
void shprocvar(void);
|
||||
|
||||
SHELLPROC {
|
||||
shprocvar();
|
||||
}
|
||||
#endif
|
||||
|
||||
void
|
||||
shprocvar(void)
|
||||
{
|
||||
struct var **vpp;
|
||||
struct var *vp, **prev;
|
||||
|
||||
for (vpp = vartab ; vpp < vartab + VTABSIZE ; vpp++) {
|
||||
for (prev = vpp ; (vp = *prev) != NULL ; ) {
|
||||
if ((vp->flags & VEXPORT) == 0) {
|
||||
*prev = vp->next;
|
||||
if ((vp->flags & VTEXTFIXED) == 0)
|
||||
ckfree(vp->text);
|
||||
if ((vp->flags & VSTRFIXED) == 0)
|
||||
ckfree(vp);
|
||||
} else {
|
||||
if (vp->flags & VSTACK) {
|
||||
vp->text = savestr(vp->text);
|
||||
vp->flags &=~ VSTACK;
|
||||
}
|
||||
prev = &vp->next;
|
||||
}
|
||||
}
|
||||
}
|
||||
initvar();
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Command to list all variables which are set. Currently this command
|
||||
* is invoked from the set command when the set command is called without
|
||||
* any variables.
|
||||
*/
|
||||
|
||||
void
|
||||
print_quoted(const char *p)
|
||||
{
|
||||
const char *q;
|
||||
|
||||
if (strcspn(p, "|&;<>()$`\\\"' \t\n*?[]#~=%") == strlen(p)) {
|
||||
out1fmt("%s", p);
|
||||
return;
|
||||
}
|
||||
while (*p) {
|
||||
if (*p == '\'') {
|
||||
out1fmt("\\'");
|
||||
p++;
|
||||
continue;
|
||||
}
|
||||
q = index(p, '\'');
|
||||
if (!q) {
|
||||
out1fmt("'%s'", p );
|
||||
return;
|
||||
}
|
||||
out1fmt("'%.*s'", (int)(q - p), p );
|
||||
p = q;
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
sort_var(const void *v_v1, const void *v_v2)
|
||||
{
|
||||
const struct var * const *v1 = v_v1;
|
||||
const struct var * const *v2 = v_v2;
|
||||
|
||||
/* XXX Will anyone notice we include the '=' of the shorter name? */
|
||||
return strcmp((*v1)->text, (*v2)->text);
|
||||
}
|
||||
|
||||
/*
|
||||
* POSIX requires that 'set' (but not export or readonly) output the
|
||||
* variables in lexicographic order - by the locale's collating order (sigh).
|
||||
* Maybe we could keep them in an ordered balanced binary tree
|
||||
* instead of hashed lists.
|
||||
* For now just roll 'em through qsort for printing...
|
||||
*/
|
||||
|
||||
int
|
||||
showvars(const char *name, int flag, int show_value)
|
||||
{
|
||||
struct var **vpp;
|
||||
struct var *vp;
|
||||
const char *p;
|
||||
|
||||
static struct var **list; /* static in case we are interrupted */
|
||||
static int list_len;
|
||||
int count = 0;
|
||||
|
||||
if (!list) {
|
||||
list_len = 32;
|
||||
list = ckmalloc(list_len * sizeof *list);
|
||||
}
|
||||
|
||||
for (vpp = vartab ; vpp < vartab + VTABSIZE ; vpp++) {
|
||||
for (vp = *vpp ; vp ; vp = vp->next) {
|
||||
if (flag && !(vp->flags & flag))
|
||||
continue;
|
||||
if (vp->flags & VUNSET && !(show_value & 2))
|
||||
continue;
|
||||
if (count >= list_len) {
|
||||
list = ckrealloc(list,
|
||||
(list_len << 1) * sizeof *list);
|
||||
list_len <<= 1;
|
||||
}
|
||||
list[count++] = vp;
|
||||
}
|
||||
}
|
||||
|
||||
qsort(list, count, sizeof *list, sort_var);
|
||||
|
||||
for (vpp = list; count--; vpp++) {
|
||||
vp = *vpp;
|
||||
if (name)
|
||||
out1fmt("%s ", name);
|
||||
for (p = vp->text ; *p != '=' ; p++)
|
||||
out1c(*p);
|
||||
if (!(vp->flags & VUNSET) && show_value) {
|
||||
out1fmt("=");
|
||||
print_quoted(++p);
|
||||
}
|
||||
out1c('\n');
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* The export and readonly commands.
|
||||
*/
|
||||
|
||||
int
|
||||
exportcmd(int argc, char **argv)
|
||||
{
|
||||
struct var *vp;
|
||||
char *name;
|
||||
const char *p;
|
||||
int flag = argv[0][0] == 'r'? VREADONLY : VEXPORT;
|
||||
int pflag;
|
||||
|
||||
pflag = nextopt("p") == 'p' ? 3 : 0;
|
||||
if (argc <= 1 || pflag) {
|
||||
showvars( pflag ? argv[0] : 0, flag, pflag );
|
||||
return 0;
|
||||
}
|
||||
|
||||
while ((name = *argptr++) != NULL) {
|
||||
if ((p = strchr(name, '=')) != NULL) {
|
||||
p++;
|
||||
} else {
|
||||
vp = find_var(name, NULL, NULL);
|
||||
if (vp != NULL) {
|
||||
vp->flags |= flag;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
setvar(name, p, flag);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* The "local" command.
|
||||
*/
|
||||
|
||||
int
|
||||
localcmd(int argc, char **argv)
|
||||
{
|
||||
char *name;
|
||||
|
||||
if (! in_function())
|
||||
error("Not in a function");
|
||||
while ((name = *argptr++) != NULL) {
|
||||
mklocal(name, 0);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Make a variable a local variable. When a variable is made local, it's
|
||||
* value and flags are saved in a localvar structure. The saved values
|
||||
* will be restored when the shell function returns. We handle the name
|
||||
* "-" as a special case.
|
||||
*/
|
||||
|
||||
void
|
||||
mklocal(const char *name, int flags)
|
||||
{
|
||||
struct localvar *lvp;
|
||||
struct var **vpp;
|
||||
struct var *vp;
|
||||
|
||||
INTOFF;
|
||||
lvp = ckmalloc(sizeof (struct localvar));
|
||||
if (name[0] == '-' && name[1] == '\0') {
|
||||
char *p;
|
||||
p = ckmalloc(sizeof_optlist);
|
||||
lvp->text = memcpy(p, optlist, sizeof_optlist);
|
||||
vp = NULL;
|
||||
} else {
|
||||
vp = find_var(name, &vpp, NULL);
|
||||
if (vp == NULL) {
|
||||
if (strchr(name, '='))
|
||||
setvareq(savestr(name), VSTRFIXED|flags);
|
||||
else
|
||||
setvar(name, NULL, VSTRFIXED|flags);
|
||||
vp = *vpp; /* the new variable */
|
||||
lvp->text = NULL;
|
||||
lvp->flags = VUNSET;
|
||||
} else {
|
||||
lvp->text = vp->text;
|
||||
lvp->flags = vp->flags;
|
||||
vp->flags |= VSTRFIXED|VTEXTFIXED;
|
||||
if (name[vp->name_len] == '=')
|
||||
setvareq(savestr(name), flags);
|
||||
}
|
||||
}
|
||||
lvp->vp = vp;
|
||||
lvp->next = localvars;
|
||||
localvars = lvp;
|
||||
INTON;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Called after a function returns.
|
||||
*/
|
||||
|
||||
void
|
||||
poplocalvars(void)
|
||||
{
|
||||
struct localvar *lvp;
|
||||
struct var *vp;
|
||||
|
||||
while ((lvp = localvars) != NULL) {
|
||||
localvars = lvp->next;
|
||||
vp = lvp->vp;
|
||||
TRACE(("poplocalvar %s", vp ? vp->text : "-"));
|
||||
if (vp == NULL) { /* $- saved */
|
||||
memcpy(optlist, lvp->text, sizeof_optlist);
|
||||
ckfree(lvp->text);
|
||||
} else if ((lvp->flags & (VUNSET|VSTRFIXED)) == VUNSET) {
|
||||
(void)unsetvar(vp->text, 0);
|
||||
} else {
|
||||
if (vp->func && (vp->flags & VNOFUNC) == 0)
|
||||
(*vp->func)(lvp->text + vp->name_len + 1);
|
||||
if ((vp->flags & VTEXTFIXED) == 0)
|
||||
ckfree(vp->text);
|
||||
vp->flags = lvp->flags;
|
||||
vp->text = lvp->text;
|
||||
}
|
||||
ckfree(lvp);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
setvarcmd(int argc, char **argv)
|
||||
{
|
||||
if (argc <= 2)
|
||||
return unsetcmd(argc, argv);
|
||||
else if (argc == 3)
|
||||
setvar(argv[1], argv[2], 0);
|
||||
else
|
||||
error("List assignment not implemented");
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* The unset builtin command. We unset the function before we unset the
|
||||
* variable to allow a function to be unset when there is a readonly variable
|
||||
* with the same name.
|
||||
*/
|
||||
|
||||
int
|
||||
unsetcmd(int argc, char **argv)
|
||||
{
|
||||
char **ap;
|
||||
int i;
|
||||
int flg_func = 0;
|
||||
int flg_var = 0;
|
||||
int ret = 0;
|
||||
|
||||
while ((i = nextopt("evf")) != '\0') {
|
||||
if (i == 'f')
|
||||
flg_func = 1;
|
||||
else
|
||||
flg_var = i;
|
||||
}
|
||||
if (flg_func == 0 && flg_var == 0)
|
||||
flg_var = 1;
|
||||
|
||||
for (ap = argptr; *ap ; ap++) {
|
||||
if (flg_func)
|
||||
ret |= unsetfunc(*ap);
|
||||
if (flg_var)
|
||||
ret |= unsetvar(*ap, flg_var == 'e');
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Unset the specified variable.
|
||||
*/
|
||||
|
||||
int
|
||||
unsetvar(const char *s, int unexport)
|
||||
{
|
||||
struct var **vpp;
|
||||
struct var *vp;
|
||||
|
||||
vp = find_var(s, &vpp, NULL);
|
||||
if (vp == NULL)
|
||||
return 1;
|
||||
|
||||
if (vp->flags & VREADONLY)
|
||||
return (1);
|
||||
|
||||
INTOFF;
|
||||
if (unexport) {
|
||||
vp->flags &= ~VEXPORT;
|
||||
} else {
|
||||
if (vp->text[vp->name_len + 1] != '\0')
|
||||
setvar(s, nullstr, 0);
|
||||
vp->flags &= ~VEXPORT;
|
||||
vp->flags |= VUNSET;
|
||||
if ((vp->flags & VSTRFIXED) == 0) {
|
||||
if ((vp->flags & VTEXTFIXED) == 0)
|
||||
ckfree(vp->text);
|
||||
*vpp = vp->next;
|
||||
ckfree(vp);
|
||||
}
|
||||
}
|
||||
INTON;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Returns true if the two strings specify the same varable. The first
|
||||
* variable name is terminated by '='; the second may be terminated by
|
||||
* either '=' or '\0'.
|
||||
*/
|
||||
|
||||
STATIC int
|
||||
strequal(const char *p, const char *q)
|
||||
{
|
||||
while (*p == *q++) {
|
||||
if (*p++ == '=')
|
||||
return 1;
|
||||
}
|
||||
if (*p == '=' && *(q - 1) == '\0')
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Search for a variable.
|
||||
* 'name' may be terminated by '=' or a NUL.
|
||||
* vppp is set to the pointer to vp, or the list head if vp isn't found
|
||||
* lenp is set to the number of charactets in 'name'
|
||||
*/
|
||||
|
||||
STATIC struct var *
|
||||
find_var(const char *name, struct var ***vppp, int *lenp)
|
||||
{
|
||||
unsigned int hashval;
|
||||
int len;
|
||||
struct var *vp, **vpp;
|
||||
const char *p = name;
|
||||
|
||||
hashval = 0;
|
||||
while (*p && *p != '=')
|
||||
hashval = 2 * hashval + (unsigned char)*p++;
|
||||
len = p - name;
|
||||
|
||||
if (lenp)
|
||||
*lenp = len;
|
||||
vpp = &vartab[hashval % VTABSIZE];
|
||||
if (vppp)
|
||||
*vppp = vpp;
|
||||
|
||||
for (vp = *vpp ; vp ; vpp = &vp->next, vp = *vpp) {
|
||||
if (vp->name_len != len)
|
||||
continue;
|
||||
if (memcmp(vp->text, name, len) != 0)
|
||||
continue;
|
||||
if (vppp)
|
||||
*vppp = vpp;
|
||||
return vp;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
131
sh/var.h
131
sh/var.h
|
|
@ -1,131 +0,0 @@
|
|||
/* $NetBSD: var.h,v 1.23 2004/10/02 12:16:53 dsl Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1991, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to Berkeley by
|
||||
* Kenneth Almquist.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)var.h 8.2 (Berkeley) 5/4/95
|
||||
*/
|
||||
|
||||
/*
|
||||
* Shell variables.
|
||||
*/
|
||||
|
||||
/* flags */
|
||||
#define VEXPORT 0x01 /* variable is exported */
|
||||
#define VREADONLY 0x02 /* variable cannot be modified */
|
||||
#define VSTRFIXED 0x04 /* variable struct is statically allocated */
|
||||
#define VTEXTFIXED 0x08 /* text is statically allocated */
|
||||
#define VSTACK 0x10 /* text is allocated on the stack */
|
||||
#define VUNSET 0x20 /* the variable is not set */
|
||||
#define VNOFUNC 0x40 /* don't call the callback function */
|
||||
#define VNOSET 0x80 /* do not set variable - just readonly test */
|
||||
|
||||
|
||||
struct var {
|
||||
struct var *next; /* next entry in hash list */
|
||||
int flags; /* flags are defined above */
|
||||
char *text; /* name=value */
|
||||
int name_len; /* length of name */
|
||||
void (*func)(const char *);
|
||||
/* function to be called when */
|
||||
/* the variable gets set/unset */
|
||||
};
|
||||
|
||||
|
||||
struct localvar {
|
||||
struct localvar *next; /* next local variable in list */
|
||||
struct var *vp; /* the variable that was made local */
|
||||
int flags; /* saved flags */
|
||||
char *text; /* saved text */
|
||||
};
|
||||
|
||||
|
||||
struct localvar *localvars;
|
||||
|
||||
#if ATTY
|
||||
extern struct var vatty;
|
||||
#endif
|
||||
extern struct var vifs;
|
||||
extern struct var vmpath;
|
||||
extern struct var vpath;
|
||||
extern struct var vps1;
|
||||
extern struct var vps2;
|
||||
extern struct var vps4;
|
||||
#ifdef WITH_HISTORY
|
||||
extern struct var vterm;
|
||||
extern struct var vtermcap;
|
||||
extern struct var vhistsize;
|
||||
#endif
|
||||
|
||||
/*
|
||||
* The following macros access the values of the above variables.
|
||||
* They have to skip over the name. They return the null string
|
||||
* for unset variables.
|
||||
*/
|
||||
|
||||
#define ifsval() (vifs.text + 4)
|
||||
#define ifsset() ((vifs.flags & VUNSET) == 0)
|
||||
#define mpathval() (vmpath.text + 9)
|
||||
#define pathval() (vpath.text + 5)
|
||||
#define ps1val() (vps1.text + 4)
|
||||
#define ps2val() (vps2.text + 4)
|
||||
#define ps4val() (vps4.text + 4)
|
||||
#define optindval() (voptind.text + 7)
|
||||
#ifdef WITH_HISTORY
|
||||
#define histsizeval() (vhistsize.text + 9)
|
||||
#define termval() (vterm.text + 5)
|
||||
#endif
|
||||
|
||||
#if ATTY
|
||||
#define attyset() ((vatty.flags & VUNSET) == 0)
|
||||
#endif
|
||||
#define mpathset() ((vmpath.flags & VUNSET) == 0)
|
||||
|
||||
void initvar(void);
|
||||
void setvar(const char *, const char *, int);
|
||||
void setvareq(char *, int);
|
||||
struct strlist;
|
||||
void listsetvar(struct strlist *, int);
|
||||
char *lookupvar(const char *);
|
||||
char *bltinlookup(const char *, int);
|
||||
char **environment(void);
|
||||
void shprocvar(void);
|
||||
int showvars(const char *, int, int);
|
||||
int exportcmd(int, char **);
|
||||
int localcmd(int, char **);
|
||||
void mklocal(const char *, int);
|
||||
void listmklocal(struct strlist *, int);
|
||||
void poplocalvars(void);
|
||||
int setvarcmd(int, char **);
|
||||
int unsetcmd(int, char **);
|
||||
int unsetvar(const char *, int);
|
||||
int setvarsafe(const char *, const char *, int);
|
||||
void print_quoted(const char *);
|
||||
Loading…
Add table
Reference in a new issue