Dispose of ash.
We haven't used ash for several releases. Remove ash and its companion liblinenoise. I've left the support for an alternative shell here for now, but we can move that out to external/mksh later if we want. (For now this seemed like a somewhat useful signpost to the real shell.) Change-Id: I634c7969f6cbe375a2bc56fc1077e64888380f3d
This commit is contained in:
parent
8c58086c54
commit
f6e21e06e3
|
@ -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…
Reference in New Issue