Merge "Dispose of ash."
This commit is contained in:
commit
c8626ba480
85 changed files with 2 additions and 25738 deletions
|
|
@ -1,12 +0,0 @@
|
||||||
LOCAL_PATH:= $(call my-dir)
|
|
||||||
include $(CLEAR_VARS)
|
|
||||||
|
|
||||||
# Static library
|
|
||||||
# ========================================================
|
|
||||||
|
|
||||||
include $(CLEAR_VARS)
|
|
||||||
LOCAL_MODULE:= liblinenoise
|
|
||||||
LOCAL_SRC_FILES := linenoise.c
|
|
||||||
|
|
||||||
|
|
||||||
include $(BUILD_STATIC_LIBRARY)
|
|
||||||
|
|
@ -1,28 +0,0 @@
|
||||||
Copyright (c) 2010, Salvatore Sanfilippo <antirez at gmail dot com>
|
|
||||||
All rights reserved.
|
|
||||||
|
|
||||||
Redistribution and use in source and binary forms, with or without
|
|
||||||
modification, are permitted provided that the following conditions are met:
|
|
||||||
|
|
||||||
* Redistributions of source code must retain the above copyright notice,
|
|
||||||
this list of conditions and the following disclaimer.
|
|
||||||
|
|
||||||
* Redistributions in binary form must reproduce the above copyright
|
|
||||||
notice, this list of conditions and the following disclaimer in the
|
|
||||||
documentation and/or other materials provided with the distribution.
|
|
||||||
|
|
||||||
* Neither the name of Redis nor the names of its contributors may be used
|
|
||||||
to endorse or promote products derived from this software without
|
|
||||||
specific prior written permission.
|
|
||||||
|
|
||||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
||||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
||||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
||||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
|
||||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
|
||||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
|
||||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
|
||||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
|
||||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
|
||||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
|
||||||
POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
|
|
@ -1,449 +0,0 @@
|
||||||
/* linenoise.c -- guerrilla line editing library against the idea that a
|
|
||||||
* line editing lib needs to be 20,000 lines of C code.
|
|
||||||
*
|
|
||||||
* You can find the latest source code at:
|
|
||||||
*
|
|
||||||
* http://github.com/antirez/linenoise
|
|
||||||
*
|
|
||||||
* Does a number of crazy assumptions that happen to be true in 99.9999% of
|
|
||||||
* the 2010 UNIX computers around.
|
|
||||||
*
|
|
||||||
* Copyright (c) 2010, Salvatore Sanfilippo <antirez at gmail dot com>
|
|
||||||
* All rights reserved.
|
|
||||||
*
|
|
||||||
* Redistribution and use in source and binary forms, with or without
|
|
||||||
* modification, are permitted provided that the following conditions are met:
|
|
||||||
*
|
|
||||||
* * Redistributions of source code must retain the above copyright notice,
|
|
||||||
* this list of conditions and the following disclaimer.
|
|
||||||
* * Redistributions in binary form must reproduce the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer in the
|
|
||||||
* documentation and/or other materials provided with the distribution.
|
|
||||||
* * Neither the name of Redis nor the names of its contributors may be used
|
|
||||||
* to endorse or promote products derived from this software without
|
|
||||||
* specific prior written permission.
|
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
||||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
||||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
||||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
|
||||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
|
||||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
|
||||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
|
||||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
|
||||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
|
||||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
|
||||||
* POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
*
|
|
||||||
* References:
|
|
||||||
* - http://invisible-island.net/xterm/ctlseqs/ctlseqs.html
|
|
||||||
* - http://www.3waylabs.com/nw/WWW/products/wizcon/vt220.html
|
|
||||||
*
|
|
||||||
* Todo list:
|
|
||||||
* - Switch to gets() if $TERM is something we can't support.
|
|
||||||
* - Filter bogus Ctrl+<char> combinations.
|
|
||||||
* - Win32 support
|
|
||||||
*
|
|
||||||
* Bloat:
|
|
||||||
* - Completion?
|
|
||||||
* - History search like Ctrl+r in readline?
|
|
||||||
*
|
|
||||||
* List of escape sequences used by this program, we do everything just
|
|
||||||
* with three sequences. In order to be so cheap we may have some
|
|
||||||
* flickering effect with some slow terminal, but the lesser sequences
|
|
||||||
* the more compatible.
|
|
||||||
*
|
|
||||||
* CHA (Cursor Horizontal Absolute)
|
|
||||||
* Sequence: ESC [ n G
|
|
||||||
* Effect: moves cursor to column n
|
|
||||||
*
|
|
||||||
* EL (Erase Line)
|
|
||||||
* Sequence: ESC [ n K
|
|
||||||
* Effect: if n is 0 or missing, clear from cursor to end of line
|
|
||||||
* Effect: if n is 1, clear from beginning of line to cursor
|
|
||||||
* Effect: if n is 2, clear entire line
|
|
||||||
*
|
|
||||||
* CUF (CUrsor Forward)
|
|
||||||
* Sequence: ESC [ n C
|
|
||||||
* Effect: moves cursor forward of n chars
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <termios.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <errno.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <sys/types.h>
|
|
||||||
#include <sys/ioctl.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
|
|
||||||
#define LINENOISE_MAX_LINE 4096
|
|
||||||
static char *unsupported_term[] = {"dumb","cons25",NULL};
|
|
||||||
|
|
||||||
static struct termios orig_termios; /* in order to restore at exit */
|
|
||||||
static int rawmode = 0; /* for atexit() function to check if restore is needed*/
|
|
||||||
static int atexit_registered = 0; /* register atexit just 1 time */
|
|
||||||
static int history_max_len = 100;
|
|
||||||
static int history_len = 0;
|
|
||||||
char **history = NULL;
|
|
||||||
|
|
||||||
static void linenoiseAtExit(void);
|
|
||||||
int linenoiseHistoryAdd(const char *line);
|
|
||||||
|
|
||||||
static int isUnsupportedTerm(void) {
|
|
||||||
char *term = getenv("TERM");
|
|
||||||
int j;
|
|
||||||
|
|
||||||
if (term == NULL) return 0;
|
|
||||||
for (j = 0; unsupported_term[j]; j++)
|
|
||||||
if (!strcasecmp(term,unsupported_term[j])) return 1;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void freeHistory(void) {
|
|
||||||
if (history) {
|
|
||||||
int j;
|
|
||||||
|
|
||||||
for (j = 0; j < history_len; j++)
|
|
||||||
free(history[j]);
|
|
||||||
free(history);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static int enableRawMode(int fd) {
|
|
||||||
struct termios raw;
|
|
||||||
|
|
||||||
if (!isatty(STDIN_FILENO)) goto fatal;
|
|
||||||
if (!atexit_registered) {
|
|
||||||
atexit(linenoiseAtExit);
|
|
||||||
atexit_registered = 1;
|
|
||||||
}
|
|
||||||
if (tcgetattr(fd,&orig_termios) == -1) goto fatal;
|
|
||||||
|
|
||||||
raw = orig_termios; /* modify the original mode */
|
|
||||||
/* input modes: no break, no CR to NL, no parity check, no strip char,
|
|
||||||
* no start/stop output control. */
|
|
||||||
raw.c_iflag &= ~(BRKINT | ICRNL | INPCK | ISTRIP | IXON);
|
|
||||||
/* output modes - disable post processing */
|
|
||||||
raw.c_oflag &= ~(OPOST);
|
|
||||||
/* control modes - set 8 bit chars */
|
|
||||||
raw.c_cflag |= (CS8);
|
|
||||||
/* local modes - choing off, canonical off, no extended functions,
|
|
||||||
* no signal chars (^Z,^C) */
|
|
||||||
raw.c_lflag &= ~(ECHO | ICANON | IEXTEN | ISIG);
|
|
||||||
/* control chars - set return condition: min number of bytes and timer.
|
|
||||||
* We want read to return every single byte, without timeout. */
|
|
||||||
raw.c_cc[VMIN] = 1; raw.c_cc[VTIME] = 0; /* 1 byte, no timer */
|
|
||||||
|
|
||||||
/* put terminal in raw mode */
|
|
||||||
if (tcsetattr(fd,TCSADRAIN,&raw) < 0) goto fatal;
|
|
||||||
rawmode = 1;
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
fatal:
|
|
||||||
errno = ENOTTY;
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void disableRawMode(int fd) {
|
|
||||||
/* Don't even check the return value as it's too late. */
|
|
||||||
if (rawmode && tcsetattr(fd,TCSADRAIN,&orig_termios) != -1)
|
|
||||||
rawmode = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* At exit we'll try to fix the terminal to the initial conditions. */
|
|
||||||
static void linenoiseAtExit(void) {
|
|
||||||
disableRawMode(STDIN_FILENO);
|
|
||||||
freeHistory();
|
|
||||||
}
|
|
||||||
|
|
||||||
static int getColumns(void) {
|
|
||||||
struct winsize ws;
|
|
||||||
|
|
||||||
if (ioctl(1, TIOCGWINSZ, &ws) == -1) return 4096;
|
|
||||||
if (ws.ws_col == 0) {
|
|
||||||
return 4096;
|
|
||||||
}
|
|
||||||
return ws.ws_col;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int effectiveLen(const char* prompt) {
|
|
||||||
int col = 0;
|
|
||||||
char c;
|
|
||||||
// TODO: Handle escape sequences.
|
|
||||||
while ( (c = *prompt++) != 0 ) {
|
|
||||||
if (c == '\n') {
|
|
||||||
col = 0;
|
|
||||||
} else {
|
|
||||||
col++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return col;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void refreshLine(int fd, const char *prompt, char *buf, size_t len, size_t pos, size_t cols) {
|
|
||||||
char seq[64];
|
|
||||||
size_t plen = effectiveLen(prompt);
|
|
||||||
|
|
||||||
while((plen+pos) >= cols) {
|
|
||||||
buf++;
|
|
||||||
len--;
|
|
||||||
pos--;
|
|
||||||
}
|
|
||||||
while (plen+len > cols) {
|
|
||||||
len--;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Cursor to left edge */
|
|
||||||
snprintf(seq,64,"\x1b[0G");
|
|
||||||
if (write(fd,seq,strlen(seq)) == -1) return;
|
|
||||||
/* Write the prompt and the current buffer content */
|
|
||||||
if (write(fd,prompt,strlen(prompt)) == -1) return;
|
|
||||||
if (write(fd,buf,len) == -1) return;
|
|
||||||
/* Erase to right */
|
|
||||||
snprintf(seq,64,"\x1b[0K");
|
|
||||||
if (write(fd,seq,strlen(seq)) == -1) return;
|
|
||||||
/* Move cursor to original position. */
|
|
||||||
snprintf(seq,64,"\x1b[0G\x1b[%dC", (int)(pos+plen));
|
|
||||||
if (write(fd,seq,strlen(seq)) == -1) return;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int linenoisePrompt(int fd, char *buf, size_t buflen, const char *prompt) {
|
|
||||||
size_t plen = strlen(prompt);
|
|
||||||
size_t pos = 0;
|
|
||||||
size_t len = 0;
|
|
||||||
size_t cols = getColumns();
|
|
||||||
int history_index = 0;
|
|
||||||
|
|
||||||
buf[0] = '\0';
|
|
||||||
buflen--; /* Make sure there is always space for the nulterm */
|
|
||||||
|
|
||||||
/* The latest history entry is always our current buffer, that
|
|
||||||
* initially is just an empty string. */
|
|
||||||
linenoiseHistoryAdd("");
|
|
||||||
|
|
||||||
if (write(fd,prompt,plen) == -1) return -1;
|
|
||||||
while(1) {
|
|
||||||
char c;
|
|
||||||
int nread;
|
|
||||||
char seq[2];
|
|
||||||
|
|
||||||
nread = read(fd,&c,1);
|
|
||||||
if (nread <= 0) return len;
|
|
||||||
switch(c) {
|
|
||||||
case 10: /* line feed. */
|
|
||||||
case 13: /* enter */
|
|
||||||
history_len--;
|
|
||||||
return len;
|
|
||||||
case 4: /* ctrl-d */
|
|
||||||
history_len--;
|
|
||||||
return (len == 0) ? -1 : (int)len;
|
|
||||||
case 3: /* ctrl-c */
|
|
||||||
errno = EAGAIN;
|
|
||||||
return -1;
|
|
||||||
case 127: /* backspace */
|
|
||||||
case 8: /* ctrl-h */
|
|
||||||
if (pos > 0 && len > 0) {
|
|
||||||
memmove(buf+pos-1,buf+pos,len-pos);
|
|
||||||
pos--;
|
|
||||||
len--;
|
|
||||||
buf[len] = '\0';
|
|
||||||
refreshLine(fd,prompt,buf,len,pos,cols);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case 20: /* ctrl-t */
|
|
||||||
if (pos > 0 && pos < len) {
|
|
||||||
int aux = buf[pos-1];
|
|
||||||
buf[pos-1] = buf[pos];
|
|
||||||
buf[pos] = aux;
|
|
||||||
if (pos != len-1) pos++;
|
|
||||||
refreshLine(fd,prompt,buf,len,pos,cols);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case 2: /* ctrl-b */
|
|
||||||
goto left_arrow;
|
|
||||||
case 6: /* ctrl-f */
|
|
||||||
goto right_arrow;
|
|
||||||
case 16: /* ctrl-p */
|
|
||||||
seq[1] = 65;
|
|
||||||
goto up_down_arrow;
|
|
||||||
case 14: /* ctrl-n */
|
|
||||||
seq[1] = 66;
|
|
||||||
goto up_down_arrow;
|
|
||||||
break;
|
|
||||||
case 27: /* escape sequence */
|
|
||||||
if (read(fd,seq,2) == -1) break;
|
|
||||||
if (seq[0] == 91 && seq[1] == 68) {
|
|
||||||
left_arrow:
|
|
||||||
/* left arrow */
|
|
||||||
if (pos > 0) {
|
|
||||||
pos--;
|
|
||||||
refreshLine(fd,prompt,buf,len,pos,cols);
|
|
||||||
}
|
|
||||||
} else if (seq[0] == 91 && seq[1] == 67) {
|
|
||||||
right_arrow:
|
|
||||||
/* right arrow */
|
|
||||||
if (pos != len) {
|
|
||||||
pos++;
|
|
||||||
refreshLine(fd,prompt,buf,len,pos,cols);
|
|
||||||
}
|
|
||||||
} else if (seq[0] == 91 && (seq[1] == 65 || seq[1] == 66)) {
|
|
||||||
up_down_arrow:
|
|
||||||
/* up and down arrow: history */
|
|
||||||
if (history_len > 1) {
|
|
||||||
/* Update the current history entry before to
|
|
||||||
* overwrite it with tne next one. */
|
|
||||||
free(history[history_len-1-history_index]);
|
|
||||||
history[history_len-1-history_index] = strdup(buf);
|
|
||||||
/* Show the new entry */
|
|
||||||
history_index += (seq[1] == 65) ? 1 : -1;
|
|
||||||
if (history_index < 0) {
|
|
||||||
history_index = 0;
|
|
||||||
break;
|
|
||||||
} else if (history_index >= history_len) {
|
|
||||||
history_index = history_len-1;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
strncpy(buf,history[history_len-1-history_index],buflen);
|
|
||||||
buf[buflen] = '\0';
|
|
||||||
len = pos = strlen(buf);
|
|
||||||
refreshLine(fd,prompt,buf,len,pos,cols);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
if (len < buflen) {
|
|
||||||
if (len == pos) {
|
|
||||||
buf[pos] = c;
|
|
||||||
pos++;
|
|
||||||
len++;
|
|
||||||
buf[len] = '\0';
|
|
||||||
if (plen+len < cols) {
|
|
||||||
/* Avoid a full update of the line in the
|
|
||||||
* trivial case. */
|
|
||||||
if (write(fd,&c,1) == -1) return -1;
|
|
||||||
} else {
|
|
||||||
refreshLine(fd,prompt,buf,len,pos,cols);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
memmove(buf+pos+1,buf+pos,len-pos);
|
|
||||||
buf[pos] = c;
|
|
||||||
len++;
|
|
||||||
pos++;
|
|
||||||
buf[len] = '\0';
|
|
||||||
refreshLine(fd,prompt,buf,len,pos,cols);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case 21: /* Ctrl+u, delete the whole line. */
|
|
||||||
buf[0] = '\0';
|
|
||||||
pos = len = 0;
|
|
||||||
refreshLine(fd,prompt,buf,len,pos,cols);
|
|
||||||
break;
|
|
||||||
case 11: /* Ctrl+k, delete from current to end of line. */
|
|
||||||
buf[pos] = '\0';
|
|
||||||
len = pos;
|
|
||||||
refreshLine(fd,prompt,buf,len,pos,cols);
|
|
||||||
break;
|
|
||||||
case 1: /* Ctrl+a, go to the start of the line */
|
|
||||||
pos = 0;
|
|
||||||
refreshLine(fd,prompt,buf,len,pos,cols);
|
|
||||||
break;
|
|
||||||
case 5: /* ctrl+e, go to the end of the line */
|
|
||||||
pos = len;
|
|
||||||
refreshLine(fd,prompt,buf,len,pos,cols);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return len;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int linenoiseRaw(char *buf, size_t buflen, const char *prompt) {
|
|
||||||
int fd = STDIN_FILENO;
|
|
||||||
int count;
|
|
||||||
|
|
||||||
if (buflen == 0) {
|
|
||||||
errno = EINVAL;
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
if (!isatty(STDIN_FILENO)) {
|
|
||||||
if (fgets(buf, buflen, stdin) == NULL) return -1;
|
|
||||||
count = strlen(buf);
|
|
||||||
if (count && buf[count-1] == '\n') {
|
|
||||||
count--;
|
|
||||||
buf[count] = '\0';
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (enableRawMode(fd) == -1) return -1;
|
|
||||||
count = linenoisePrompt(fd, buf, buflen, prompt);
|
|
||||||
disableRawMode(fd);
|
|
||||||
}
|
|
||||||
return count;
|
|
||||||
}
|
|
||||||
|
|
||||||
char *linenoise(const char *prompt) {
|
|
||||||
char buf[LINENOISE_MAX_LINE];
|
|
||||||
int count;
|
|
||||||
|
|
||||||
if (isUnsupportedTerm()) {
|
|
||||||
size_t len;
|
|
||||||
|
|
||||||
printf("%s",prompt);
|
|
||||||
fflush(stdout);
|
|
||||||
if (fgets(buf,LINENOISE_MAX_LINE,stdin) == NULL) return NULL;
|
|
||||||
len = strlen(buf);
|
|
||||||
while(len && (buf[len-1] == '\n' || buf[len-1] == '\r')) {
|
|
||||||
len--;
|
|
||||||
buf[len] = '\0';
|
|
||||||
}
|
|
||||||
return strdup(buf);
|
|
||||||
} else {
|
|
||||||
count = linenoiseRaw(buf,LINENOISE_MAX_LINE,prompt);
|
|
||||||
if (count == -1) return NULL;
|
|
||||||
return strdup(buf);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Using a circular buffer is smarter, but a bit more complex to handle. */
|
|
||||||
int linenoiseHistoryAdd(const char *line) {
|
|
||||||
char *linecopy;
|
|
||||||
|
|
||||||
if (history_max_len == 0) return 0;
|
|
||||||
if (history == 0) {
|
|
||||||
history = malloc(sizeof(char*)*history_max_len);
|
|
||||||
if (history == NULL) return 0;
|
|
||||||
memset(history,0,(sizeof(char*)*history_max_len));
|
|
||||||
}
|
|
||||||
linecopy = strdup(line);
|
|
||||||
if (!linecopy) return 0;
|
|
||||||
if (history_len == history_max_len) {
|
|
||||||
memmove(history,history+1,sizeof(char*)*(history_max_len-1));
|
|
||||||
history_len--;
|
|
||||||
}
|
|
||||||
history[history_len] = linecopy;
|
|
||||||
history_len++;
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
int linenoiseHistorySetMaxLen(int len) {
|
|
||||||
char **new;
|
|
||||||
|
|
||||||
if (len < 1) return 0;
|
|
||||||
if (history) {
|
|
||||||
int tocopy = history_len;
|
|
||||||
|
|
||||||
new = malloc(sizeof(char*)*len);
|
|
||||||
if (new == NULL) return 0;
|
|
||||||
if (len < tocopy) tocopy = len;
|
|
||||||
memcpy(new,history+(history_max_len-tocopy), sizeof(char*)*tocopy);
|
|
||||||
free(history);
|
|
||||||
history = new;
|
|
||||||
}
|
|
||||||
history_max_len = len;
|
|
||||||
if (history_len > history_max_len)
|
|
||||||
history_len = history_max_len;
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
@ -1,41 +0,0 @@
|
||||||
/* linenoise.h -- guerrilla line editing library against the idea that a
|
|
||||||
* line editing lib needs to be 20,000 lines of C code.
|
|
||||||
*
|
|
||||||
* See linenoise.c for more information.
|
|
||||||
*
|
|
||||||
* Copyright (c) 2010, Salvatore Sanfilippo <antirez at gmail dot com>
|
|
||||||
* All rights reserved.
|
|
||||||
*
|
|
||||||
* Redistribution and use in source and binary forms, with or without
|
|
||||||
* modification, are permitted provided that the following conditions are met:
|
|
||||||
*
|
|
||||||
* * Redistributions of source code must retain the above copyright notice,
|
|
||||||
* this list of conditions and the following disclaimer.
|
|
||||||
* * Redistributions in binary form must reproduce the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer in the
|
|
||||||
* documentation and/or other materials provided with the distribution.
|
|
||||||
* * Neither the name of Redis nor the names of its contributors may be used
|
|
||||||
* to endorse or promote products derived from this software without
|
|
||||||
* specific prior written permission.
|
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
||||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
||||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
||||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
|
||||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
|
||||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
|
||||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
|
||||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
|
||||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
|
||||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
|
||||||
* POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef __LINENOISE_H
|
|
||||||
#define __LINENOISE_H
|
|
||||||
|
|
||||||
char *linenoise(const char *prompt);
|
|
||||||
int linenoiseHistoryAdd(const char *line);
|
|
||||||
int linenoiseHistorySetMaxLen(int len);
|
|
||||||
|
|
||||||
#endif /* __LINENOISE_H */
|
|
||||||
|
|
@ -1,61 +1,5 @@
|
||||||
LOCAL_PATH:= $(call my-dir)
|
# Create the /system/bin/sh symlink to $(TARGET_SHELL).
|
||||||
include $(CLEAR_VARS)
|
# Currently, Android's shell is external/mksh.
|
||||||
|
|
||||||
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
|
|
||||||
|
|
||||||
OUTSYSTEMBINSH := $(TARGET_OUT)/bin/sh
|
OUTSYSTEMBINSH := $(TARGET_OUT)/bin/sh
|
||||||
LOCAL_MODULE := systembinsh
|
LOCAL_MODULE := systembinsh
|
||||||
|
|
|
||||||
31
sh/NOTICE
31
sh/NOTICE
|
|
@ -1,31 +0,0 @@
|
||||||
Copyright (c) 1991, 1993
|
|
||||||
The Regents of the University of California. All rights reserved.
|
|
||||||
|
|
||||||
This code is derived from software contributed to Berkeley by
|
|
||||||
Kenneth Almquist.
|
|
||||||
|
|
||||||
Redistribution and use in source and binary forms, with or without
|
|
||||||
modification, are permitted provided that the following conditions
|
|
||||||
are met:
|
|
||||||
1. Redistributions of source code must retain the above copyright
|
|
||||||
notice, this list of conditions and the following disclaimer.
|
|
||||||
2. Redistributions in binary form must reproduce the above copyright
|
|
||||||
notice, this list of conditions and the following disclaimer in the
|
|
||||||
documentation and/or other materials provided with the distribution.
|
|
||||||
3. Neither the name of the University nor the names of its contributors
|
|
||||||
may be used to endorse or promote products derived from this software
|
|
||||||
without specific prior written permission.
|
|
||||||
|
|
||||||
THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
|
||||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
||||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
||||||
ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
|
||||||
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
||||||
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
|
||||||
OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
|
||||||
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
||||||
LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
|
||||||
OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
|
||||||
SUCH DAMAGE.
|
|
||||||
|
|
||||||
|
|
||||||
357
sh/TOUR
357
sh/TOUR
|
|
@ -1,357 +0,0 @@
|
||||||
# $NetBSD: TOUR,v 1.8 1996/10/16 14:24:56 christos Exp $
|
|
||||||
# @(#)TOUR 8.1 (Berkeley) 5/31/93
|
|
||||||
|
|
||||||
NOTE -- This is the original TOUR paper distributed with ash and
|
|
||||||
does not represent the current state of the shell. It is provided anyway
|
|
||||||
since it provides helpful information for how the shell is structured,
|
|
||||||
but be warned that things have changed -- the current shell is
|
|
||||||
still under development.
|
|
||||||
|
|
||||||
================================================================
|
|
||||||
|
|
||||||
A Tour through Ash
|
|
||||||
|
|
||||||
Copyright 1989 by Kenneth Almquist.
|
|
||||||
|
|
||||||
|
|
||||||
DIRECTORIES: The subdirectory bltin contains commands which can
|
|
||||||
be compiled stand-alone. The rest of the source is in the main
|
|
||||||
ash directory.
|
|
||||||
|
|
||||||
SOURCE CODE GENERATORS: Files whose names begin with "mk" are
|
|
||||||
programs that generate source code. A complete list of these
|
|
||||||
programs is:
|
|
||||||
|
|
||||||
program intput files generates
|
|
||||||
------- ------------ ---------
|
|
||||||
mkbuiltins builtins builtins.h builtins.c
|
|
||||||
mkinit *.c init.c
|
|
||||||
mknodes nodetypes nodes.h nodes.c
|
|
||||||
mksignames - signames.h signames.c
|
|
||||||
mksyntax - syntax.h syntax.c
|
|
||||||
mktokens - token.h
|
|
||||||
bltin/mkexpr unary_op binary_op operators.h operators.c
|
|
||||||
|
|
||||||
There are undoubtedly too many of these. Mkinit searches all the
|
|
||||||
C source files for entries looking like:
|
|
||||||
|
|
||||||
INIT {
|
|
||||||
x = 1; /* executed during initialization */
|
|
||||||
}
|
|
||||||
|
|
||||||
RESET {
|
|
||||||
x = 2; /* executed when the shell does a longjmp
|
|
||||||
back to the main command loop */
|
|
||||||
}
|
|
||||||
|
|
||||||
SHELLPROC {
|
|
||||||
x = 3; /* executed when the shell runs a shell procedure */
|
|
||||||
}
|
|
||||||
|
|
||||||
It pulls this code out into routines which are when particular
|
|
||||||
events occur. The intent is to improve modularity by isolating
|
|
||||||
the information about which modules need to be explicitly
|
|
||||||
initialized/reset within the modules themselves.
|
|
||||||
|
|
||||||
Mkinit recognizes several constructs for placing declarations in
|
|
||||||
the init.c file.
|
|
||||||
INCLUDE "file.h"
|
|
||||||
includes a file. The storage class MKINIT makes a declaration
|
|
||||||
available in the init.c file, for example:
|
|
||||||
MKINIT int funcnest; /* depth of function calls */
|
|
||||||
MKINIT alone on a line introduces a structure or union declara-
|
|
||||||
tion:
|
|
||||||
MKINIT
|
|
||||||
struct redirtab {
|
|
||||||
short renamed[10];
|
|
||||||
};
|
|
||||||
Preprocessor #define statements are copied to init.c without any
|
|
||||||
special action to request this.
|
|
||||||
|
|
||||||
INDENTATION: The ash source is indented in multiples of six
|
|
||||||
spaces. The only study that I have heard of on the subject con-
|
|
||||||
cluded that the optimal amount to indent is in the range of four
|
|
||||||
to six spaces. I use six spaces since it is not too big a jump
|
|
||||||
from the widely used eight spaces. If you really hate six space
|
|
||||||
indentation, use the adjind (source included) program to change
|
|
||||||
it to something else.
|
|
||||||
|
|
||||||
EXCEPTIONS: Code for dealing with exceptions appears in
|
|
||||||
exceptions.c. The C language doesn't include exception handling,
|
|
||||||
so I implement it using setjmp and longjmp. The global variable
|
|
||||||
exception contains the type of exception. EXERROR is raised by
|
|
||||||
calling error. EXINT is an interrupt. EXSHELLPROC is an excep-
|
|
||||||
tion which is raised when a shell procedure is invoked. The pur-
|
|
||||||
pose of EXSHELLPROC is to perform the cleanup actions associated
|
|
||||||
with other exceptions. After these cleanup actions, the shell
|
|
||||||
can interpret a shell procedure itself without exec'ing a new
|
|
||||||
copy of the shell.
|
|
||||||
|
|
||||||
INTERRUPTS: In an interactive shell, an interrupt will cause an
|
|
||||||
EXINT exception to return to the main command loop. (Exception:
|
|
||||||
EXINT is not raised if the user traps interrupts using the trap
|
|
||||||
command.) The INTOFF and INTON macros (defined in exception.h)
|
|
||||||
provide uninterruptable critical sections. Between the execution
|
|
||||||
of INTOFF and the execution of INTON, interrupt signals will be
|
|
||||||
held for later delivery. INTOFF and INTON can be nested.
|
|
||||||
|
|
||||||
MEMALLOC.C: Memalloc.c defines versions of malloc and realloc
|
|
||||||
which call error when there is no memory left. It also defines a
|
|
||||||
stack oriented memory allocation scheme. Allocating off a stack
|
|
||||||
is probably more efficient than allocation using malloc, but the
|
|
||||||
big advantage is that when an exception occurs all we have to do
|
|
||||||
to free up the memory in use at the time of the exception is to
|
|
||||||
restore the stack pointer. The stack is implemented using a
|
|
||||||
linked list of blocks.
|
|
||||||
|
|
||||||
STPUTC: If the stack were contiguous, it would be easy to store
|
|
||||||
strings on the stack without knowing in advance how long the
|
|
||||||
string was going to be:
|
|
||||||
p = stackptr;
|
|
||||||
*p++ = c; /* repeated as many times as needed */
|
|
||||||
stackptr = p;
|
|
||||||
The folloing three macros (defined in memalloc.h) perform these
|
|
||||||
operations, but grow the stack if you run off the end:
|
|
||||||
STARTSTACKSTR(p);
|
|
||||||
STPUTC(c, p); /* repeated as many times as needed */
|
|
||||||
grabstackstr(p);
|
|
||||||
|
|
||||||
We now start a top-down look at the code:
|
|
||||||
|
|
||||||
MAIN.C: The main routine performs some initialization, executes
|
|
||||||
the user's profile if necessary, and calls cmdloop. Cmdloop is
|
|
||||||
repeatedly parses and executes commands.
|
|
||||||
|
|
||||||
OPTIONS.C: This file contains the option processing code. It is
|
|
||||||
called from main to parse the shell arguments when the shell is
|
|
||||||
invoked, and it also contains the set builtin. The -i and -j op-
|
|
||||||
tions (the latter turns on job control) require changes in signal
|
|
||||||
handling. The routines setjobctl (in jobs.c) and setinteractive
|
|
||||||
(in trap.c) are called to handle changes to these options.
|
|
||||||
|
|
||||||
PARSING: The parser code is all in parser.c. A recursive des-
|
|
||||||
cent parser is used. Syntax tables (generated by mksyntax) are
|
|
||||||
used to classify characters during lexical analysis. There are
|
|
||||||
three tables: one for normal use, one for use when inside single
|
|
||||||
quotes, and one for use when inside double quotes. The tables
|
|
||||||
are machine dependent because they are indexed by character vari-
|
|
||||||
ables and the range of a char varies from machine to machine.
|
|
||||||
|
|
||||||
PARSE OUTPUT: The output of the parser consists of a tree of
|
|
||||||
nodes. The various types of nodes are defined in the file node-
|
|
||||||
types.
|
|
||||||
|
|
||||||
Nodes of type NARG are used to represent both words and the con-
|
|
||||||
tents of here documents. An early version of ash kept the con-
|
|
||||||
tents of here documents in temporary files, but keeping here do-
|
|
||||||
cuments in memory typically results in significantly better per-
|
|
||||||
formance. It would have been nice to make it an option to use
|
|
||||||
temporary files for here documents, for the benefit of small
|
|
||||||
machines, but the code to keep track of when to delete the tem-
|
|
||||||
porary files was complex and I never fixed all the bugs in it.
|
|
||||||
(AT&T has been maintaining the Bourne shell for more than ten
|
|
||||||
years, and to the best of my knowledge they still haven't gotten
|
|
||||||
it to handle temporary files correctly in obscure cases.)
|
|
||||||
|
|
||||||
The text field of a NARG structure points to the text of the
|
|
||||||
word. The text consists of ordinary characters and a number of
|
|
||||||
special codes defined in parser.h. The special codes are:
|
|
||||||
|
|
||||||
CTLVAR Variable substitution
|
|
||||||
CTLENDVAR End of variable substitution
|
|
||||||
CTLBACKQ Command substitution
|
|
||||||
CTLBACKQ|CTLQUOTE Command substitution inside double quotes
|
|
||||||
CTLESC Escape next character
|
|
||||||
|
|
||||||
A variable substitution contains the following elements:
|
|
||||||
|
|
||||||
CTLVAR type name '=' [ alternative-text CTLENDVAR ]
|
|
||||||
|
|
||||||
The type field is a single character specifying the type of sub-
|
|
||||||
stitution. The possible types are:
|
|
||||||
|
|
||||||
VSNORMAL $var
|
|
||||||
VSMINUS ${var-text}
|
|
||||||
VSMINUS|VSNUL ${var:-text}
|
|
||||||
VSPLUS ${var+text}
|
|
||||||
VSPLUS|VSNUL ${var:+text}
|
|
||||||
VSQUESTION ${var?text}
|
|
||||||
VSQUESTION|VSNUL ${var:?text}
|
|
||||||
VSASSIGN ${var=text}
|
|
||||||
VSASSIGN|VSNUL ${var=text}
|
|
||||||
|
|
||||||
In addition, the type field will have the VSQUOTE flag set if the
|
|
||||||
variable is enclosed in double quotes. The name of the variable
|
|
||||||
comes next, terminated by an equals sign. If the type is not
|
|
||||||
VSNORMAL, then the text field in the substitution follows, ter-
|
|
||||||
minated by a CTLENDVAR byte.
|
|
||||||
|
|
||||||
Commands in back quotes are parsed and stored in a linked list.
|
|
||||||
The locations of these commands in the string are indicated by
|
|
||||||
CTLBACKQ and CTLBACKQ+CTLQUOTE characters, depending upon whether
|
|
||||||
the back quotes were enclosed in double quotes.
|
|
||||||
|
|
||||||
The character CTLESC escapes the next character, so that in case
|
|
||||||
any of the CTL characters mentioned above appear in the input,
|
|
||||||
they can be passed through transparently. CTLESC is also used to
|
|
||||||
escape '*', '?', '[', and '!' characters which were quoted by the
|
|
||||||
user and thus should not be used for file name generation.
|
|
||||||
|
|
||||||
CTLESC characters have proved to be particularly tricky to get
|
|
||||||
right. In the case of here documents which are not subject to
|
|
||||||
variable and command substitution, the parser doesn't insert any
|
|
||||||
CTLESC characters to begin with (so the contents of the text
|
|
||||||
field can be written without any processing). Other here docu-
|
|
||||||
ments, and words which are not subject to splitting and file name
|
|
||||||
generation, have the CTLESC characters removed during the vari-
|
|
||||||
able and command substitution phase. Words which are subject
|
|
||||||
splitting and file name generation have the CTLESC characters re-
|
|
||||||
moved as part of the file name phase.
|
|
||||||
|
|
||||||
EXECUTION: Command execution is handled by the following files:
|
|
||||||
eval.c The top level routines.
|
|
||||||
redir.c Code to handle redirection of input and output.
|
|
||||||
jobs.c Code to handle forking, waiting, and job control.
|
|
||||||
exec.c Code to to path searches and the actual exec sys call.
|
|
||||||
expand.c Code to evaluate arguments.
|
|
||||||
var.c Maintains the variable symbol table. Called from expand.c.
|
|
||||||
|
|
||||||
EVAL.C: Evaltree recursively executes a parse tree. The exit
|
|
||||||
status is returned in the global variable exitstatus. The alter-
|
|
||||||
native entry evalbackcmd is called to evaluate commands in back
|
|
||||||
quotes. It saves the result in memory if the command is a buil-
|
|
||||||
tin; otherwise it forks off a child to execute the command and
|
|
||||||
connects the standard output of the child to a pipe.
|
|
||||||
|
|
||||||
JOBS.C: To create a process, you call makejob to return a job
|
|
||||||
structure, and then call forkshell (passing the job structure as
|
|
||||||
an argument) to create the process. Waitforjob waits for a job
|
|
||||||
to complete. These routines take care of process groups if job
|
|
||||||
control is defined.
|
|
||||||
|
|
||||||
REDIR.C: Ash allows file descriptors to be redirected and then
|
|
||||||
restored without forking off a child process. This is accom-
|
|
||||||
plished by duplicating the original file descriptors. The redir-
|
|
||||||
tab structure records where the file descriptors have be dupli-
|
|
||||||
cated to.
|
|
||||||
|
|
||||||
EXEC.C: The routine find_command locates a command, and enters
|
|
||||||
the command in the hash table if it is not already there. The
|
|
||||||
third argument specifies whether it is to print an error message
|
|
||||||
if the command is not found. (When a pipeline is set up,
|
|
||||||
find_command is called for all the commands in the pipeline be-
|
|
||||||
fore any forking is done, so to get the commands into the hash
|
|
||||||
table of the parent process. But to make command hashing as
|
|
||||||
transparent as possible, we silently ignore errors at that point
|
|
||||||
and only print error messages if the command cannot be found
|
|
||||||
later.)
|
|
||||||
|
|
||||||
The routine shellexec is the interface to the exec system call.
|
|
||||||
|
|
||||||
EXPAND.C: Arguments are processed in three passes. The first
|
|
||||||
(performed by the routine argstr) performs variable and command
|
|
||||||
substitution. The second (ifsbreakup) performs word splitting
|
|
||||||
and the third (expandmeta) performs file name generation. If the
|
|
||||||
"/u" directory is simulated, then when "/u/username" is replaced
|
|
||||||
by the user's home directory, the flag "didudir" is set. This
|
|
||||||
tells the cd command that it should print out the directory name,
|
|
||||||
just as it would if the "/u" directory were implemented using
|
|
||||||
symbolic links.
|
|
||||||
|
|
||||||
VAR.C: Variables are stored in a hash table. Probably we should
|
|
||||||
switch to extensible hashing. The variable name is stored in the
|
|
||||||
same string as the value (using the format "name=value") so that
|
|
||||||
no string copying is needed to create the environment of a com-
|
|
||||||
mand. Variables which the shell references internally are preal-
|
|
||||||
located so that the shell can reference the values of these vari-
|
|
||||||
ables without doing a lookup.
|
|
||||||
|
|
||||||
When a program is run, the code in eval.c sticks any environment
|
|
||||||
variables which precede the command (as in "PATH=xxx command") in
|
|
||||||
the variable table as the simplest way to strip duplicates, and
|
|
||||||
then calls "environment" to get the value of the environment.
|
|
||||||
There are two consequences of this. First, if an assignment to
|
|
||||||
PATH precedes the command, the value of PATH before the assign-
|
|
||||||
ment must be remembered and passed to shellexec. Second, if the
|
|
||||||
program turns out to be a shell procedure, the strings from the
|
|
||||||
environment variables which preceded the command must be pulled
|
|
||||||
out of the table and replaced with strings obtained from malloc,
|
|
||||||
since the former will automatically be freed when the stack (see
|
|
||||||
the entry on memalloc.c) is emptied.
|
|
||||||
|
|
||||||
BUILTIN COMMANDS: The procedures for handling these are scat-
|
|
||||||
tered throughout the code, depending on which location appears
|
|
||||||
most appropriate. They can be recognized because their names al-
|
|
||||||
ways end in "cmd". The mapping from names to procedures is
|
|
||||||
specified in the file builtins, which is processed by the mkbuil-
|
|
||||||
tins command.
|
|
||||||
|
|
||||||
A builtin command is invoked with argc and argv set up like a
|
|
||||||
normal program. A builtin command is allowed to overwrite its
|
|
||||||
arguments. Builtin routines can call nextopt to do option pars-
|
|
||||||
ing. This is kind of like getopt, but you don't pass argc and
|
|
||||||
argv to it. Builtin routines can also call error. This routine
|
|
||||||
normally terminates the shell (or returns to the main command
|
|
||||||
loop if the shell is interactive), but when called from a builtin
|
|
||||||
command it causes the builtin command to terminate with an exit
|
|
||||||
status of 2.
|
|
||||||
|
|
||||||
The directory bltins contains commands which can be compiled in-
|
|
||||||
dependently but can also be built into the shell for efficiency
|
|
||||||
reasons. The makefile in this directory compiles these programs
|
|
||||||
in the normal fashion (so that they can be run regardless of
|
|
||||||
whether the invoker is ash), but also creates a library named
|
|
||||||
bltinlib.a which can be linked with ash. The header file bltin.h
|
|
||||||
takes care of most of the differences between the ash and the
|
|
||||||
stand-alone environment. The user should call the main routine
|
|
||||||
"main", and #define main to be the name of the routine to use
|
|
||||||
when the program is linked into ash. This #define should appear
|
|
||||||
before bltin.h is included; bltin.h will #undef main if the pro-
|
|
||||||
gram is to be compiled stand-alone.
|
|
||||||
|
|
||||||
CD.C: This file defines the cd and pwd builtins. The pwd com-
|
|
||||||
mand runs /bin/pwd the first time it is invoked (unless the user
|
|
||||||
has already done a cd to an absolute pathname), but then
|
|
||||||
remembers the current directory and updates it when the cd com-
|
|
||||||
mand is run, so subsequent pwd commands run very fast. The main
|
|
||||||
complication in the cd command is in the docd command, which
|
|
||||||
resolves symbolic links into actual names and informs the user
|
|
||||||
where the user ended up if he crossed a symbolic link.
|
|
||||||
|
|
||||||
SIGNALS: Trap.c implements the trap command. The routine set-
|
|
||||||
signal figures out what action should be taken when a signal is
|
|
||||||
received and invokes the signal system call to set the signal ac-
|
|
||||||
tion appropriately. When a signal that a user has set a trap for
|
|
||||||
is caught, the routine "onsig" sets a flag. The routine dotrap
|
|
||||||
is called at appropriate points to actually handle the signal.
|
|
||||||
When an interrupt is caught and no trap has been set for that
|
|
||||||
signal, the routine "onint" in error.c is called.
|
|
||||||
|
|
||||||
OUTPUT: Ash uses it's own output routines. There are three out-
|
|
||||||
put structures allocated. "Output" represents the standard out-
|
|
||||||
put, "errout" the standard error, and "memout" contains output
|
|
||||||
which is to be stored in memory. This last is used when a buil-
|
|
||||||
tin command appears in backquotes, to allow its output to be col-
|
|
||||||
lected without doing any I/O through the UNIX operating system.
|
|
||||||
The variables out1 and out2 normally point to output and errout,
|
|
||||||
respectively, but they are set to point to memout when appropri-
|
|
||||||
ate inside backquotes.
|
|
||||||
|
|
||||||
INPUT: The basic input routine is pgetc, which reads from the
|
|
||||||
current input file. There is a stack of input files; the current
|
|
||||||
input file is the top file on this stack. The code allows the
|
|
||||||
input to come from a string rather than a file. (This is for the
|
|
||||||
-c option and the "." and eval builtin commands.) The global
|
|
||||||
variable plinno is saved and restored when files are pushed and
|
|
||||||
popped from the stack. The parser routines store the number of
|
|
||||||
the current line in this variable.
|
|
||||||
|
|
||||||
DEBUGGING: If DEBUG is defined in shell.h, then the shell will
|
|
||||||
write debugging information to the file $HOME/trace. Most of
|
|
||||||
this is done using the TRACE macro, which takes a set of printf
|
|
||||||
arguments inside two sets of parenthesis. Example:
|
|
||||||
"TRACE(("n=%d0, n))". The double parenthesis are necessary be-
|
|
||||||
cause the preprocessor can't handle functions with a variable
|
|
||||||
number of arguments. Defining DEBUG also causes the shell to
|
|
||||||
generate a core dump if it is sent a quit signal. The tracing
|
|
||||||
code is in show.c.
|
|
||||||
|
|
@ -1,9 +0,0 @@
|
||||||
# Copyright 2010 Google Inc. All Rights Reserved.
|
|
||||||
#Fri Jul 16 10:03:08 PDT 2010
|
|
||||||
currentVersion=Unknown
|
|
||||||
version=1.17
|
|
||||||
isNative=true
|
|
||||||
name=ash
|
|
||||||
keywords=ash
|
|
||||||
onDevice=true
|
|
||||||
homepage=http\://www.in-ulm.de/~mascheck/various/ash/
|
|
||||||
273
sh/alias.c
273
sh/alias.c
|
|
@ -1,273 +0,0 @@
|
||||||
/* $NetBSD: alias.c,v 1.12 2003/08/07 09:05:29 agc Exp $ */
|
|
||||||
|
|
||||||
/*-
|
|
||||||
* Copyright (c) 1993
|
|
||||||
* The Regents of the University of California. All rights reserved.
|
|
||||||
*
|
|
||||||
* This code is derived from software contributed to Berkeley by
|
|
||||||
* Kenneth Almquist.
|
|
||||||
*
|
|
||||||
* Redistribution and use in source and binary forms, with or without
|
|
||||||
* modification, are permitted provided that the following conditions
|
|
||||||
* are met:
|
|
||||||
* 1. Redistributions of source code must retain the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer.
|
|
||||||
* 2. Redistributions in binary form must reproduce the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer in the
|
|
||||||
* documentation and/or other materials provided with the distribution.
|
|
||||||
* 3. Neither the name of the University nor the names of its contributors
|
|
||||||
* may be used to endorse or promote products derived from this software
|
|
||||||
* without specific prior written permission.
|
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
|
||||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
||||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
||||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
|
||||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
||||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
|
||||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
|
||||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
||||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
|
||||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
|
||||||
* SUCH DAMAGE.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <sys/cdefs.h>
|
|
||||||
#ifndef lint
|
|
||||||
#if 0
|
|
||||||
static char sccsid[] = "@(#)alias.c 8.3 (Berkeley) 5/4/95";
|
|
||||||
#else
|
|
||||||
__RCSID("$NetBSD: alias.c,v 1.12 2003/08/07 09:05:29 agc Exp $");
|
|
||||||
#endif
|
|
||||||
#endif /* not lint */
|
|
||||||
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include "shell.h"
|
|
||||||
#include "input.h"
|
|
||||||
#include "output.h"
|
|
||||||
#include "error.h"
|
|
||||||
#include "memalloc.h"
|
|
||||||
#include "mystring.h"
|
|
||||||
#include "alias.h"
|
|
||||||
#include "options.h" /* XXX for argptr (should remove?) */
|
|
||||||
#include "var.h"
|
|
||||||
|
|
||||||
#define ATABSIZE 39
|
|
||||||
|
|
||||||
struct alias *atab[ATABSIZE];
|
|
||||||
|
|
||||||
STATIC void setalias(char *, char *);
|
|
||||||
STATIC int unalias(char *);
|
|
||||||
STATIC struct alias **hashalias(char *);
|
|
||||||
|
|
||||||
STATIC
|
|
||||||
void
|
|
||||||
setalias(char *name, char *val)
|
|
||||||
{
|
|
||||||
struct alias *ap, **app;
|
|
||||||
|
|
||||||
app = hashalias(name);
|
|
||||||
for (ap = *app; ap; ap = ap->next) {
|
|
||||||
if (equal(name, ap->name)) {
|
|
||||||
INTOFF;
|
|
||||||
ckfree(ap->val);
|
|
||||||
ap->val = savestr(val);
|
|
||||||
INTON;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/* not found */
|
|
||||||
INTOFF;
|
|
||||||
ap = ckmalloc(sizeof (struct alias));
|
|
||||||
ap->name = savestr(name);
|
|
||||||
/*
|
|
||||||
* XXX - HACK: in order that the parser will not finish reading the
|
|
||||||
* alias value off the input before processing the next alias, we
|
|
||||||
* dummy up an extra space at the end of the alias. This is a crock
|
|
||||||
* and should be re-thought. The idea (if you feel inclined to help)
|
|
||||||
* is to avoid alias recursions. The mechanism used is: when
|
|
||||||
* expanding an alias, the value of the alias is pushed back on the
|
|
||||||
* input as a string and a pointer to the alias is stored with the
|
|
||||||
* string. The alias is marked as being in use. When the input
|
|
||||||
* routine finishes reading the string, it markes the alias not
|
|
||||||
* in use. The problem is synchronization with the parser. Since
|
|
||||||
* it reads ahead, the alias is marked not in use before the
|
|
||||||
* resulting token(s) is next checked for further alias sub. The
|
|
||||||
* H A C K is that we add a little fluff after the alias value
|
|
||||||
* so that the string will not be exhausted. This is a good
|
|
||||||
* idea ------- ***NOT***
|
|
||||||
*/
|
|
||||||
#ifdef notyet
|
|
||||||
ap->val = savestr(val);
|
|
||||||
#else /* hack */
|
|
||||||
{
|
|
||||||
int len = strlen(val);
|
|
||||||
ap->val = ckmalloc(len + 2);
|
|
||||||
memcpy(ap->val, val, len);
|
|
||||||
ap->val[len] = ' '; /* fluff */
|
|
||||||
ap->val[len+1] = '\0';
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
ap->next = *app;
|
|
||||||
*app = ap;
|
|
||||||
INTON;
|
|
||||||
}
|
|
||||||
|
|
||||||
STATIC int
|
|
||||||
unalias(char *name)
|
|
||||||
{
|
|
||||||
struct alias *ap, **app;
|
|
||||||
|
|
||||||
app = hashalias(name);
|
|
||||||
|
|
||||||
for (ap = *app; ap; app = &(ap->next), ap = ap->next) {
|
|
||||||
if (equal(name, ap->name)) {
|
|
||||||
/*
|
|
||||||
* if the alias is currently in use (i.e. its
|
|
||||||
* buffer is being used by the input routine) we
|
|
||||||
* just null out the name instead of freeing it.
|
|
||||||
* We could clear it out later, but this situation
|
|
||||||
* is so rare that it hardly seems worth it.
|
|
||||||
*/
|
|
||||||
if (ap->flag & ALIASINUSE)
|
|
||||||
*ap->name = '\0';
|
|
||||||
else {
|
|
||||||
INTOFF;
|
|
||||||
*app = ap->next;
|
|
||||||
ckfree(ap->name);
|
|
||||||
ckfree(ap->val);
|
|
||||||
ckfree(ap);
|
|
||||||
INTON;
|
|
||||||
}
|
|
||||||
return (0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return (1);
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef mkinit
|
|
||||||
MKINIT void rmaliases(void);
|
|
||||||
|
|
||||||
SHELLPROC {
|
|
||||||
rmaliases();
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
void
|
|
||||||
rmaliases(void)
|
|
||||||
{
|
|
||||||
struct alias *ap, *tmp;
|
|
||||||
int i;
|
|
||||||
|
|
||||||
INTOFF;
|
|
||||||
for (i = 0; i < ATABSIZE; i++) {
|
|
||||||
ap = atab[i];
|
|
||||||
atab[i] = NULL;
|
|
||||||
while (ap) {
|
|
||||||
ckfree(ap->name);
|
|
||||||
ckfree(ap->val);
|
|
||||||
tmp = ap;
|
|
||||||
ap = ap->next;
|
|
||||||
ckfree(tmp);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
INTON;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct alias *
|
|
||||||
lookupalias(char *name, int check)
|
|
||||||
{
|
|
||||||
struct alias *ap = *hashalias(name);
|
|
||||||
|
|
||||||
for (; ap; ap = ap->next) {
|
|
||||||
if (equal(name, ap->name)) {
|
|
||||||
if (check && (ap->flag & ALIASINUSE))
|
|
||||||
return (NULL);
|
|
||||||
return (ap);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return (NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
char *
|
|
||||||
get_alias_text(char *name)
|
|
||||||
{
|
|
||||||
struct alias *ap;
|
|
||||||
|
|
||||||
ap = lookupalias(name, 0);
|
|
||||||
if (ap == NULL)
|
|
||||||
return NULL;
|
|
||||||
return ap->val;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* TODO - sort output
|
|
||||||
*/
|
|
||||||
int
|
|
||||||
aliascmd(int argc, char **argv)
|
|
||||||
{
|
|
||||||
char *n, *v;
|
|
||||||
int ret = 0;
|
|
||||||
struct alias *ap;
|
|
||||||
|
|
||||||
if (argc == 1) {
|
|
||||||
int i;
|
|
||||||
|
|
||||||
for (i = 0; i < ATABSIZE; i++)
|
|
||||||
for (ap = atab[i]; ap; ap = ap->next) {
|
|
||||||
if (*ap->name != '\0') {
|
|
||||||
out1fmt("alias %s=", ap->name);
|
|
||||||
print_quoted(ap->val);
|
|
||||||
out1c('\n');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return (0);
|
|
||||||
}
|
|
||||||
while ((n = *++argv) != NULL) {
|
|
||||||
if ((v = strchr(n+1, '=')) == NULL) { /* n+1: funny ksh stuff */
|
|
||||||
if ((ap = lookupalias(n, 0)) == NULL) {
|
|
||||||
outfmt(out2, "alias: %s not found\n", n);
|
|
||||||
ret = 1;
|
|
||||||
} else {
|
|
||||||
out1fmt("alias %s=", n);
|
|
||||||
print_quoted(ap->val);
|
|
||||||
out1c('\n');
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
*v++ = '\0';
|
|
||||||
setalias(n, v);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return (ret);
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
unaliascmd(int argc, char **argv)
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
|
|
||||||
while ((i = nextopt("a")) != '\0') {
|
|
||||||
if (i == 'a') {
|
|
||||||
rmaliases();
|
|
||||||
return (0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for (i = 0; *argptr; argptr++)
|
|
||||||
i = unalias(*argptr);
|
|
||||||
|
|
||||||
return (i);
|
|
||||||
}
|
|
||||||
|
|
||||||
STATIC struct alias **
|
|
||||||
hashalias(char *p)
|
|
||||||
{
|
|
||||||
unsigned int hashval;
|
|
||||||
|
|
||||||
hashval = *p << 4;
|
|
||||||
while (*p)
|
|
||||||
hashval+= *p++;
|
|
||||||
return &atab[hashval % ATABSIZE];
|
|
||||||
}
|
|
||||||
50
sh/alias.h
50
sh/alias.h
|
|
@ -1,50 +0,0 @@
|
||||||
/* $NetBSD: alias.h,v 1.6 2003/08/07 09:05:29 agc Exp $ */
|
|
||||||
|
|
||||||
/*-
|
|
||||||
* Copyright (c) 1993
|
|
||||||
* The Regents of the University of California. All rights reserved.
|
|
||||||
*
|
|
||||||
* This code is derived from software contributed to Berkeley by
|
|
||||||
* Kenneth Almquist.
|
|
||||||
*
|
|
||||||
* Redistribution and use in source and binary forms, with or without
|
|
||||||
* modification, are permitted provided that the following conditions
|
|
||||||
* are met:
|
|
||||||
* 1. Redistributions of source code must retain the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer.
|
|
||||||
* 2. Redistributions in binary form must reproduce the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer in the
|
|
||||||
* documentation and/or other materials provided with the distribution.
|
|
||||||
* 3. Neither the name of the University nor the names of its contributors
|
|
||||||
* may be used to endorse or promote products derived from this software
|
|
||||||
* without specific prior written permission.
|
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
|
||||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
||||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
||||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
|
||||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
||||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
|
||||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
|
||||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
||||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
|
||||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
|
||||||
* SUCH DAMAGE.
|
|
||||||
*
|
|
||||||
* @(#)alias.h 8.2 (Berkeley) 5/4/95
|
|
||||||
*/
|
|
||||||
|
|
||||||
#define ALIASINUSE 1
|
|
||||||
|
|
||||||
struct alias {
|
|
||||||
struct alias *next;
|
|
||||||
char *name;
|
|
||||||
char *val;
|
|
||||||
int flag;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct alias *lookupalias(char *, int);
|
|
||||||
char *get_alias_text(char *);
|
|
||||||
int aliascmd(int, char **);
|
|
||||||
int unaliascmd(int, char **);
|
|
||||||
void rmaliases(void);
|
|
||||||
1587
sh/arith.c
1587
sh/arith.c
File diff suppressed because it is too large
Load diff
25
sh/arith.h
25
sh/arith.h
|
|
@ -1,25 +0,0 @@
|
||||||
#define ARITH_NUM 258
|
|
||||||
#define ARITH_LPAREN 259
|
|
||||||
#define ARITH_RPAREN 260
|
|
||||||
#define ARITH_OR 261
|
|
||||||
#define ARITH_AND 262
|
|
||||||
#define ARITH_BOR 263
|
|
||||||
#define ARITH_BXOR 264
|
|
||||||
#define ARITH_BAND 265
|
|
||||||
#define ARITH_NE 266
|
|
||||||
#define ARITH_EQ 267
|
|
||||||
#define ARITH_LE 268
|
|
||||||
#define ARITH_GE 269
|
|
||||||
#define ARITH_GT 270
|
|
||||||
#define ARITH_LT 271
|
|
||||||
#define ARITH_RSHIFT 272
|
|
||||||
#define ARITH_LSHIFT 273
|
|
||||||
#define ARITH_SUB 274
|
|
||||||
#define ARITH_ADD 275
|
|
||||||
#define ARITH_REM 276
|
|
||||||
#define ARITH_DIV 277
|
|
||||||
#define ARITH_MUL 278
|
|
||||||
#define ARITH_BNOT 279
|
|
||||||
#define ARITH_NOT 280
|
|
||||||
#define ARITH_UNARYPLUS 281
|
|
||||||
#define ARITH_UNARYMINUS 282
|
|
||||||
199
sh/arith.y
199
sh/arith.y
|
|
@ -1,199 +0,0 @@
|
||||||
%{
|
|
||||||
/* $NetBSD: arith.y,v 1.17 2003/09/17 17:33:36 jmmv Exp $ */
|
|
||||||
|
|
||||||
/*-
|
|
||||||
* Copyright (c) 1993
|
|
||||||
* The Regents of the University of California. All rights reserved.
|
|
||||||
*
|
|
||||||
* This code is derived from software contributed to Berkeley by
|
|
||||||
* Kenneth Almquist.
|
|
||||||
*
|
|
||||||
* Redistribution and use in source and binary forms, with or without
|
|
||||||
* modification, are permitted provided that the following conditions
|
|
||||||
* are met:
|
|
||||||
* 1. Redistributions of source code must retain the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer.
|
|
||||||
* 2. Redistributions in binary form must reproduce the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer in the
|
|
||||||
* documentation and/or other materials provided with the distribution.
|
|
||||||
* 3. Neither the name of the University nor the names of its contributors
|
|
||||||
* may be used to endorse or promote products derived from this software
|
|
||||||
* without specific prior written permission.
|
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
|
||||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
||||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
||||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
|
||||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
||||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
|
||||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
|
||||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
||||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
|
||||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
|
||||||
* SUCH DAMAGE.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <sys/cdefs.h>
|
|
||||||
#ifndef lint
|
|
||||||
#if 0
|
|
||||||
static char sccsid[] = "@(#)arith.y 8.3 (Berkeley) 5/4/95";
|
|
||||||
#else
|
|
||||||
__RCSID("$NetBSD: arith.y,v 1.17 2003/09/17 17:33:36 jmmv Exp $");
|
|
||||||
#endif
|
|
||||||
#endif /* not lint */
|
|
||||||
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include "expand.h"
|
|
||||||
#include "shell.h"
|
|
||||||
#include "error.h"
|
|
||||||
#include "output.h"
|
|
||||||
#include "memalloc.h"
|
|
||||||
|
|
||||||
const char *arith_buf, *arith_startbuf;
|
|
||||||
|
|
||||||
void yyerror(const char *);
|
|
||||||
#ifdef TESTARITH
|
|
||||||
int main(int , char *[]);
|
|
||||||
int error(char *);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
%}
|
|
||||||
%token ARITH_NUM ARITH_LPAREN ARITH_RPAREN
|
|
||||||
|
|
||||||
%left ARITH_OR
|
|
||||||
%left ARITH_AND
|
|
||||||
%left ARITH_BOR
|
|
||||||
%left ARITH_BXOR
|
|
||||||
%left ARITH_BAND
|
|
||||||
%left ARITH_EQ ARITH_NE
|
|
||||||
%left ARITH_LT ARITH_GT ARITH_GE ARITH_LE
|
|
||||||
%left ARITH_LSHIFT ARITH_RSHIFT
|
|
||||||
%left ARITH_ADD ARITH_SUB
|
|
||||||
%left ARITH_MUL ARITH_DIV ARITH_REM
|
|
||||||
%left ARITH_UNARYMINUS ARITH_UNARYPLUS ARITH_NOT ARITH_BNOT
|
|
||||||
%%
|
|
||||||
|
|
||||||
exp: expr {
|
|
||||||
return ($1);
|
|
||||||
}
|
|
||||||
;
|
|
||||||
|
|
||||||
|
|
||||||
expr: ARITH_LPAREN expr ARITH_RPAREN { $$ = $2; }
|
|
||||||
| expr ARITH_OR expr { $$ = $1 ? $1 : $3 ? $3 : 0; }
|
|
||||||
| expr ARITH_AND expr { $$ = $1 ? ( $3 ? $3 : 0 ) : 0; }
|
|
||||||
| expr ARITH_BOR expr { $$ = $1 | $3; }
|
|
||||||
| expr ARITH_BXOR expr { $$ = $1 ^ $3; }
|
|
||||||
| expr ARITH_BAND expr { $$ = $1 & $3; }
|
|
||||||
| expr ARITH_EQ expr { $$ = $1 == $3; }
|
|
||||||
| expr ARITH_GT expr { $$ = $1 > $3; }
|
|
||||||
| expr ARITH_GE expr { $$ = $1 >= $3; }
|
|
||||||
| expr ARITH_LT expr { $$ = $1 < $3; }
|
|
||||||
| expr ARITH_LE expr { $$ = $1 <= $3; }
|
|
||||||
| expr ARITH_NE expr { $$ = $1 != $3; }
|
|
||||||
| expr ARITH_LSHIFT expr { $$ = $1 << $3; }
|
|
||||||
| expr ARITH_RSHIFT expr { $$ = $1 >> $3; }
|
|
||||||
| expr ARITH_ADD expr { $$ = $1 + $3; }
|
|
||||||
| expr ARITH_SUB expr { $$ = $1 - $3; }
|
|
||||||
| expr ARITH_MUL expr { $$ = $1 * $3; }
|
|
||||||
| expr ARITH_DIV expr {
|
|
||||||
if ($3 == 0)
|
|
||||||
yyerror("division by zero");
|
|
||||||
$$ = $1 / $3;
|
|
||||||
}
|
|
||||||
| expr ARITH_REM expr {
|
|
||||||
if ($3 == 0)
|
|
||||||
yyerror("division by zero");
|
|
||||||
$$ = $1 % $3;
|
|
||||||
}
|
|
||||||
| ARITH_NOT expr { $$ = !($2); }
|
|
||||||
| ARITH_BNOT expr { $$ = ~($2); }
|
|
||||||
| ARITH_SUB expr %prec ARITH_UNARYMINUS { $$ = -($2); }
|
|
||||||
| ARITH_ADD expr %prec ARITH_UNARYPLUS { $$ = $2; }
|
|
||||||
| ARITH_NUM
|
|
||||||
;
|
|
||||||
%%
|
|
||||||
int
|
|
||||||
arith(s)
|
|
||||||
const char *s;
|
|
||||||
{
|
|
||||||
long result;
|
|
||||||
|
|
||||||
arith_buf = arith_startbuf = s;
|
|
||||||
|
|
||||||
INTOFF;
|
|
||||||
result = yyparse();
|
|
||||||
arith_lex_reset(); /* reprime lex */
|
|
||||||
INTON;
|
|
||||||
|
|
||||||
return (result);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* The exp(1) builtin.
|
|
||||||
*/
|
|
||||||
int
|
|
||||||
expcmd(argc, argv)
|
|
||||||
int argc;
|
|
||||||
char **argv;
|
|
||||||
{
|
|
||||||
const char *p;
|
|
||||||
char *concat;
|
|
||||||
char **ap;
|
|
||||||
long i;
|
|
||||||
|
|
||||||
if (argc > 1) {
|
|
||||||
p = argv[1];
|
|
||||||
if (argc > 2) {
|
|
||||||
/*
|
|
||||||
* concatenate arguments
|
|
||||||
*/
|
|
||||||
STARTSTACKSTR(concat);
|
|
||||||
ap = argv + 2;
|
|
||||||
for (;;) {
|
|
||||||
while (*p)
|
|
||||||
STPUTC(*p++, concat);
|
|
||||||
if ((p = *ap++) == NULL)
|
|
||||||
break;
|
|
||||||
STPUTC(' ', concat);
|
|
||||||
}
|
|
||||||
STPUTC('\0', concat);
|
|
||||||
p = grabstackstr(concat);
|
|
||||||
}
|
|
||||||
} else
|
|
||||||
p = "";
|
|
||||||
|
|
||||||
i = arith(p);
|
|
||||||
|
|
||||||
out1fmt("%ld\n", i);
|
|
||||||
return (! i);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*************************/
|
|
||||||
#ifdef TEST_ARITH
|
|
||||||
#include <stdio.h>
|
|
||||||
main(argc, argv)
|
|
||||||
char *argv[];
|
|
||||||
{
|
|
||||||
printf("%d\n", exp(argv[1]));
|
|
||||||
}
|
|
||||||
error(s)
|
|
||||||
char *s;
|
|
||||||
{
|
|
||||||
fprintf(stderr, "exp: %s\n", s);
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
void
|
|
||||||
yyerror(s)
|
|
||||||
const char *s;
|
|
||||||
{
|
|
||||||
|
|
||||||
// yyerrok;
|
|
||||||
yyclearin;
|
|
||||||
arith_lex_reset(); /* reprime lex */
|
|
||||||
error("arithmetic expression: %s: \"%s\"", s, arith_startbuf);
|
|
||||||
/* NOTREACHED */
|
|
||||||
}
|
|
||||||
1890
sh/arith_lex.c
1890
sh/arith_lex.c
File diff suppressed because it is too large
Load diff
103
sh/arith_lex.l
103
sh/arith_lex.l
|
|
@ -1,103 +0,0 @@
|
||||||
%{
|
|
||||||
/* $NetBSD: arith_lex.l,v 1.12.6.1 2005/04/07 11:38:58 tron Exp $ */
|
|
||||||
|
|
||||||
/*-
|
|
||||||
* Copyright (c) 1993
|
|
||||||
* The Regents of the University of California. All rights reserved.
|
|
||||||
*
|
|
||||||
* This code is derived from software contributed to Berkeley by
|
|
||||||
* Kenneth Almquist.
|
|
||||||
*
|
|
||||||
* Redistribution and use in source and binary forms, with or without
|
|
||||||
* modification, are permitted provided that the following conditions
|
|
||||||
* are met:
|
|
||||||
* 1. Redistributions of source code must retain the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer.
|
|
||||||
* 2. Redistributions in binary form must reproduce the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer in the
|
|
||||||
* documentation and/or other materials provided with the distribution.
|
|
||||||
* 3. Neither the name of the University nor the names of its contributors
|
|
||||||
* may be used to endorse or promote products derived from this software
|
|
||||||
* without specific prior written permission.
|
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
|
||||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
||||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
||||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
|
||||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
||||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
|
||||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
|
||||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
||||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
|
||||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
|
||||||
* SUCH DAMAGE.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <sys/cdefs.h>
|
|
||||||
#ifndef lint
|
|
||||||
#if 0
|
|
||||||
static char sccsid[] = "@(#)arith_lex.l 8.3 (Berkeley) 5/4/95";
|
|
||||||
#else
|
|
||||||
__RCSID("$NetBSD: arith_lex.l,v 1.12.6.1 2005/04/07 11:38:58 tron Exp $");
|
|
||||||
#endif
|
|
||||||
#endif /* not lint */
|
|
||||||
|
|
||||||
#include <unistd.h>
|
|
||||||
#include "arith.h"
|
|
||||||
#include "error.h"
|
|
||||||
#include "expand.h"
|
|
||||||
#include "var.h"
|
|
||||||
|
|
||||||
extern int yylval;
|
|
||||||
extern char *arith_buf, *arith_startbuf;
|
|
||||||
#undef YY_INPUT
|
|
||||||
#define YY_INPUT(buf,result,max) \
|
|
||||||
result = (*buf = *arith_buf++) ? 1 : YY_NULL;
|
|
||||||
#define YY_NO_UNPUT
|
|
||||||
%}
|
|
||||||
%option noyywrap
|
|
||||||
|
|
||||||
%%
|
|
||||||
[ \t\n] { ; }
|
|
||||||
0x[0-9a-fA-F]+ { yylval = strtol(yytext, 0, 0); return(ARITH_NUM); }
|
|
||||||
0[0-7]* { yylval = strtol(yytext, 0, 0); return(ARITH_NUM); }
|
|
||||||
[1-9][0-9]* { yylval = strtol(yytext, 0, 0); return(ARITH_NUM); }
|
|
||||||
[A-Za-z_][A-Za-z_0-9]* { char *v = lookupvar(yytext);
|
|
||||||
if (v) {
|
|
||||||
yylval = strtol(v, &v, 0);
|
|
||||||
if (*v == 0)
|
|
||||||
return ARITH_NUM;
|
|
||||||
}
|
|
||||||
error("arith: syntax error: \"%s\"", arith_startbuf);
|
|
||||||
}
|
|
||||||
"(" { return(ARITH_LPAREN); }
|
|
||||||
")" { return(ARITH_RPAREN); }
|
|
||||||
"||" { return(ARITH_OR); }
|
|
||||||
"&&" { return(ARITH_AND); }
|
|
||||||
"|" { return(ARITH_BOR); }
|
|
||||||
"^" { return(ARITH_BXOR); }
|
|
||||||
"&" { return(ARITH_BAND); }
|
|
||||||
"==" { return(ARITH_EQ); }
|
|
||||||
"!=" { return(ARITH_NE); }
|
|
||||||
">" { return(ARITH_GT); }
|
|
||||||
">=" { return(ARITH_GE); }
|
|
||||||
"<" { return(ARITH_LT); }
|
|
||||||
"<=" { return(ARITH_LE); }
|
|
||||||
"<<" { return(ARITH_LSHIFT); }
|
|
||||||
">>" { return(ARITH_RSHIFT); }
|
|
||||||
"*" { return(ARITH_MUL); }
|
|
||||||
"/" { return(ARITH_DIV); }
|
|
||||||
"%" { return(ARITH_REM); }
|
|
||||||
"+" { return(ARITH_ADD); }
|
|
||||||
"-" { return(ARITH_SUB); }
|
|
||||||
"~" { return(ARITH_BNOT); }
|
|
||||||
"!" { return(ARITH_NOT); }
|
|
||||||
. { error("arith: syntax error: \"%s\"", arith_startbuf); }
|
|
||||||
%%
|
|
||||||
|
|
||||||
void
|
|
||||||
arith_lex_reset() {
|
|
||||||
#ifdef YY_NEW_FILE
|
|
||||||
YY_NEW_FILE;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
@ -1,94 +0,0 @@
|
||||||
/* $NetBSD: bltin.h,v 1.11 2003/08/07 09:05:40 agc Exp $ */
|
|
||||||
|
|
||||||
/*-
|
|
||||||
* Copyright (c) 1991, 1993
|
|
||||||
* The Regents of the University of California. All rights reserved.
|
|
||||||
*
|
|
||||||
* This code is derived from software contributed to Berkeley by
|
|
||||||
* Kenneth Almquist.
|
|
||||||
*
|
|
||||||
* Redistribution and use in source and binary forms, with or without
|
|
||||||
* modification, are permitted provided that the following conditions
|
|
||||||
* are met:
|
|
||||||
* 1. Redistributions of source code must retain the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer.
|
|
||||||
* 2. Redistributions in binary form must reproduce the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer in the
|
|
||||||
* documentation and/or other materials provided with the distribution.
|
|
||||||
* 3. Neither the name of the University nor the names of its contributors
|
|
||||||
* may be used to endorse or promote products derived from this software
|
|
||||||
* without specific prior written permission.
|
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
|
||||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
||||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
||||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
|
||||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
||||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
|
||||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
|
||||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
||||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
|
||||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
|
||||||
* SUCH DAMAGE.
|
|
||||||
*
|
|
||||||
* @(#)bltin.h 8.1 (Berkeley) 5/31/93
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
* This file is included by programs which are optionally built into the
|
|
||||||
* shell. If SHELL is defined, we try to map the standard UNIX library
|
|
||||||
* routines to ash routines using defines.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "../shell.h"
|
|
||||||
#include "../mystring.h"
|
|
||||||
#ifdef SHELL
|
|
||||||
#include "../output.h"
|
|
||||||
#include "../error.h"
|
|
||||||
#undef stdout
|
|
||||||
#undef stderr
|
|
||||||
#undef putc
|
|
||||||
#undef putchar
|
|
||||||
#undef fileno
|
|
||||||
#define stdout out1
|
|
||||||
#define stderr out2
|
|
||||||
#define printf out1fmt
|
|
||||||
#define putc(c, file) outc(c, file)
|
|
||||||
#define putchar(c) out1c(c)
|
|
||||||
#define FILE struct output
|
|
||||||
#define fprintf outfmt
|
|
||||||
#define fputs outstr
|
|
||||||
#define fflush flushout
|
|
||||||
#define fileno(f) ((f)->fd)
|
|
||||||
#define INITARGS(argv)
|
|
||||||
#define err sh_err
|
|
||||||
#define verr sh_verr
|
|
||||||
#define errx sh_errx
|
|
||||||
#define verrx sh_verrx
|
|
||||||
#define warn sh_warn
|
|
||||||
#define vwarn sh_vwarn
|
|
||||||
#define warnx sh_warnx
|
|
||||||
#define vwarnx sh_vwarnx
|
|
||||||
#define exit sh_exit
|
|
||||||
#define setprogname(s)
|
|
||||||
#define getprogname() commandname
|
|
||||||
#define setlocate(l,s) 0
|
|
||||||
|
|
||||||
#define getenv(p) bltinlookup((p),0)
|
|
||||||
|
|
||||||
#else
|
|
||||||
#undef NULL
|
|
||||||
#include <stdio.h>
|
|
||||||
#undef main
|
|
||||||
#define INITARGS(argv) if ((commandname = argv[0]) == NULL) {fputs("Argc is zero\n", stderr); exit(2);} else
|
|
||||||
#endif
|
|
||||||
|
|
||||||
pointer stalloc(int);
|
|
||||||
void error(const char *, ...);
|
|
||||||
void sh_warnx(const char *, ...);
|
|
||||||
void sh_exit(int) __attribute__((__noreturn__));
|
|
||||||
|
|
||||||
int echocmd(int, char **);
|
|
||||||
|
|
||||||
|
|
||||||
extern const char *commandname;
|
|
||||||
109
sh/bltin/echo.1
109
sh/bltin/echo.1
|
|
@ -1,109 +0,0 @@
|
||||||
.\" $NetBSD: echo.1,v 1.13 2003/08/07 09:05:40 agc Exp $
|
|
||||||
.\"
|
|
||||||
.\" Copyright (c) 1991, 1993
|
|
||||||
.\" The Regents of the University of California. All rights reserved.
|
|
||||||
.\"
|
|
||||||
.\" This code is derived from software contributed to Berkeley by
|
|
||||||
.\" Kenneth Almquist.
|
|
||||||
.\" Copyright 1989 by Kenneth Almquist
|
|
||||||
.\"
|
|
||||||
.\" Redistribution and use in source and binary forms, with or without
|
|
||||||
.\" modification, are permitted provided that the following conditions
|
|
||||||
.\" are met:
|
|
||||||
.\" 1. Redistributions of source code must retain the above copyright
|
|
||||||
.\" notice, this list of conditions and the following disclaimer.
|
|
||||||
.\" 2. Redistributions in binary form must reproduce the above copyright
|
|
||||||
.\" notice, this list of conditions and the following disclaimer in the
|
|
||||||
.\" documentation and/or other materials provided with the distribution.
|
|
||||||
.\" 3. Neither the name of the University nor the names of its contributors
|
|
||||||
.\" may be used to endorse or promote products derived from this software
|
|
||||||
.\" without specific prior written permission.
|
|
||||||
.\"
|
|
||||||
.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
|
||||||
.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
||||||
.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
||||||
.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
|
||||||
.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
||||||
.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
|
||||||
.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
|
||||||
.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
||||||
.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
|
||||||
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
|
||||||
.\" SUCH DAMAGE.
|
|
||||||
.\"
|
|
||||||
.\" @(#)echo.1 8.1 (Berkeley) 5/31/93
|
|
||||||
.\"
|
|
||||||
.Dd May 31, 1993
|
|
||||||
.Dt ECHO 1
|
|
||||||
.Os
|
|
||||||
.Sh NAME
|
|
||||||
.Nm echo
|
|
||||||
.Nd produce message in a shell script
|
|
||||||
.Sh SYNOPSIS
|
|
||||||
.Nm
|
|
||||||
.Op Fl n | Fl e
|
|
||||||
.Ar args ...
|
|
||||||
.Sh DESCRIPTION
|
|
||||||
.Nm
|
|
||||||
prints its arguments on the standard output, separated by spaces.
|
|
||||||
Unless the
|
|
||||||
.Fl n
|
|
||||||
option is present, a newline is output following the arguments.
|
|
||||||
The
|
|
||||||
.Fl e
|
|
||||||
option causes
|
|
||||||
.Nm
|
|
||||||
to treat the escape sequences specially, as described in the following
|
|
||||||
paragraph.
|
|
||||||
The
|
|
||||||
.Fl e
|
|
||||||
option is the default, and is provided solely for compatibility with
|
|
||||||
other systems.
|
|
||||||
Only one of the options
|
|
||||||
.Fl n
|
|
||||||
and
|
|
||||||
.Fl e
|
|
||||||
may be given.
|
|
||||||
.Pp
|
|
||||||
If any of the following sequences of characters is encountered during
|
|
||||||
output, the sequence is not output. Instead, the specified action is
|
|
||||||
performed:
|
|
||||||
.Bl -tag -width indent
|
|
||||||
.It Li \eb
|
|
||||||
A backspace character is output.
|
|
||||||
.It Li \ec
|
|
||||||
Subsequent output is suppressed. This is normally used at the end of the
|
|
||||||
last argument to suppress the trailing newline that
|
|
||||||
.Nm
|
|
||||||
would otherwise output.
|
|
||||||
.It Li \ef
|
|
||||||
Output a form feed.
|
|
||||||
.It Li \en
|
|
||||||
Output a newline character.
|
|
||||||
.It Li \er
|
|
||||||
Output a carriage return.
|
|
||||||
.It Li \et
|
|
||||||
Output a (horizontal) tab character.
|
|
||||||
.It Li \ev
|
|
||||||
Output a vertical tab.
|
|
||||||
.It Li \e0 Ns Ar digits
|
|
||||||
Output the character whose value is given by zero to three digits.
|
|
||||||
If there are zero digits, a nul character is output.
|
|
||||||
.It Li \e\e
|
|
||||||
Output a backslash.
|
|
||||||
.El
|
|
||||||
.Sh HINTS
|
|
||||||
Remember that backslash is special to the shell and needs to be escaped.
|
|
||||||
To output a message to standard error, say
|
|
||||||
.Pp
|
|
||||||
.D1 echo message \*[Gt]\*[Am]2
|
|
||||||
.Sh BUGS
|
|
||||||
The octal character escape mechanism
|
|
||||||
.Pq Li \e0 Ns Ar digits
|
|
||||||
differs from the
|
|
||||||
C language mechanism.
|
|
||||||
.Pp
|
|
||||||
There is no way to force
|
|
||||||
.Nm
|
|
||||||
to treat its arguments literally, rather than interpreting them as
|
|
||||||
options and escape sequences.
|
|
||||||
116
sh/bltin/echo.c
116
sh/bltin/echo.c
|
|
@ -1,116 +0,0 @@
|
||||||
/* $NetBSD: echo.c,v 1.12 2005/02/06 04:43:43 perry Exp $ */
|
|
||||||
|
|
||||||
/*-
|
|
||||||
* Copyright (c) 1991, 1993
|
|
||||||
* The Regents of the University of California. All rights reserved.
|
|
||||||
*
|
|
||||||
* This code is derived from software contributed to Berkeley by
|
|
||||||
* Kenneth Almquist.
|
|
||||||
*
|
|
||||||
* Redistribution and use in source and binary forms, with or without
|
|
||||||
* modification, are permitted provided that the following conditions
|
|
||||||
* are met:
|
|
||||||
* 1. Redistributions of source code must retain the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer.
|
|
||||||
* 2. Redistributions in binary form must reproduce the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer in the
|
|
||||||
* documentation and/or other materials provided with the distribution.
|
|
||||||
* 3. Neither the name of the University nor the names of its contributors
|
|
||||||
* may be used to endorse or promote products derived from this software
|
|
||||||
* without specific prior written permission.
|
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
|
||||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
||||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
||||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
|
||||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
||||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
|
||||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
|
||||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
||||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
|
||||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
|
||||||
* SUCH DAMAGE.
|
|
||||||
*
|
|
||||||
* @(#)echo.c 8.1 (Berkeley) 5/31/93
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Echo command.
|
|
||||||
*
|
|
||||||
* echo is steeped in tradition - several of them!
|
|
||||||
* netbsd has supported 'echo [-n | -e] args' in spite of -e not being
|
|
||||||
* documented anywhere.
|
|
||||||
* Posix requires that -n be supported, output from strings containing
|
|
||||||
* \ is implementation defined
|
|
||||||
* The Single Unix Spec requires that \ escapes be treated as if -e
|
|
||||||
* were set, but that -n not be treated as an option.
|
|
||||||
* (ksh supports 'echo [-eEn] args', but not -- so that it is actually
|
|
||||||
* impossible to actually output '-n')
|
|
||||||
*
|
|
||||||
* It is suggested that 'printf "%b" "string"' be used to get \ sequences
|
|
||||||
* expanded. printf is now a builtin of netbsd's sh and csh.
|
|
||||||
*/
|
|
||||||
|
|
||||||
//#define main echocmd
|
|
||||||
|
|
||||||
#include "bltin.h"
|
|
||||||
|
|
||||||
int
|
|
||||||
echocmd(int argc, char **argv)
|
|
||||||
{
|
|
||||||
char **ap;
|
|
||||||
char *p;
|
|
||||||
char c;
|
|
||||||
int count;
|
|
||||||
int nflag = 0;
|
|
||||||
int eflag = 0;
|
|
||||||
|
|
||||||
ap = argv;
|
|
||||||
if (argc)
|
|
||||||
ap++;
|
|
||||||
|
|
||||||
if ((p = *ap) != NULL) {
|
|
||||||
if (equal(p, "-n")) {
|
|
||||||
nflag = 1;
|
|
||||||
ap++;
|
|
||||||
} else if (equal(p, "-e")) {
|
|
||||||
eflag = 1;
|
|
||||||
ap++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
while ((p = *ap++) != NULL) {
|
|
||||||
while ((c = *p++) != '\0') {
|
|
||||||
if (c == '\\' && eflag) {
|
|
||||||
switch (*p++) {
|
|
||||||
case 'a': c = '\a'; break; /* bell */
|
|
||||||
case 'b': c = '\b'; break;
|
|
||||||
case 'c': return 0; /* exit */
|
|
||||||
case 'e': c = 033; break; /* escape */
|
|
||||||
case 'f': c = '\f'; break;
|
|
||||||
case 'n': c = '\n'; break;
|
|
||||||
case 'r': c = '\r'; break;
|
|
||||||
case 't': c = '\t'; break;
|
|
||||||
case 'v': c = '\v'; break;
|
|
||||||
case '\\': break; /* c = '\\' */
|
|
||||||
case '0':
|
|
||||||
c = 0;
|
|
||||||
count = 3;
|
|
||||||
while (--count >= 0 && (unsigned)(*p - '0') < 8)
|
|
||||||
c = (c << 3) + (*p++ - '0');
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
/* Output the '/' and char following */
|
|
||||||
p--;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
putchar(c);
|
|
||||||
}
|
|
||||||
if (*ap)
|
|
||||||
putchar(' ');
|
|
||||||
}
|
|
||||||
if (! nflag)
|
|
||||||
putchar('\n');
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
@ -1,61 +0,0 @@
|
||||||
/*
|
|
||||||
* This file was generated by the mkbuiltins program.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "shell.h"
|
|
||||||
#include "builtins.h"
|
|
||||||
|
|
||||||
const struct builtincmd builtincmd[] = {
|
|
||||||
|
|
||||||
{ "command", bltincmd },
|
|
||||||
{ "bg", bgcmd },
|
|
||||||
{ "cd", cdcmd },
|
|
||||||
{ "chdir", cdcmd },
|
|
||||||
{ "echo", echocmd },
|
|
||||||
{ "exp", expcmd },
|
|
||||||
{ "let", expcmd },
|
|
||||||
{ "false", falsecmd },
|
|
||||||
#if WITH_HISTORY
|
|
||||||
{ "fc", histcmd },
|
|
||||||
{ "inputrc", inputrc },
|
|
||||||
#endif
|
|
||||||
{ "fg", fgcmd },
|
|
||||||
{ "getopts", getoptscmd },
|
|
||||||
{ "hash", hashcmd },
|
|
||||||
{ "jobid", jobidcmd },
|
|
||||||
{ "jobs", jobscmd },
|
|
||||||
{ "local", localcmd },
|
|
||||||
#ifndef SMALL
|
|
||||||
#endif
|
|
||||||
{ "pwd", pwdcmd },
|
|
||||||
{ "read", readcmd },
|
|
||||||
{ "setvar", setvarcmd },
|
|
||||||
{ "true", truecmd },
|
|
||||||
{ "type", typecmd },
|
|
||||||
{ "umask", umaskcmd },
|
|
||||||
{ "unalias", unaliascmd },
|
|
||||||
{ "wait", waitcmd },
|
|
||||||
{ "alias", aliascmd },
|
|
||||||
{ "ulimit", ulimitcmd },
|
|
||||||
{ "wordexp", wordexpcmd },
|
|
||||||
{ 0, 0 },
|
|
||||||
};
|
|
||||||
|
|
||||||
const struct builtincmd splbltincmd[] = {
|
|
||||||
{ "break", breakcmd },
|
|
||||||
{ "continue", breakcmd },
|
|
||||||
{ ".", dotcmd },
|
|
||||||
{ "eval", evalcmd },
|
|
||||||
{ "exec", execcmd },
|
|
||||||
{ "exit", exitcmd },
|
|
||||||
{ "export", exportcmd },
|
|
||||||
{ "readonly", exportcmd },
|
|
||||||
{ "return", returncmd },
|
|
||||||
{ "set", setcmd },
|
|
||||||
{ "shift", shiftcmd },
|
|
||||||
{ "times", timescmd },
|
|
||||||
{ "trap", trapcmd },
|
|
||||||
{ ":", truecmd },
|
|
||||||
{ "unset", unsetcmd },
|
|
||||||
{ 0, 0 },
|
|
||||||
};
|
|
||||||
|
|
@ -1,94 +0,0 @@
|
||||||
#!/bin/sh -
|
|
||||||
# $NetBSD: builtins.def,v 1.21 2004/07/13 15:05:59 seb Exp $
|
|
||||||
#
|
|
||||||
# Copyright (c) 1991, 1993
|
|
||||||
# The Regents of the University of California. All rights reserved.
|
|
||||||
#
|
|
||||||
# This code is derived from software contributed to Berkeley by
|
|
||||||
# Kenneth Almquist.
|
|
||||||
#
|
|
||||||
# Redistribution and use in source and binary forms, with or without
|
|
||||||
# modification, are permitted provided that the following conditions
|
|
||||||
# are met:
|
|
||||||
# 1. Redistributions of source code must retain the above copyright
|
|
||||||
# notice, this list of conditions and the following disclaimer.
|
|
||||||
# 2. Redistributions in binary form must reproduce the above copyright
|
|
||||||
# notice, this list of conditions and the following disclaimer in the
|
|
||||||
# documentation and/or other materials provided with the distribution.
|
|
||||||
# 3. Neither the name of the University nor the names of its contributors
|
|
||||||
# may be used to endorse or promote products derived from this software
|
|
||||||
# without specific prior written permission.
|
|
||||||
#
|
|
||||||
# THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
|
||||||
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
||||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
||||||
# ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
|
||||||
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
||||||
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
|
||||||
# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
|
||||||
# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
||||||
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
|
||||||
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
|
||||||
# SUCH DAMAGE.
|
|
||||||
#
|
|
||||||
# @(#)builtins.def 8.4 (Berkeley) 5/4/95
|
|
||||||
|
|
||||||
#
|
|
||||||
# This file lists all the builtin commands. The first column is the name
|
|
||||||
# of a C routine.
|
|
||||||
# The -j flag specifies that this command is to be excluded from systems
|
|
||||||
# without job control.
|
|
||||||
# The -h flag specifies that this command is to be excluded from systems
|
|
||||||
# based on the SMALL compile-time symbol.
|
|
||||||
# The -s flag specifies that this is a posix 'special builtin' command.
|
|
||||||
# The -u flag specifies that this is a posix 'standard utility'.
|
|
||||||
# The rest of the line specifies the command name or names used to run
|
|
||||||
# the command.
|
|
||||||
|
|
||||||
bltincmd -u command
|
|
||||||
bgcmd -j -u bg
|
|
||||||
breakcmd -s break -s continue
|
|
||||||
cdcmd -u cd chdir
|
|
||||||
dotcmd -s .
|
|
||||||
echocmd echo
|
|
||||||
evalcmd -s eval
|
|
||||||
execcmd -s exec
|
|
||||||
exitcmd -s exit
|
|
||||||
expcmd exp let
|
|
||||||
exportcmd -s export -s readonly
|
|
||||||
falsecmd -u false
|
|
||||||
#if WITH_HISTORY
|
|
||||||
histcmd -h -u fc
|
|
||||||
inputrc inputrc
|
|
||||||
#endif
|
|
||||||
fgcmd -j -u fg
|
|
||||||
getoptscmd -u getopts
|
|
||||||
hashcmd hash
|
|
||||||
jobidcmd jobid
|
|
||||||
jobscmd -u jobs
|
|
||||||
localcmd local
|
|
||||||
#ifndef SMALL
|
|
||||||
##printfcmd printf
|
|
||||||
#endif
|
|
||||||
pwdcmd -u pwd
|
|
||||||
readcmd -u read
|
|
||||||
returncmd -s return
|
|
||||||
setcmd -s set
|
|
||||||
setvarcmd setvar
|
|
||||||
shiftcmd -s shift
|
|
||||||
timescmd -s times
|
|
||||||
trapcmd -s trap
|
|
||||||
truecmd -s : -u true
|
|
||||||
typecmd type
|
|
||||||
umaskcmd -u umask
|
|
||||||
unaliascmd -u unalias
|
|
||||||
unsetcmd -s unset
|
|
||||||
waitcmd -u wait
|
|
||||||
aliascmd -u alias
|
|
||||||
ulimitcmd ulimit
|
|
||||||
##testcmd test [
|
|
||||||
##killcmd -u kill # mandated by posix for 'kill %job'
|
|
||||||
wordexpcmd wordexp
|
|
||||||
#newgrp -u newgrp # optional command in posix
|
|
||||||
|
|
||||||
#exprcmd expr
|
|
||||||
|
|
@ -1,56 +0,0 @@
|
||||||
/*
|
|
||||||
* This file was generated by the mkbuiltins program.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <sys/cdefs.h>
|
|
||||||
|
|
||||||
struct builtincmd {
|
|
||||||
const char *name;
|
|
||||||
int (*builtin)(int, char **);
|
|
||||||
};
|
|
||||||
|
|
||||||
extern const struct builtincmd builtincmd[];
|
|
||||||
extern const struct builtincmd splbltincmd[];
|
|
||||||
|
|
||||||
|
|
||||||
int bltincmd(int, char **);
|
|
||||||
int bgcmd(int, char **);
|
|
||||||
int breakcmd(int, char **);
|
|
||||||
int cdcmd(int, char **);
|
|
||||||
int dotcmd(int, char **);
|
|
||||||
int echocmd(int, char **);
|
|
||||||
int evalcmd(int, char **);
|
|
||||||
int execcmd(int, char **);
|
|
||||||
int exitcmd(int, char **);
|
|
||||||
int expcmd(int, char **);
|
|
||||||
int exportcmd(int, char **);
|
|
||||||
int falsecmd(int, char **);
|
|
||||||
#if WITH_HISTORY
|
|
||||||
int histcmd(int, char **);
|
|
||||||
int inputrc(int, char **);
|
|
||||||
#endif
|
|
||||||
int fgcmd(int, char **);
|
|
||||||
int getoptscmd(int, char **);
|
|
||||||
int hashcmd(int, char **);
|
|
||||||
int jobidcmd(int, char **);
|
|
||||||
int jobscmd(int, char **);
|
|
||||||
int localcmd(int, char **);
|
|
||||||
#ifndef SMALL
|
|
||||||
#endif
|
|
||||||
int pwdcmd(int, char **);
|
|
||||||
int readcmd(int, char **);
|
|
||||||
int returncmd(int, char **);
|
|
||||||
int setcmd(int, char **);
|
|
||||||
int setvarcmd(int, char **);
|
|
||||||
int shiftcmd(int, char **);
|
|
||||||
int timescmd(int, char **);
|
|
||||||
int trapcmd(int, char **);
|
|
||||||
int truecmd(int, char **);
|
|
||||||
int typecmd(int, char **);
|
|
||||||
int umaskcmd(int, char **);
|
|
||||||
int unaliascmd(int, char **);
|
|
||||||
int unsetcmd(int, char **);
|
|
||||||
int waitcmd(int, char **);
|
|
||||||
int aliascmd(int, char **);
|
|
||||||
int ulimitcmd(int, char **);
|
|
||||||
int wordexpcmd(int, char **);
|
|
||||||
446
sh/cd.c
446
sh/cd.c
|
|
@ -1,446 +0,0 @@
|
||||||
/* $NetBSD: cd.c,v 1.34 2003/11/14 20:00:28 dsl Exp $ */
|
|
||||||
|
|
||||||
/*-
|
|
||||||
* Copyright (c) 1991, 1993
|
|
||||||
* The Regents of the University of California. All rights reserved.
|
|
||||||
*
|
|
||||||
* This code is derived from software contributed to Berkeley by
|
|
||||||
* Kenneth Almquist.
|
|
||||||
*
|
|
||||||
* Redistribution and use in source and binary forms, with or without
|
|
||||||
* modification, are permitted provided that the following conditions
|
|
||||||
* are met:
|
|
||||||
* 1. Redistributions of source code must retain the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer.
|
|
||||||
* 2. Redistributions in binary form must reproduce the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer in the
|
|
||||||
* documentation and/or other materials provided with the distribution.
|
|
||||||
* 3. Neither the name of the University nor the names of its contributors
|
|
||||||
* may be used to endorse or promote products derived from this software
|
|
||||||
* without specific prior written permission.
|
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
|
||||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
||||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
||||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
|
||||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
||||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
|
||||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
|
||||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
||||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
|
||||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
|
||||||
* SUCH DAMAGE.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <sys/cdefs.h>
|
|
||||||
#ifndef lint
|
|
||||||
#if 0
|
|
||||||
static char sccsid[] = "@(#)cd.c 8.2 (Berkeley) 5/4/95";
|
|
||||||
#else
|
|
||||||
__RCSID("$NetBSD: cd.c,v 1.34 2003/11/14 20:00:28 dsl Exp $");
|
|
||||||
#endif
|
|
||||||
#endif /* not lint */
|
|
||||||
|
|
||||||
#include <sys/types.h>
|
|
||||||
#include <sys/stat.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <errno.h>
|
|
||||||
|
|
||||||
/*
|
|
||||||
* The cd and pwd commands.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "shell.h"
|
|
||||||
#include "var.h"
|
|
||||||
#include "nodes.h" /* for jobs.h */
|
|
||||||
#include "jobs.h"
|
|
||||||
#include "options.h"
|
|
||||||
#include "output.h"
|
|
||||||
#include "memalloc.h"
|
|
||||||
#include "error.h"
|
|
||||||
#include "exec.h"
|
|
||||||
#include "redir.h"
|
|
||||||
#include "mystring.h"
|
|
||||||
#include "show.h"
|
|
||||||
#include "cd.h"
|
|
||||||
|
|
||||||
STATIC int docd(char *, int);
|
|
||||||
STATIC char *getcomponent(void);
|
|
||||||
STATIC void updatepwd(char *);
|
|
||||||
STATIC void find_curdir(int noerror);
|
|
||||||
|
|
||||||
char *curdir = NULL; /* current working directory */
|
|
||||||
char *prevdir; /* previous working directory */
|
|
||||||
STATIC char *cdcomppath;
|
|
||||||
|
|
||||||
int
|
|
||||||
cdcmd(int argc, char **argv)
|
|
||||||
{
|
|
||||||
const char *dest;
|
|
||||||
const char *path;
|
|
||||||
char *p, *d;
|
|
||||||
struct stat statb;
|
|
||||||
int print = cdprint; /* set -cdprint to enable */
|
|
||||||
|
|
||||||
nextopt(nullstr);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Try (quite hard) to have 'curdir' defined, nothing has set
|
|
||||||
* it on entry to the shell, but we want 'cd fred; cd -' to work.
|
|
||||||
*/
|
|
||||||
getpwd(1);
|
|
||||||
dest = *argptr;
|
|
||||||
if (dest == NULL) {
|
|
||||||
dest = bltinlookup("HOME", 1);
|
|
||||||
if (dest == NULL)
|
|
||||||
error("HOME not set");
|
|
||||||
} else {
|
|
||||||
if (argptr[1]) {
|
|
||||||
/* Do 'ksh' style substitution */
|
|
||||||
if (!curdir)
|
|
||||||
error("PWD not set");
|
|
||||||
p = strstr(curdir, dest);
|
|
||||||
if (!p)
|
|
||||||
error("bad substitution");
|
|
||||||
d = stalloc(strlen(curdir) + strlen(argptr[1]) + 1);
|
|
||||||
memcpy(d, curdir, p - curdir);
|
|
||||||
strcpy(d + (p - curdir), argptr[1]);
|
|
||||||
strcat(d, p + strlen(dest));
|
|
||||||
dest = d;
|
|
||||||
print = 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (dest[0] == '-' && dest[1] == '\0') {
|
|
||||||
dest = prevdir ? prevdir : curdir;
|
|
||||||
print = 1;
|
|
||||||
}
|
|
||||||
if (*dest == '\0')
|
|
||||||
dest = ".";
|
|
||||||
if (*dest == '/' || (path = bltinlookup("CDPATH", 1)) == NULL)
|
|
||||||
path = nullstr;
|
|
||||||
while ((p = padvance(&path, dest)) != NULL) {
|
|
||||||
if (stat(p, &statb) >= 0 && S_ISDIR(statb.st_mode)) {
|
|
||||||
if (!print) {
|
|
||||||
/*
|
|
||||||
* XXX - rethink
|
|
||||||
*/
|
|
||||||
if (p[0] == '.' && p[1] == '/' && p[2] != '\0')
|
|
||||||
p += 2;
|
|
||||||
print = strcmp(p, dest);
|
|
||||||
}
|
|
||||||
if (docd(p, print) >= 0)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
error("can't cd to %s", dest);
|
|
||||||
/* NOTREACHED */
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Actually do the chdir. In an interactive shell, print the
|
|
||||||
* directory name if "print" is nonzero.
|
|
||||||
*/
|
|
||||||
|
|
||||||
STATIC int
|
|
||||||
docd(char *dest, int print)
|
|
||||||
{
|
|
||||||
char *p;
|
|
||||||
char *q;
|
|
||||||
char *component;
|
|
||||||
struct stat statb;
|
|
||||||
int first;
|
|
||||||
int badstat;
|
|
||||||
|
|
||||||
TRACE(("docd(\"%s\", %d) called\n", dest, print));
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Check each component of the path. If we find a symlink or
|
|
||||||
* something we can't stat, clear curdir to force a getcwd()
|
|
||||||
* next time we get the value of the current directory.
|
|
||||||
*/
|
|
||||||
badstat = 0;
|
|
||||||
cdcomppath = stalloc(strlen(dest) + 1);
|
|
||||||
scopy(dest, cdcomppath);
|
|
||||||
STARTSTACKSTR(p);
|
|
||||||
if (*dest == '/') {
|
|
||||||
STPUTC('/', p);
|
|
||||||
cdcomppath++;
|
|
||||||
}
|
|
||||||
first = 1;
|
|
||||||
while ((q = getcomponent()) != NULL) {
|
|
||||||
if (q[0] == '\0' || (q[0] == '.' && q[1] == '\0'))
|
|
||||||
continue;
|
|
||||||
if (! first)
|
|
||||||
STPUTC('/', p);
|
|
||||||
first = 0;
|
|
||||||
component = q;
|
|
||||||
while (*q)
|
|
||||||
STPUTC(*q++, p);
|
|
||||||
if (equal(component, ".."))
|
|
||||||
continue;
|
|
||||||
STACKSTRNUL(p);
|
|
||||||
if ((lstat(stackblock(), &statb) < 0)
|
|
||||||
|| (S_ISLNK(statb.st_mode))) {
|
|
||||||
/* print = 1; */
|
|
||||||
badstat = 1;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
INTOFF;
|
|
||||||
if (chdir(dest) < 0) {
|
|
||||||
INTON;
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
updatepwd(badstat ? NULL : dest);
|
|
||||||
INTON;
|
|
||||||
if (print && iflag && curdir)
|
|
||||||
out1fmt("%s\n", curdir);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Get the next component of the path name pointed to by cdcomppath.
|
|
||||||
* This routine overwrites the string pointed to by cdcomppath.
|
|
||||||
*/
|
|
||||||
|
|
||||||
STATIC char *
|
|
||||||
getcomponent()
|
|
||||||
{
|
|
||||||
char *p;
|
|
||||||
char *start;
|
|
||||||
|
|
||||||
if ((p = cdcomppath) == NULL)
|
|
||||||
return NULL;
|
|
||||||
start = cdcomppath;
|
|
||||||
while (*p != '/' && *p != '\0')
|
|
||||||
p++;
|
|
||||||
if (*p == '\0') {
|
|
||||||
cdcomppath = NULL;
|
|
||||||
} else {
|
|
||||||
*p++ = '\0';
|
|
||||||
cdcomppath = p;
|
|
||||||
}
|
|
||||||
return start;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Update curdir (the name of the current directory) in response to a
|
|
||||||
* cd command. We also call hashcd to let the routines in exec.c know
|
|
||||||
* that the current directory has changed.
|
|
||||||
*/
|
|
||||||
|
|
||||||
STATIC void
|
|
||||||
updatepwd(char *dir)
|
|
||||||
{
|
|
||||||
char *new;
|
|
||||||
char *p;
|
|
||||||
|
|
||||||
hashcd(); /* update command hash table */
|
|
||||||
|
|
||||||
/*
|
|
||||||
* If our argument is NULL, we don't know the current directory
|
|
||||||
* any more because we traversed a symbolic link or something
|
|
||||||
* we couldn't stat().
|
|
||||||
*/
|
|
||||||
if (dir == NULL || curdir == NULL) {
|
|
||||||
if (prevdir)
|
|
||||||
ckfree(prevdir);
|
|
||||||
INTOFF;
|
|
||||||
prevdir = curdir;
|
|
||||||
curdir = NULL;
|
|
||||||
getpwd(1);
|
|
||||||
INTON;
|
|
||||||
if (curdir)
|
|
||||||
setvar("PWD", curdir, VEXPORT);
|
|
||||||
else
|
|
||||||
unsetvar("PWD", 0);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
cdcomppath = stalloc(strlen(dir) + 1);
|
|
||||||
scopy(dir, cdcomppath);
|
|
||||||
STARTSTACKSTR(new);
|
|
||||||
if (*dir != '/') {
|
|
||||||
p = curdir;
|
|
||||||
while (*p)
|
|
||||||
STPUTC(*p++, new);
|
|
||||||
if (p[-1] == '/')
|
|
||||||
STUNPUTC(new);
|
|
||||||
}
|
|
||||||
while ((p = getcomponent()) != NULL) {
|
|
||||||
if (equal(p, "..")) {
|
|
||||||
while (new > stackblock() && (STUNPUTC(new), *new) != '/');
|
|
||||||
} else if (*p != '\0' && ! equal(p, ".")) {
|
|
||||||
STPUTC('/', new);
|
|
||||||
while (*p)
|
|
||||||
STPUTC(*p++, new);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (new == stackblock())
|
|
||||||
STPUTC('/', new);
|
|
||||||
STACKSTRNUL(new);
|
|
||||||
INTOFF;
|
|
||||||
if (prevdir)
|
|
||||||
ckfree(prevdir);
|
|
||||||
prevdir = curdir;
|
|
||||||
curdir = savestr(stackblock());
|
|
||||||
setvar("PWD", curdir, VEXPORT);
|
|
||||||
INTON;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Posix says the default should be 'pwd -L' (as below), however
|
|
||||||
* the 'cd' command (above) does something much nearer to the
|
|
||||||
* posix 'cd -P' (not the posix default of 'cd -L').
|
|
||||||
* If 'cd' is changed to support -P/L then the default here
|
|
||||||
* needs to be revisited if the historic behaviour is to be kept.
|
|
||||||
*/
|
|
||||||
|
|
||||||
int
|
|
||||||
pwdcmd(int argc, char **argv)
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
char opt = 'L';
|
|
||||||
|
|
||||||
while ((i = nextopt("LP")) != '\0')
|
|
||||||
opt = i;
|
|
||||||
if (*argptr)
|
|
||||||
error("unexpected argument");
|
|
||||||
|
|
||||||
if (opt == 'L')
|
|
||||||
getpwd(0);
|
|
||||||
else
|
|
||||||
find_curdir(0);
|
|
||||||
|
|
||||||
setvar("PWD", curdir, VEXPORT);
|
|
||||||
out1str(curdir);
|
|
||||||
out1c('\n');
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#define MAXPWD 256
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Find out what the current directory is. If we already know the current
|
|
||||||
* directory, this routine returns immediately.
|
|
||||||
*/
|
|
||||||
void
|
|
||||||
getpwd(int noerror)
|
|
||||||
{
|
|
||||||
char *pwd;
|
|
||||||
struct stat stdot, stpwd;
|
|
||||||
static int first = 1;
|
|
||||||
|
|
||||||
if (curdir)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (first) {
|
|
||||||
first = 0;
|
|
||||||
pwd = getenv("PWD");
|
|
||||||
if (pwd && *pwd == '/' && stat(".", &stdot) != -1 &&
|
|
||||||
stat(pwd, &stpwd) != -1 &&
|
|
||||||
stdot.st_dev == stpwd.st_dev &&
|
|
||||||
stdot.st_ino == stpwd.st_ino) {
|
|
||||||
curdir = savestr(pwd);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
find_curdir(noerror);
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
STATIC void
|
|
||||||
find_curdir(int noerror)
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
char *pwd;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Things are a bit complicated here; we could have just used
|
|
||||||
* getcwd, but traditionally getcwd is implemented using popen
|
|
||||||
* to /bin/pwd. This creates a problem for us, since we cannot
|
|
||||||
* keep track of the job if it is being ran behind our backs.
|
|
||||||
* So we re-implement getcwd(), and we suppress interrupts
|
|
||||||
* throughout the process. This is not completely safe, since
|
|
||||||
* the user can still break out of it by killing the pwd program.
|
|
||||||
* We still try to use getcwd for systems that we know have a
|
|
||||||
* c implementation of getcwd, that does not open a pipe to
|
|
||||||
* /bin/pwd.
|
|
||||||
*/
|
|
||||||
#if defined(__NetBSD__) || defined(__SVR4) || defined(__linux__)
|
|
||||||
for (i = MAXPWD;; i *= 2) {
|
|
||||||
pwd = stalloc(i);
|
|
||||||
if (getcwd(pwd, i) != NULL) {
|
|
||||||
curdir = savestr(pwd);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
stunalloc(pwd);
|
|
||||||
if (errno == ERANGE)
|
|
||||||
continue;
|
|
||||||
if (!noerror)
|
|
||||||
error("getcwd() failed: %s", strerror(errno));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
{
|
|
||||||
char *p;
|
|
||||||
int status;
|
|
||||||
struct job *jp;
|
|
||||||
int pip[2];
|
|
||||||
|
|
||||||
pwd = stalloc(MAXPWD);
|
|
||||||
INTOFF;
|
|
||||||
if (pipe(pip) < 0)
|
|
||||||
error("Pipe call failed");
|
|
||||||
jp = makejob((union node *)NULL, 1);
|
|
||||||
if (forkshell(jp, (union node *)NULL, FORK_NOJOB) == 0) {
|
|
||||||
(void) close(pip[0]);
|
|
||||||
if (pip[1] != 1) {
|
|
||||||
close(1);
|
|
||||||
copyfd(pip[1], 1);
|
|
||||||
close(pip[1]);
|
|
||||||
}
|
|
||||||
(void) execl("/bin/pwd", "pwd", (char *)0);
|
|
||||||
sh_warn("Cannot exec /bin/pwd");
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
(void) close(pip[1]);
|
|
||||||
pip[1] = -1;
|
|
||||||
p = pwd;
|
|
||||||
while ((i = read(pip[0], p, pwd + MAXPWD - p)) > 0
|
|
||||||
|| (i == -1 && errno == EINTR)) {
|
|
||||||
if (i > 0)
|
|
||||||
p += i;
|
|
||||||
}
|
|
||||||
(void) close(pip[0]);
|
|
||||||
pip[0] = -1;
|
|
||||||
status = waitforjob(jp);
|
|
||||||
if (status != 0)
|
|
||||||
error((char *)0);
|
|
||||||
if (i < 0 || p == pwd || p[-1] != '\n') {
|
|
||||||
if (noerror) {
|
|
||||||
INTON;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
error("pwd command failed");
|
|
||||||
}
|
|
||||||
p[-1] = '\0';
|
|
||||||
INTON;
|
|
||||||
curdir = savestr(pwd);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
35
sh/cd.h
35
sh/cd.h
|
|
@ -1,35 +0,0 @@
|
||||||
/* $NetBSD: cd.h,v 1.4 2003/08/07 09:05:30 agc Exp $ */
|
|
||||||
|
|
||||||
/*-
|
|
||||||
* Copyright (c) 1995
|
|
||||||
* The Regents of the University of California. All rights reserved.
|
|
||||||
*
|
|
||||||
* Redistribution and use in source and binary forms, with or without
|
|
||||||
* modification, are permitted provided that the following conditions
|
|
||||||
* are met:
|
|
||||||
* 1. Redistributions of source code must retain the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer.
|
|
||||||
* 2. Redistributions in binary form must reproduce the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer in the
|
|
||||||
* documentation and/or other materials provided with the distribution.
|
|
||||||
* 3. Neither the name of the University nor the names of its contributors
|
|
||||||
* may be used to endorse or promote products derived from this software
|
|
||||||
* without specific prior written permission.
|
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
|
||||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
||||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
||||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
|
||||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
||||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
|
||||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
|
||||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
||||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
|
||||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
|
||||||
* SUCH DAMAGE.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
void getpwd(int);
|
|
||||||
int cdcmd(int, char **);
|
|
||||||
int pwdcmd(int, char **);
|
|
||||||
366
sh/error.c
366
sh/error.c
|
|
@ -1,366 +0,0 @@
|
||||||
/* $NetBSD: error.c,v 1.31 2003/08/07 09:05:30 agc Exp $ */
|
|
||||||
|
|
||||||
/*-
|
|
||||||
* Copyright (c) 1991, 1993
|
|
||||||
* The Regents of the University of California. All rights reserved.
|
|
||||||
*
|
|
||||||
* This code is derived from software contributed to Berkeley by
|
|
||||||
* Kenneth Almquist.
|
|
||||||
*
|
|
||||||
* Redistribution and use in source and binary forms, with or without
|
|
||||||
* modification, are permitted provided that the following conditions
|
|
||||||
* are met:
|
|
||||||
* 1. Redistributions of source code must retain the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer.
|
|
||||||
* 2. Redistributions in binary form must reproduce the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer in the
|
|
||||||
* documentation and/or other materials provided with the distribution.
|
|
||||||
* 3. Neither the name of the University nor the names of its contributors
|
|
||||||
* may be used to endorse or promote products derived from this software
|
|
||||||
* without specific prior written permission.
|
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
|
||||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
||||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
||||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
|
||||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
||||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
|
||||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
|
||||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
||||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
|
||||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
|
||||||
* SUCH DAMAGE.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <sys/cdefs.h>
|
|
||||||
#ifndef lint
|
|
||||||
#if 0
|
|
||||||
static char sccsid[] = "@(#)error.c 8.2 (Berkeley) 5/4/95";
|
|
||||||
#else
|
|
||||||
__RCSID("$NetBSD: error.c,v 1.31 2003/08/07 09:05:30 agc Exp $");
|
|
||||||
#endif
|
|
||||||
#endif /* not lint */
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Errors and exceptions.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <signal.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <errno.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
#include "shell.h"
|
|
||||||
#include "main.h"
|
|
||||||
#include "options.h"
|
|
||||||
#include "output.h"
|
|
||||||
#include "error.h"
|
|
||||||
#include "show.h"
|
|
||||||
|
|
||||||
#define signal bsd_signal
|
|
||||||
/*
|
|
||||||
* Code to handle exceptions in C.
|
|
||||||
*/
|
|
||||||
|
|
||||||
struct jmploc *handler;
|
|
||||||
int exception;
|
|
||||||
volatile int suppressint;
|
|
||||||
volatile int intpending;
|
|
||||||
char *commandname;
|
|
||||||
|
|
||||||
|
|
||||||
static void exverror(int, const char *, va_list)
|
|
||||||
__attribute__((__noreturn__));
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Called to raise an exception. Since C doesn't include exceptions, we
|
|
||||||
* just do a longjmp to the exception handler. The type of exception is
|
|
||||||
* stored in the global variable "exception".
|
|
||||||
*/
|
|
||||||
|
|
||||||
void
|
|
||||||
exraise(int e)
|
|
||||||
{
|
|
||||||
if (handler == NULL)
|
|
||||||
abort();
|
|
||||||
exception = e;
|
|
||||||
longjmp(handler->loc, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Called from trap.c when a SIGINT is received. (If the user specifies
|
|
||||||
* that SIGINT is to be trapped or ignored using the trap builtin, then
|
|
||||||
* this routine is not called.) Suppressint is nonzero when interrupts
|
|
||||||
* are held using the INTOFF macro. The call to _exit is necessary because
|
|
||||||
* there is a short period after a fork before the signal handlers are
|
|
||||||
* set to the appropriate value for the child. (The test for iflag is
|
|
||||||
* just defensive programming.)
|
|
||||||
*/
|
|
||||||
|
|
||||||
void
|
|
||||||
onint(void)
|
|
||||||
{
|
|
||||||
sigset_t nsigset;
|
|
||||||
|
|
||||||
if (suppressint) {
|
|
||||||
intpending = 1;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
intpending = 0;
|
|
||||||
sigemptyset(&nsigset);
|
|
||||||
sigprocmask(SIG_SETMASK, &nsigset, NULL);
|
|
||||||
if (rootshell && iflag)
|
|
||||||
exraise(EXINT);
|
|
||||||
else {
|
|
||||||
signal(SIGINT, SIG_DFL);
|
|
||||||
raise(SIGINT);
|
|
||||||
}
|
|
||||||
/* NOTREACHED */
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
exvwarning(int sv_errno, const char *msg, va_list ap)
|
|
||||||
{
|
|
||||||
/* Partially emulate line buffered output so that:
|
|
||||||
* printf '%d\n' 1 a 2
|
|
||||||
* and
|
|
||||||
* printf '%d %d %d\n' 1 a 2
|
|
||||||
* both generate sensible text when stdout and stderr are merged.
|
|
||||||
*/
|
|
||||||
if (output.nextc != output.buf && output.nextc[-1] == '\n')
|
|
||||||
flushout(&output);
|
|
||||||
if (commandname)
|
|
||||||
outfmt(&errout, "%s: ", commandname);
|
|
||||||
if (msg != NULL) {
|
|
||||||
doformat(&errout, msg, ap);
|
|
||||||
if (sv_errno >= 0)
|
|
||||||
outfmt(&errout, ": ");
|
|
||||||
}
|
|
||||||
if (sv_errno >= 0)
|
|
||||||
outfmt(&errout, "%s", strerror(sv_errno));
|
|
||||||
out2c('\n');
|
|
||||||
flushout(&errout);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Exverror is called to raise the error exception. If the second argument
|
|
||||||
* is not NULL then error prints an error message using printf style
|
|
||||||
* formatting. It then raises the error exception.
|
|
||||||
*/
|
|
||||||
static void
|
|
||||||
exverror(int cond, const char *msg, va_list ap)
|
|
||||||
{
|
|
||||||
CLEAR_PENDING_INT;
|
|
||||||
INTOFF;
|
|
||||||
|
|
||||||
#ifdef DEBUG
|
|
||||||
if (msg) {
|
|
||||||
TRACE(("exverror(%d, \"", cond));
|
|
||||||
TRACEV((msg, ap));
|
|
||||||
TRACE(("\") pid=%d\n", getpid()));
|
|
||||||
} else
|
|
||||||
TRACE(("exverror(%d, NULL) pid=%d\n", cond, getpid()));
|
|
||||||
#endif
|
|
||||||
if (msg)
|
|
||||||
exvwarning(-1, msg, ap);
|
|
||||||
|
|
||||||
flushall();
|
|
||||||
exraise(cond);
|
|
||||||
/* NOTREACHED */
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
error(const char *msg, ...)
|
|
||||||
{
|
|
||||||
va_list ap;
|
|
||||||
|
|
||||||
va_start(ap, msg);
|
|
||||||
exverror(EXERROR, msg, ap);
|
|
||||||
/* NOTREACHED */
|
|
||||||
va_end(ap);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
exerror(int cond, const char *msg, ...)
|
|
||||||
{
|
|
||||||
va_list ap;
|
|
||||||
|
|
||||||
va_start(ap, msg);
|
|
||||||
exverror(cond, msg, ap);
|
|
||||||
/* NOTREACHED */
|
|
||||||
va_end(ap);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* error/warning routines for external builtins
|
|
||||||
*/
|
|
||||||
|
|
||||||
void
|
|
||||||
sh_exit(int rval)
|
|
||||||
{
|
|
||||||
exerrno = rval & 255;
|
|
||||||
exraise(EXEXEC);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
sh_err(int status, const char *fmt, ...)
|
|
||||||
{
|
|
||||||
va_list ap;
|
|
||||||
|
|
||||||
va_start(ap, fmt);
|
|
||||||
exvwarning(errno, fmt, ap);
|
|
||||||
va_end(ap);
|
|
||||||
sh_exit(status);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
sh_verr(int status, const char *fmt, va_list ap)
|
|
||||||
{
|
|
||||||
exvwarning(errno, fmt, ap);
|
|
||||||
sh_exit(status);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
sh_errx(int status, const char *fmt, ...)
|
|
||||||
{
|
|
||||||
va_list ap;
|
|
||||||
|
|
||||||
va_start(ap, fmt);
|
|
||||||
exvwarning(-1, fmt, ap);
|
|
||||||
va_end(ap);
|
|
||||||
sh_exit(status);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
sh_verrx(int status, const char *fmt, va_list ap)
|
|
||||||
{
|
|
||||||
exvwarning(-1, fmt, ap);
|
|
||||||
sh_exit(status);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
sh_warn(const char *fmt, ...)
|
|
||||||
{
|
|
||||||
va_list ap;
|
|
||||||
|
|
||||||
va_start(ap, fmt);
|
|
||||||
exvwarning(errno, fmt, ap);
|
|
||||||
va_end(ap);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
sh_vwarn(const char *fmt, va_list ap)
|
|
||||||
{
|
|
||||||
exvwarning(errno, fmt, ap);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
sh_warnx(const char *fmt, ...)
|
|
||||||
{
|
|
||||||
va_list ap;
|
|
||||||
|
|
||||||
va_start(ap, fmt);
|
|
||||||
exvwarning(-1, fmt, ap);
|
|
||||||
va_end(ap);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
sh_vwarnx(const char *fmt, va_list ap)
|
|
||||||
{
|
|
||||||
exvwarning(-1, fmt, ap);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Table of error messages.
|
|
||||||
*/
|
|
||||||
|
|
||||||
struct errname {
|
|
||||||
short errcode; /* error number */
|
|
||||||
short action; /* operation which encountered the error */
|
|
||||||
const char *msg; /* text describing the error */
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
#define ALL (E_OPEN|E_CREAT|E_EXEC)
|
|
||||||
|
|
||||||
STATIC const struct errname errormsg[] = {
|
|
||||||
{ EINTR, ALL, "interrupted" },
|
|
||||||
{ EACCES, ALL, "permission denied" },
|
|
||||||
{ EIO, ALL, "I/O error" },
|
|
||||||
{ EEXIST, ALL, "file exists" },
|
|
||||||
{ ENOENT, E_OPEN, "no such file" },
|
|
||||||
{ ENOENT, E_CREAT,"directory nonexistent" },
|
|
||||||
{ ENOENT, E_EXEC, "not found" },
|
|
||||||
{ ENOTDIR, E_OPEN, "no such file" },
|
|
||||||
{ ENOTDIR, E_CREAT,"directory nonexistent" },
|
|
||||||
{ ENOTDIR, E_EXEC, "not found" },
|
|
||||||
{ EISDIR, ALL, "is a directory" },
|
|
||||||
#ifdef EMFILE
|
|
||||||
{ EMFILE, ALL, "too many open files" },
|
|
||||||
#endif
|
|
||||||
{ ENFILE, ALL, "file table overflow" },
|
|
||||||
{ ENOSPC, ALL, "file system full" },
|
|
||||||
#ifdef EDQUOT
|
|
||||||
{ EDQUOT, ALL, "disk quota exceeded" },
|
|
||||||
#endif
|
|
||||||
#ifdef ENOSR
|
|
||||||
{ ENOSR, ALL, "no streams resources" },
|
|
||||||
#endif
|
|
||||||
{ ENXIO, ALL, "no such device or address" },
|
|
||||||
{ EROFS, ALL, "read-only file system" },
|
|
||||||
{ ETXTBSY, ALL, "text busy" },
|
|
||||||
#ifdef EAGAIN
|
|
||||||
{ EAGAIN, E_EXEC, "not enough memory" },
|
|
||||||
#endif
|
|
||||||
{ ENOMEM, ALL, "not enough memory" },
|
|
||||||
#ifdef ENOLINK
|
|
||||||
{ ENOLINK, ALL, "remote access failed" },
|
|
||||||
#endif
|
|
||||||
#ifdef EMULTIHOP
|
|
||||||
{ EMULTIHOP, ALL, "remote access failed" },
|
|
||||||
#endif
|
|
||||||
#ifdef ECOMM
|
|
||||||
{ ECOMM, ALL, "remote access failed" },
|
|
||||||
#endif
|
|
||||||
#ifdef ESTALE
|
|
||||||
{ ESTALE, ALL, "remote access failed" },
|
|
||||||
#endif
|
|
||||||
#ifdef ETIMEDOUT
|
|
||||||
{ ETIMEDOUT, ALL, "remote access failed" },
|
|
||||||
#endif
|
|
||||||
#ifdef ELOOP
|
|
||||||
{ ELOOP, ALL, "symbolic link loop" },
|
|
||||||
#endif
|
|
||||||
{ E2BIG, E_EXEC, "argument list too long" },
|
|
||||||
#ifdef ELIBACC
|
|
||||||
{ ELIBACC, E_EXEC, "shared library missing" },
|
|
||||||
#endif
|
|
||||||
{ 0, 0, NULL },
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Return a string describing an error. The returned string may be a
|
|
||||||
* pointer to a static buffer that will be overwritten on the next call.
|
|
||||||
* Action describes the operation that got the error.
|
|
||||||
*/
|
|
||||||
|
|
||||||
const char *
|
|
||||||
errmsg(int e, int action)
|
|
||||||
{
|
|
||||||
struct errname const *ep;
|
|
||||||
static char buf[12];
|
|
||||||
|
|
||||||
for (ep = errormsg ; ep->errcode ; ep++) {
|
|
||||||
if (ep->errcode == e && (ep->action & action) != 0)
|
|
||||||
return ep->msg;
|
|
||||||
}
|
|
||||||
fmtstr(buf, sizeof buf, "error %d", e);
|
|
||||||
return buf;
|
|
||||||
}
|
|
||||||
117
sh/error.h
117
sh/error.h
|
|
@ -1,117 +0,0 @@
|
||||||
/* $NetBSD: error.h,v 1.16 2003/08/07 09:05:30 agc Exp $ */
|
|
||||||
|
|
||||||
/*-
|
|
||||||
* Copyright (c) 1991, 1993
|
|
||||||
* The Regents of the University of California. All rights reserved.
|
|
||||||
*
|
|
||||||
* This code is derived from software contributed to Berkeley by
|
|
||||||
* Kenneth Almquist.
|
|
||||||
*
|
|
||||||
* Redistribution and use in source and binary forms, with or without
|
|
||||||
* modification, are permitted provided that the following conditions
|
|
||||||
* are met:
|
|
||||||
* 1. Redistributions of source code must retain the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer.
|
|
||||||
* 2. Redistributions in binary form must reproduce the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer in the
|
|
||||||
* documentation and/or other materials provided with the distribution.
|
|
||||||
* 3. Neither the name of the University nor the names of its contributors
|
|
||||||
* may be used to endorse or promote products derived from this software
|
|
||||||
* without specific prior written permission.
|
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
|
||||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
||||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
||||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
|
||||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
||||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
|
||||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
|
||||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
||||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
|
||||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
|
||||||
* SUCH DAMAGE.
|
|
||||||
*
|
|
||||||
* @(#)error.h 8.2 (Berkeley) 5/4/95
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <stdarg.h>
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Types of operations (passed to the errmsg routine).
|
|
||||||
*/
|
|
||||||
|
|
||||||
#define E_OPEN 01 /* opening a file */
|
|
||||||
#define E_CREAT 02 /* creating a file */
|
|
||||||
#define E_EXEC 04 /* executing a program */
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* We enclose jmp_buf in a structure so that we can declare pointers to
|
|
||||||
* jump locations. The global variable handler contains the location to
|
|
||||||
* jump to when an exception occurs, and the global variable exception
|
|
||||||
* contains a code identifying the exeception. To implement nested
|
|
||||||
* exception handlers, the user should save the value of handler on entry
|
|
||||||
* to an inner scope, set handler to point to a jmploc structure for the
|
|
||||||
* inner scope, and restore handler on exit from the scope.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <setjmp.h>
|
|
||||||
|
|
||||||
struct jmploc {
|
|
||||||
jmp_buf loc;
|
|
||||||
};
|
|
||||||
|
|
||||||
extern struct jmploc *handler;
|
|
||||||
extern int exception;
|
|
||||||
extern int exerrno; /* error for EXEXEC */
|
|
||||||
|
|
||||||
/* exceptions */
|
|
||||||
#define EXINT 0 /* SIGINT received */
|
|
||||||
#define EXERROR 1 /* a generic error */
|
|
||||||
#define EXSHELLPROC 2 /* execute a shell procedure */
|
|
||||||
#define EXEXEC 3 /* command execution failed */
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* These macros allow the user to suspend the handling of interrupt signals
|
|
||||||
* over a period of time. This is similar to SIGHOLD to or sigblock, but
|
|
||||||
* much more efficient and portable. (But hacking the kernel is so much
|
|
||||||
* more fun than worrying about efficiency and portability. :-))
|
|
||||||
*/
|
|
||||||
|
|
||||||
extern volatile int suppressint;
|
|
||||||
extern volatile int intpending;
|
|
||||||
|
|
||||||
#define INTOFF suppressint++
|
|
||||||
#define INTON { if (--suppressint == 0 && intpending) onint(); }
|
|
||||||
#define FORCEINTON {suppressint = 0; if (intpending) onint();}
|
|
||||||
#define CLEAR_PENDING_INT intpending = 0
|
|
||||||
#define int_pending() intpending
|
|
||||||
|
|
||||||
void exraise(int) __attribute__((__noreturn__));
|
|
||||||
void onint(void);
|
|
||||||
void error(const char *, ...) __attribute__((__noreturn__));
|
|
||||||
void exerror(int, const char *, ...) __attribute__((__noreturn__));
|
|
||||||
const char *errmsg(int, int);
|
|
||||||
|
|
||||||
void sh_err(int, const char *, ...) __attribute__((__noreturn__));
|
|
||||||
void sh_verr(int, const char *, va_list) __attribute__((__noreturn__));
|
|
||||||
void sh_errx(int, const char *, ...) __attribute__((__noreturn__));
|
|
||||||
void sh_verrx(int, const char *, va_list) __attribute__((__noreturn__));
|
|
||||||
void sh_warn(const char *, ...);
|
|
||||||
void sh_vwarn(const char *, va_list);
|
|
||||||
void sh_warnx(const char *, ...);
|
|
||||||
void sh_vwarnx(const char *, va_list);
|
|
||||||
|
|
||||||
void sh_exit(int) __attribute__((__noreturn__));
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* BSD setjmp saves the signal mask, which violates ANSI C and takes time,
|
|
||||||
* so we use _setjmp instead.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#if defined(BSD) && !defined(__SVR4) && !defined(__linux__)
|
|
||||||
#define setjmp(jmploc) _setjmp(jmploc)
|
|
||||||
#define longjmp(jmploc, val) _longjmp(jmploc, val)
|
|
||||||
#endif
|
|
||||||
64
sh/eval.h
64
sh/eval.h
|
|
@ -1,64 +0,0 @@
|
||||||
/* $NetBSD: eval.h,v 1.14 2003/08/07 09:05:31 agc Exp $ */
|
|
||||||
|
|
||||||
/*-
|
|
||||||
* Copyright (c) 1991, 1993
|
|
||||||
* The Regents of the University of California. All rights reserved.
|
|
||||||
*
|
|
||||||
* This code is derived from software contributed to Berkeley by
|
|
||||||
* Kenneth Almquist.
|
|
||||||
*
|
|
||||||
* Redistribution and use in source and binary forms, with or without
|
|
||||||
* modification, are permitted provided that the following conditions
|
|
||||||
* are met:
|
|
||||||
* 1. Redistributions of source code must retain the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer.
|
|
||||||
* 2. Redistributions in binary form must reproduce the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer in the
|
|
||||||
* documentation and/or other materials provided with the distribution.
|
|
||||||
* 3. Neither the name of the University nor the names of its contributors
|
|
||||||
* may be used to endorse or promote products derived from this software
|
|
||||||
* without specific prior written permission.
|
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
|
||||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
||||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
||||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
|
||||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
||||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
|
||||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
|
||||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
||||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
|
||||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
|
||||||
* SUCH DAMAGE.
|
|
||||||
*
|
|
||||||
* @(#)eval.h 8.2 (Berkeley) 5/4/95
|
|
||||||
*/
|
|
||||||
|
|
||||||
extern char *commandname; /* currently executing command */
|
|
||||||
extern int exitstatus; /* exit status of last command */
|
|
||||||
extern int back_exitstatus; /* exit status of backquoted command */
|
|
||||||
extern struct strlist *cmdenviron; /* environment for builtin command */
|
|
||||||
|
|
||||||
|
|
||||||
struct backcmd { /* result of evalbackcmd */
|
|
||||||
int fd; /* file descriptor to read from */
|
|
||||||
char *buf; /* buffer */
|
|
||||||
int nleft; /* number of chars in buffer */
|
|
||||||
struct job *jp; /* job structure for command */
|
|
||||||
};
|
|
||||||
|
|
||||||
void evalstring(char *, int);
|
|
||||||
union node; /* BLETCH for ansi C */
|
|
||||||
void evaltree(union node *, int);
|
|
||||||
void evalbackcmd(union node *, struct backcmd *);
|
|
||||||
|
|
||||||
/* in_function returns nonzero if we are currently evaluating a function */
|
|
||||||
#define in_function() funcnest
|
|
||||||
extern int funcnest;
|
|
||||||
extern int evalskip;
|
|
||||||
|
|
||||||
/* reasons for skipping commands (see comment on breakcmd routine) */
|
|
||||||
#define SKIPBREAK 1
|
|
||||||
#define SKIPCONT 2
|
|
||||||
#define SKIPFUNC 3
|
|
||||||
#define SKIPFILE 4
|
|
||||||
79
sh/exec.h
79
sh/exec.h
|
|
@ -1,79 +0,0 @@
|
||||||
/* $NetBSD: exec.h,v 1.21 2003/08/07 09:05:31 agc Exp $ */
|
|
||||||
|
|
||||||
/*-
|
|
||||||
* Copyright (c) 1991, 1993
|
|
||||||
* The Regents of the University of California. All rights reserved.
|
|
||||||
*
|
|
||||||
* This code is derived from software contributed to Berkeley by
|
|
||||||
* Kenneth Almquist.
|
|
||||||
*
|
|
||||||
* Redistribution and use in source and binary forms, with or without
|
|
||||||
* modification, are permitted provided that the following conditions
|
|
||||||
* are met:
|
|
||||||
* 1. Redistributions of source code must retain the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer.
|
|
||||||
* 2. Redistributions in binary form must reproduce the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer in the
|
|
||||||
* documentation and/or other materials provided with the distribution.
|
|
||||||
* 3. Neither the name of the University nor the names of its contributors
|
|
||||||
* may be used to endorse or promote products derived from this software
|
|
||||||
* without specific prior written permission.
|
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
|
||||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
||||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
||||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
|
||||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
||||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
|
||||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
|
||||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
||||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
|
||||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
|
||||||
* SUCH DAMAGE.
|
|
||||||
*
|
|
||||||
* @(#)exec.h 8.3 (Berkeley) 6/8/95
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* values of cmdtype */
|
|
||||||
#define CMDUNKNOWN -1 /* no entry in table for command */
|
|
||||||
#define CMDNORMAL 0 /* command is an executable program */
|
|
||||||
#define CMDFUNCTION 1 /* command is a shell function */
|
|
||||||
#define CMDBUILTIN 2 /* command is a shell builtin */
|
|
||||||
#define CMDSPLBLTIN 3 /* command is a special shell builtin */
|
|
||||||
|
|
||||||
|
|
||||||
struct cmdentry {
|
|
||||||
int cmdtype;
|
|
||||||
union param {
|
|
||||||
int index;
|
|
||||||
int (*bltin)(int, char**);
|
|
||||||
union node *func;
|
|
||||||
} u;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/* action to find_command() */
|
|
||||||
#define DO_ERR 0x01 /* prints errors */
|
|
||||||
#define DO_ABS 0x02 /* checks absolute paths */
|
|
||||||
#define DO_NOFUNC 0x04 /* don't return shell functions, for command */
|
|
||||||
#define DO_ALTPATH 0x08 /* using alternate path */
|
|
||||||
#define DO_ALTBLTIN 0x20 /* %builtin in alt. path */
|
|
||||||
|
|
||||||
extern const char *pathopt; /* set by padvance */
|
|
||||||
|
|
||||||
void shellexec(char **, char **, const char *, int, int)
|
|
||||||
__attribute__((__noreturn__));
|
|
||||||
char *padvance(const char **, const char *);
|
|
||||||
int hashcmd(int, char **);
|
|
||||||
void find_command(char *, struct cmdentry *, int, const char *);
|
|
||||||
int (*find_builtin(char *))(int, char **);
|
|
||||||
int (*find_splbltin(char *))(int, char **);
|
|
||||||
void hashcd(void);
|
|
||||||
void changepath(const char *);
|
|
||||||
void deletefuncs(void);
|
|
||||||
void getcmdentry(char *, struct cmdentry *);
|
|
||||||
void addcmdentry(char *, struct cmdentry *);
|
|
||||||
void defun(char *, union node *);
|
|
||||||
int unsetfunc(char *);
|
|
||||||
int typecmd(int, char **);
|
|
||||||
void hash_special_builtins(void);
|
|
||||||
1559
sh/expand.c
1559
sh/expand.c
File diff suppressed because it is too large
Load diff
72
sh/expand.h
72
sh/expand.h
|
|
@ -1,72 +0,0 @@
|
||||||
/* $NetBSD: expand.h,v 1.16 2004/07/13 15:05:59 seb Exp $ */
|
|
||||||
|
|
||||||
/*-
|
|
||||||
* Copyright (c) 1991, 1993
|
|
||||||
* The Regents of the University of California. All rights reserved.
|
|
||||||
*
|
|
||||||
* This code is derived from software contributed to Berkeley by
|
|
||||||
* Kenneth Almquist.
|
|
||||||
*
|
|
||||||
* Redistribution and use in source and binary forms, with or without
|
|
||||||
* modification, are permitted provided that the following conditions
|
|
||||||
* are met:
|
|
||||||
* 1. Redistributions of source code must retain the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer.
|
|
||||||
* 2. Redistributions in binary form must reproduce the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer in the
|
|
||||||
* documentation and/or other materials provided with the distribution.
|
|
||||||
* 3. Neither the name of the University nor the names of its contributors
|
|
||||||
* may be used to endorse or promote products derived from this software
|
|
||||||
* without specific prior written permission.
|
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
|
||||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
||||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
||||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
|
||||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
||||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
|
||||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
|
||||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
||||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
|
||||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
|
||||||
* SUCH DAMAGE.
|
|
||||||
*
|
|
||||||
* @(#)expand.h 8.2 (Berkeley) 5/4/95
|
|
||||||
*/
|
|
||||||
|
|
||||||
struct strlist {
|
|
||||||
struct strlist *next;
|
|
||||||
char *text;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
struct arglist {
|
|
||||||
struct strlist *list;
|
|
||||||
struct strlist **lastp;
|
|
||||||
};
|
|
||||||
|
|
||||||
/*
|
|
||||||
* expandarg() flags
|
|
||||||
*/
|
|
||||||
#define EXP_FULL 0x1 /* perform word splitting & file globbing */
|
|
||||||
#define EXP_TILDE 0x2 /* do normal tilde expansion */
|
|
||||||
#define EXP_VARTILDE 0x4 /* expand tildes in an assignment */
|
|
||||||
#define EXP_REDIR 0x8 /* file glob for a redirection (1 match only) */
|
|
||||||
#define EXP_CASE 0x10 /* keeps quotes around for CASE pattern */
|
|
||||||
#define EXP_IFS_SPLIT 0x20 /* need to record arguments for ifs breakup */
|
|
||||||
|
|
||||||
|
|
||||||
union node;
|
|
||||||
void expandhere(union node *, int);
|
|
||||||
void expandarg(union node *, struct arglist *, int);
|
|
||||||
void expari(int);
|
|
||||||
int patmatch(char *, char *, int);
|
|
||||||
void rmescapes(char *);
|
|
||||||
int casematch(union node *, char *);
|
|
||||||
int wordexpcmd(int, char **);
|
|
||||||
|
|
||||||
/* From arith.y */
|
|
||||||
int arith(const char *);
|
|
||||||
int expcmd(int , char **);
|
|
||||||
void arith_lex_reset(void);
|
|
||||||
int yylex(void);
|
|
||||||
50
sh/funcs/cmv
50
sh/funcs/cmv
|
|
@ -1,50 +0,0 @@
|
||||||
# $NetBSD: cmv,v 1.7 1995/05/11 21:31:05 christos Exp $
|
|
||||||
# Copyright (c) 1991, 1993
|
|
||||||
# The Regents of the University of California. All rights reserved.
|
|
||||||
#
|
|
||||||
# This code is derived from software contributed to Berkeley by
|
|
||||||
# Kenneth Almquist.
|
|
||||||
#
|
|
||||||
# Redistribution and use in source and binary forms, with or without
|
|
||||||
# modification, are permitted provided that the following conditions
|
|
||||||
# are met:
|
|
||||||
# 1. Redistributions of source code must retain the above copyright
|
|
||||||
# notice, this list of conditions and the following disclaimer.
|
|
||||||
# 2. Redistributions in binary form must reproduce the above copyright
|
|
||||||
# notice, this list of conditions and the following disclaimer in the
|
|
||||||
# documentation and/or other materials provided with the distribution.
|
|
||||||
# 3. All advertising materials mentioning features or use of this software
|
|
||||||
# must display the following acknowledgement:
|
|
||||||
# This product includes software developed by the University of
|
|
||||||
# California, Berkeley and its contributors.
|
|
||||||
# 4. Neither the name of the University nor the names of its contributors
|
|
||||||
# may be used to endorse or promote products derived from this software
|
|
||||||
# without specific prior written permission.
|
|
||||||
#
|
|
||||||
# THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
|
||||||
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
||||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
||||||
# ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
|
||||||
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
||||||
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
|
||||||
# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
|
||||||
# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
||||||
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
|
||||||
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
|
||||||
# SUCH DAMAGE.
|
|
||||||
#
|
|
||||||
# @(#)cmv 8.2 (Berkeley) 5/4/95
|
|
||||||
|
|
||||||
# Conditional move--don't replace an existing file.
|
|
||||||
|
|
||||||
cmv() {
|
|
||||||
if test $# != 2
|
|
||||||
then echo "cmv: arg count"
|
|
||||||
return 2
|
|
||||||
fi
|
|
||||||
if test -f "$2" -o -w "$2"
|
|
||||||
then echo "$2 exists"
|
|
||||||
return 2
|
|
||||||
fi
|
|
||||||
/bin/mv "$1" "$2"
|
|
||||||
}
|
|
||||||
|
|
@ -1,74 +0,0 @@
|
||||||
# $NetBSD: dirs,v 1.7 1995/05/11 21:31:08 christos Exp $
|
|
||||||
# Copyright (c) 1991, 1993
|
|
||||||
# The Regents of the University of California. All rights reserved.
|
|
||||||
#
|
|
||||||
# This code is derived from software contributed to Berkeley by
|
|
||||||
# Kenneth Almquist.
|
|
||||||
#
|
|
||||||
# Redistribution and use in source and binary forms, with or without
|
|
||||||
# modification, are permitted provided that the following conditions
|
|
||||||
# are met:
|
|
||||||
# 1. Redistributions of source code must retain the above copyright
|
|
||||||
# notice, this list of conditions and the following disclaimer.
|
|
||||||
# 2. Redistributions in binary form must reproduce the above copyright
|
|
||||||
# notice, this list of conditions and the following disclaimer in the
|
|
||||||
# documentation and/or other materials provided with the distribution.
|
|
||||||
# 3. All advertising materials mentioning features or use of this software
|
|
||||||
# must display the following acknowledgement:
|
|
||||||
# This product includes software developed by the University of
|
|
||||||
# California, Berkeley and its contributors.
|
|
||||||
# 4. Neither the name of the University nor the names of its contributors
|
|
||||||
# may be used to endorse or promote products derived from this software
|
|
||||||
# without specific prior written permission.
|
|
||||||
#
|
|
||||||
# THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
|
||||||
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
||||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
||||||
# ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
|
||||||
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
||||||
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
|
||||||
# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
|
||||||
# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
||||||
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
|
||||||
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
|
||||||
# SUCH DAMAGE.
|
|
||||||
#
|
|
||||||
# @(#)dirs 8.2 (Berkeley) 5/4/95
|
|
||||||
|
|
||||||
# pushd, popd, and dirs --- written by Chris Bertin
|
|
||||||
# Pixel Computer Inc. ...!wjh12!pixel!pixutl!chris
|
|
||||||
# as modified by Patrick Elam of GTRI and Kenneth Almquist at UW
|
|
||||||
|
|
||||||
pushd () {
|
|
||||||
SAVE=`pwd`
|
|
||||||
if [ "$1" = "" ]
|
|
||||||
then if [ "$DSTACK" = "" ]
|
|
||||||
then echo "pushd: directory stack empty."
|
|
||||||
return 1
|
|
||||||
fi
|
|
||||||
set $DSTACK
|
|
||||||
cd $1 || return
|
|
||||||
shift 1
|
|
||||||
DSTACK="$*"
|
|
||||||
else cd $1 > /dev/null || return
|
|
||||||
fi
|
|
||||||
DSTACK="$SAVE $DSTACK"
|
|
||||||
dirs
|
|
||||||
}
|
|
||||||
|
|
||||||
popd () {
|
|
||||||
if [ "$DSTACK" = "" ]
|
|
||||||
then echo "popd: directory stack empty."
|
|
||||||
return 1
|
|
||||||
fi
|
|
||||||
set $DSTACK
|
|
||||||
cd $1
|
|
||||||
shift
|
|
||||||
DSTACK=$*
|
|
||||||
dirs
|
|
||||||
}
|
|
||||||
|
|
||||||
dirs () {
|
|
||||||
echo "`pwd` $DSTACK"
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
@ -1,50 +0,0 @@
|
||||||
# $NetBSD: kill,v 1.7 1995/05/11 21:31:10 christos Exp $
|
|
||||||
# Copyright (c) 1991, 1993
|
|
||||||
# The Regents of the University of California. All rights reserved.
|
|
||||||
#
|
|
||||||
# This code is derived from software contributed to Berkeley by
|
|
||||||
# Kenneth Almquist.
|
|
||||||
#
|
|
||||||
# Redistribution and use in source and binary forms, with or without
|
|
||||||
# modification, are permitted provided that the following conditions
|
|
||||||
# are met:
|
|
||||||
# 1. Redistributions of source code must retain the above copyright
|
|
||||||
# notice, this list of conditions and the following disclaimer.
|
|
||||||
# 2. Redistributions in binary form must reproduce the above copyright
|
|
||||||
# notice, this list of conditions and the following disclaimer in the
|
|
||||||
# documentation and/or other materials provided with the distribution.
|
|
||||||
# 3. All advertising materials mentioning features or use of this software
|
|
||||||
# must display the following acknowledgement:
|
|
||||||
# This product includes software developed by the University of
|
|
||||||
# California, Berkeley and its contributors.
|
|
||||||
# 4. Neither the name of the University nor the names of its contributors
|
|
||||||
# may be used to endorse or promote products derived from this software
|
|
||||||
# without specific prior written permission.
|
|
||||||
#
|
|
||||||
# THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
|
||||||
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
||||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
||||||
# ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
|
||||||
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
||||||
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
|
||||||
# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
|
||||||
# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
||||||
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
|
||||||
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
|
||||||
# SUCH DAMAGE.
|
|
||||||
#
|
|
||||||
# @(#)kill 8.2 (Berkeley) 5/4/95
|
|
||||||
|
|
||||||
# Convert job names to process ids and then run /bin/kill.
|
|
||||||
|
|
||||||
kill() {
|
|
||||||
local args x
|
|
||||||
args=
|
|
||||||
for x in "$@"
|
|
||||||
do case $x in
|
|
||||||
%*) x=`jobid "$x"` ;;
|
|
||||||
esac
|
|
||||||
args="$args $x"
|
|
||||||
done
|
|
||||||
/bin/kill $args
|
|
||||||
}
|
|
||||||
|
|
@ -1,39 +0,0 @@
|
||||||
# $NetBSD: login,v 1.7 1995/05/11 21:31:11 christos Exp $
|
|
||||||
# Copyright (c) 1991, 1993
|
|
||||||
# The Regents of the University of California. All rights reserved.
|
|
||||||
#
|
|
||||||
# This code is derived from software contributed to Berkeley by
|
|
||||||
# Kenneth Almquist.
|
|
||||||
#
|
|
||||||
# Redistribution and use in source and binary forms, with or without
|
|
||||||
# modification, are permitted provided that the following conditions
|
|
||||||
# are met:
|
|
||||||
# 1. Redistributions of source code must retain the above copyright
|
|
||||||
# notice, this list of conditions and the following disclaimer.
|
|
||||||
# 2. Redistributions in binary form must reproduce the above copyright
|
|
||||||
# notice, this list of conditions and the following disclaimer in the
|
|
||||||
# documentation and/or other materials provided with the distribution.
|
|
||||||
# 3. All advertising materials mentioning features or use of this software
|
|
||||||
# must display the following acknowledgement:
|
|
||||||
# This product includes software developed by the University of
|
|
||||||
# California, Berkeley and its contributors.
|
|
||||||
# 4. Neither the name of the University nor the names of its contributors
|
|
||||||
# may be used to endorse or promote products derived from this software
|
|
||||||
# without specific prior written permission.
|
|
||||||
#
|
|
||||||
# THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
|
||||||
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
||||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
||||||
# ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
|
||||||
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
||||||
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
|
||||||
# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
|
||||||
# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
||||||
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
|
||||||
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
|
||||||
# SUCH DAMAGE.
|
|
||||||
#
|
|
||||||
# @(#)login 8.2 (Berkeley) 5/4/95
|
|
||||||
|
|
||||||
# replaces the login builtin in the BSD shell
|
|
||||||
login () exec login "$@"
|
|
||||||
|
|
@ -1,38 +0,0 @@
|
||||||
# $NetBSD: newgrp,v 1.7 1995/05/11 21:31:12 christos Exp $
|
|
||||||
# Copyright (c) 1991, 1993
|
|
||||||
# The Regents of the University of California. All rights reserved.
|
|
||||||
#
|
|
||||||
# This code is derived from software contributed to Berkeley by
|
|
||||||
# Kenneth Almquist.
|
|
||||||
#
|
|
||||||
# Redistribution and use in source and binary forms, with or without
|
|
||||||
# modification, are permitted provided that the following conditions
|
|
||||||
# are met:
|
|
||||||
# 1. Redistributions of source code must retain the above copyright
|
|
||||||
# notice, this list of conditions and the following disclaimer.
|
|
||||||
# 2. Redistributions in binary form must reproduce the above copyright
|
|
||||||
# notice, this list of conditions and the following disclaimer in the
|
|
||||||
# documentation and/or other materials provided with the distribution.
|
|
||||||
# 3. All advertising materials mentioning features or use of this software
|
|
||||||
# must display the following acknowledgement:
|
|
||||||
# This product includes software developed by the University of
|
|
||||||
# California, Berkeley and its contributors.
|
|
||||||
# 4. Neither the name of the University nor the names of its contributors
|
|
||||||
# may be used to endorse or promote products derived from this software
|
|
||||||
# without specific prior written permission.
|
|
||||||
#
|
|
||||||
# THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
|
||||||
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
||||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
||||||
# ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
|
||||||
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
||||||
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
|
||||||
# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
|
||||||
# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
||||||
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
|
||||||
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
|
||||||
# SUCH DAMAGE.
|
|
||||||
#
|
|
||||||
# @(#)newgrp 8.2 (Berkeley) 5/4/95
|
|
||||||
|
|
||||||
newgrp() exec newgrp "$@"
|
|
||||||
|
|
@ -1,74 +0,0 @@
|
||||||
# $NetBSD: popd,v 1.7 1995/05/11 21:31:13 christos Exp $
|
|
||||||
# Copyright (c) 1991, 1993
|
|
||||||
# The Regents of the University of California. All rights reserved.
|
|
||||||
#
|
|
||||||
# This code is derived from software contributed to Berkeley by
|
|
||||||
# Kenneth Almquist.
|
|
||||||
#
|
|
||||||
# Redistribution and use in source and binary forms, with or without
|
|
||||||
# modification, are permitted provided that the following conditions
|
|
||||||
# are met:
|
|
||||||
# 1. Redistributions of source code must retain the above copyright
|
|
||||||
# notice, this list of conditions and the following disclaimer.
|
|
||||||
# 2. Redistributions in binary form must reproduce the above copyright
|
|
||||||
# notice, this list of conditions and the following disclaimer in the
|
|
||||||
# documentation and/or other materials provided with the distribution.
|
|
||||||
# 3. All advertising materials mentioning features or use of this software
|
|
||||||
# must display the following acknowledgement:
|
|
||||||
# This product includes software developed by the University of
|
|
||||||
# California, Berkeley and its contributors.
|
|
||||||
# 4. Neither the name of the University nor the names of its contributors
|
|
||||||
# may be used to endorse or promote products derived from this software
|
|
||||||
# without specific prior written permission.
|
|
||||||
#
|
|
||||||
# THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
|
||||||
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
||||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
||||||
# ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
|
||||||
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
||||||
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
|
||||||
# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
|
||||||
# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
||||||
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
|
||||||
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
|
||||||
# SUCH DAMAGE.
|
|
||||||
#
|
|
||||||
# @(#)popd 8.2 (Berkeley) 5/4/95
|
|
||||||
|
|
||||||
# pushd, popd, and dirs --- written by Chris Bertin
|
|
||||||
# Pixel Computer Inc. ...!wjh12!pixel!pixutl!chris
|
|
||||||
# as modified by Patrick Elam of GTRI and Kenneth Almquist at UW
|
|
||||||
|
|
||||||
pushd () {
|
|
||||||
SAVE=`pwd`
|
|
||||||
if [ "$1" = "" ]
|
|
||||||
then if [ "$DSTACK" = "" ]
|
|
||||||
then echo "pushd: directory stack empty."
|
|
||||||
return 1
|
|
||||||
fi
|
|
||||||
set $DSTACK
|
|
||||||
cd $1 || return
|
|
||||||
shift 1
|
|
||||||
DSTACK="$*"
|
|
||||||
else cd $1 > /dev/null || return
|
|
||||||
fi
|
|
||||||
DSTACK="$SAVE $DSTACK"
|
|
||||||
dirs
|
|
||||||
}
|
|
||||||
|
|
||||||
popd () {
|
|
||||||
if [ "$DSTACK" = "" ]
|
|
||||||
then echo "popd: directory stack empty."
|
|
||||||
return 1
|
|
||||||
fi
|
|
||||||
set $DSTACK
|
|
||||||
cd $1
|
|
||||||
shift
|
|
||||||
DSTACK=$*
|
|
||||||
dirs
|
|
||||||
}
|
|
||||||
|
|
||||||
dirs () {
|
|
||||||
echo "`pwd` $DSTACK"
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
@ -1,74 +0,0 @@
|
||||||
# $NetBSD: pushd,v 1.7 1995/05/11 21:31:15 christos Exp $
|
|
||||||
# Copyright (c) 1991, 1993
|
|
||||||
# The Regents of the University of California. All rights reserved.
|
|
||||||
#
|
|
||||||
# This code is derived from software contributed to Berkeley by
|
|
||||||
# Kenneth Almquist.
|
|
||||||
#
|
|
||||||
# Redistribution and use in source and binary forms, with or without
|
|
||||||
# modification, are permitted provided that the following conditions
|
|
||||||
# are met:
|
|
||||||
# 1. Redistributions of source code must retain the above copyright
|
|
||||||
# notice, this list of conditions and the following disclaimer.
|
|
||||||
# 2. Redistributions in binary form must reproduce the above copyright
|
|
||||||
# notice, this list of conditions and the following disclaimer in the
|
|
||||||
# documentation and/or other materials provided with the distribution.
|
|
||||||
# 3. All advertising materials mentioning features or use of this software
|
|
||||||
# must display the following acknowledgement:
|
|
||||||
# This product includes software developed by the University of
|
|
||||||
# California, Berkeley and its contributors.
|
|
||||||
# 4. Neither the name of the University nor the names of its contributors
|
|
||||||
# may be used to endorse or promote products derived from this software
|
|
||||||
# without specific prior written permission.
|
|
||||||
#
|
|
||||||
# THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
|
||||||
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
||||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
||||||
# ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
|
||||||
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
||||||
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
|
||||||
# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
|
||||||
# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
||||||
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
|
||||||
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
|
||||||
# SUCH DAMAGE.
|
|
||||||
#
|
|
||||||
# @(#)pushd 8.2 (Berkeley) 5/4/95
|
|
||||||
|
|
||||||
# pushd, popd, and dirs --- written by Chris Bertin
|
|
||||||
# Pixel Computer Inc. ...!wjh12!pixel!pixutl!chris
|
|
||||||
# as modified by Patrick Elam of GTRI and Kenneth Almquist at UW
|
|
||||||
|
|
||||||
pushd () {
|
|
||||||
SAVE=`pwd`
|
|
||||||
if [ "$1" = "" ]
|
|
||||||
then if [ "$DSTACK" = "" ]
|
|
||||||
then echo "pushd: directory stack empty."
|
|
||||||
return 1
|
|
||||||
fi
|
|
||||||
set $DSTACK
|
|
||||||
cd $1 || return
|
|
||||||
shift 1
|
|
||||||
DSTACK="$*"
|
|
||||||
else cd $1 > /dev/null || return
|
|
||||||
fi
|
|
||||||
DSTACK="$SAVE $DSTACK"
|
|
||||||
dirs
|
|
||||||
}
|
|
||||||
|
|
||||||
popd () {
|
|
||||||
if [ "$DSTACK" = "" ]
|
|
||||||
then echo "popd: directory stack empty."
|
|
||||||
return 1
|
|
||||||
fi
|
|
||||||
set $DSTACK
|
|
||||||
cd $1
|
|
||||||
shift
|
|
||||||
DSTACK=$*
|
|
||||||
dirs
|
|
||||||
}
|
|
||||||
|
|
||||||
dirs () {
|
|
||||||
echo "`pwd` $DSTACK"
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
@ -1,42 +0,0 @@
|
||||||
# $NetBSD: suspend,v 1.7 1995/05/11 21:31:17 christos Exp $
|
|
||||||
# Copyright (c) 1991, 1993
|
|
||||||
# The Regents of the University of California. All rights reserved.
|
|
||||||
#
|
|
||||||
# This code is derived from software contributed to Berkeley by
|
|
||||||
# Kenneth Almquist.
|
|
||||||
#
|
|
||||||
# Redistribution and use in source and binary forms, with or without
|
|
||||||
# modification, are permitted provided that the following conditions
|
|
||||||
# are met:
|
|
||||||
# 1. Redistributions of source code must retain the above copyright
|
|
||||||
# notice, this list of conditions and the following disclaimer.
|
|
||||||
# 2. Redistributions in binary form must reproduce the above copyright
|
|
||||||
# notice, this list of conditions and the following disclaimer in the
|
|
||||||
# documentation and/or other materials provided with the distribution.
|
|
||||||
# 3. All advertising materials mentioning features or use of this software
|
|
||||||
# must display the following acknowledgement:
|
|
||||||
# This product includes software developed by the University of
|
|
||||||
# California, Berkeley and its contributors.
|
|
||||||
# 4. Neither the name of the University nor the names of its contributors
|
|
||||||
# may be used to endorse or promote products derived from this software
|
|
||||||
# without specific prior written permission.
|
|
||||||
#
|
|
||||||
# THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
|
||||||
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
||||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
||||||
# ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
|
||||||
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
||||||
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
|
||||||
# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
|
||||||
# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
||||||
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
|
||||||
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
|
||||||
# SUCH DAMAGE.
|
|
||||||
#
|
|
||||||
# @(#)suspend 8.2 (Berkeley) 5/4/95
|
|
||||||
|
|
||||||
suspend() {
|
|
||||||
local -
|
|
||||||
set +j
|
|
||||||
kill -TSTP 0
|
|
||||||
}
|
|
||||||
540
sh/histedit.c
540
sh/histedit.c
|
|
@ -1,540 +0,0 @@
|
||||||
/* $NetBSD: histedit.c,v 1.34 2003/10/27 06:19:29 lukem Exp $ */
|
|
||||||
|
|
||||||
/*-
|
|
||||||
* Copyright (c) 1993
|
|
||||||
* The Regents of the University of California. All rights reserved.
|
|
||||||
*
|
|
||||||
* This code is derived from software contributed to Berkeley by
|
|
||||||
* Kenneth Almquist.
|
|
||||||
*
|
|
||||||
* Redistribution and use in source and binary forms, with or without
|
|
||||||
* modification, are permitted provided that the following conditions
|
|
||||||
* are met:
|
|
||||||
* 1. Redistributions of source code must retain the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer.
|
|
||||||
* 2. Redistributions in binary form must reproduce the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer in the
|
|
||||||
* documentation and/or other materials provided with the distribution.
|
|
||||||
* 3. Neither the name of the University nor the names of its contributors
|
|
||||||
* may be used to endorse or promote products derived from this software
|
|
||||||
* without specific prior written permission.
|
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
|
||||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
||||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
||||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
|
||||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
||||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
|
||||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
|
||||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
||||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
|
||||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
|
||||||
* SUCH DAMAGE.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <sys/cdefs.h>
|
|
||||||
#ifndef lint
|
|
||||||
#if 0
|
|
||||||
static char sccsid[] = "@(#)histedit.c 8.2 (Berkeley) 5/4/95";
|
|
||||||
#else
|
|
||||||
__RCSID("$NetBSD: histedit.c,v 1.34 2003/10/27 06:19:29 lukem Exp $");
|
|
||||||
#endif
|
|
||||||
#endif /* not lint */
|
|
||||||
|
|
||||||
#include <sys/param.h>
|
|
||||||
#include <paths.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
/*
|
|
||||||
* Editline and history functions (and glue).
|
|
||||||
*/
|
|
||||||
#include "shell.h"
|
|
||||||
#include "parser.h"
|
|
||||||
#include "var.h"
|
|
||||||
#include "options.h"
|
|
||||||
#include "main.h"
|
|
||||||
#include "output.h"
|
|
||||||
#include "mystring.h"
|
|
||||||
#include "myhistedit.h"
|
|
||||||
#include "error.h"
|
|
||||||
#ifndef SMALL
|
|
||||||
#include "eval.h"
|
|
||||||
#include "memalloc.h"
|
|
||||||
|
|
||||||
#define MAXHISTLOOPS 4 /* max recursions through fc */
|
|
||||||
#define DEFEDITOR "ed" /* default editor *should* be $EDITOR */
|
|
||||||
|
|
||||||
History *hist; /* history cookie */
|
|
||||||
EditLine *el; /* editline cookie */
|
|
||||||
int displayhist;
|
|
||||||
static FILE *el_in, *el_out;
|
|
||||||
|
|
||||||
STATIC const char *fc_replace(const char *, char *, char *);
|
|
||||||
|
|
||||||
#ifdef DEBUG
|
|
||||||
extern FILE *tracefile;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Set history and editing status. Called whenever the status may
|
|
||||||
* have changed (figures out what to do).
|
|
||||||
*/
|
|
||||||
void
|
|
||||||
histedit(void)
|
|
||||||
{
|
|
||||||
FILE *el_err;
|
|
||||||
|
|
||||||
#define editing (Eflag || Vflag)
|
|
||||||
|
|
||||||
if (iflag) {
|
|
||||||
if (!hist) {
|
|
||||||
/*
|
|
||||||
* turn history on
|
|
||||||
*/
|
|
||||||
INTOFF;
|
|
||||||
hist = history_init();
|
|
||||||
INTON;
|
|
||||||
|
|
||||||
if (hist != NULL)
|
|
||||||
sethistsize(histsizeval());
|
|
||||||
else
|
|
||||||
out2str("sh: can't initialize history\n");
|
|
||||||
}
|
|
||||||
if (editing && !el && isatty(0)) { /* && isatty(2) ??? */
|
|
||||||
/*
|
|
||||||
* turn editing on
|
|
||||||
*/
|
|
||||||
char *term, *shname;
|
|
||||||
|
|
||||||
INTOFF;
|
|
||||||
if (el_in == NULL)
|
|
||||||
el_in = fdopen(0, "r");
|
|
||||||
if (el_out == NULL)
|
|
||||||
el_out = fdopen(2, "w");
|
|
||||||
if (el_in == NULL || el_out == NULL)
|
|
||||||
goto bad;
|
|
||||||
el_err = el_out;
|
|
||||||
#if DEBUG
|
|
||||||
if (tracefile)
|
|
||||||
el_err = tracefile;
|
|
||||||
#endif
|
|
||||||
term = lookupvar("TERM");
|
|
||||||
if (term)
|
|
||||||
setenv("TERM", term, 1);
|
|
||||||
else
|
|
||||||
unsetenv("TERM");
|
|
||||||
shname = arg0;
|
|
||||||
if (shname[0] == '-')
|
|
||||||
shname++;
|
|
||||||
el = el_init(shname, el_in, el_out, el_err);
|
|
||||||
if (el != NULL) {
|
|
||||||
if (hist)
|
|
||||||
el_set(el, EL_HIST, history, hist);
|
|
||||||
el_set(el, EL_PROMPT, getprompt);
|
|
||||||
el_set(el, EL_SIGNAL, 1);
|
|
||||||
} else {
|
|
||||||
bad:
|
|
||||||
out2str("sh: can't initialize editing\n");
|
|
||||||
}
|
|
||||||
INTON;
|
|
||||||
} else if (!editing && el) {
|
|
||||||
INTOFF;
|
|
||||||
el_end(el);
|
|
||||||
el = NULL;
|
|
||||||
INTON;
|
|
||||||
}
|
|
||||||
if (el) {
|
|
||||||
if (Vflag)
|
|
||||||
el_set(el, EL_EDITOR, "vi");
|
|
||||||
else if (Eflag)
|
|
||||||
el_set(el, EL_EDITOR, "emacs");
|
|
||||||
el_source(el, NULL);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
INTOFF;
|
|
||||||
if (el) { /* no editing if not interactive */
|
|
||||||
el_end(el);
|
|
||||||
el = NULL;
|
|
||||||
}
|
|
||||||
if (hist) {
|
|
||||||
history_end(hist);
|
|
||||||
hist = NULL;
|
|
||||||
}
|
|
||||||
INTON;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
sethistsize(const char *hs)
|
|
||||||
{
|
|
||||||
int histsize;
|
|
||||||
HistEvent he;
|
|
||||||
|
|
||||||
if (hist != NULL) {
|
|
||||||
if (hs == NULL || *hs == '\0' ||
|
|
||||||
(histsize = atoi(hs)) < 0)
|
|
||||||
histsize = 100;
|
|
||||||
history(hist, &he, H_SETSIZE, histsize);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
setterm(const char *term)
|
|
||||||
{
|
|
||||||
if (el != NULL && term != NULL)
|
|
||||||
if (el_set(el, EL_TERMINAL, term) != 0) {
|
|
||||||
outfmt(out2, "sh: Can't set terminal type %s\n", term);
|
|
||||||
outfmt(out2, "sh: Using dumb terminal settings.\n");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
inputrc(argc, argv)
|
|
||||||
int argc;
|
|
||||||
char **argv;
|
|
||||||
{
|
|
||||||
if (argc != 2) {
|
|
||||||
out2str("usage: inputrc file\n");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
if (el != NULL) {
|
|
||||||
if (el_source(el, argv[1])) {
|
|
||||||
out2str("inputrc: failed\n");
|
|
||||||
return 1;
|
|
||||||
} else
|
|
||||||
return 0;
|
|
||||||
} else {
|
|
||||||
out2str("sh: inputrc ignored, not editing\n");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* This command is provided since POSIX decided to standardize
|
|
||||||
* the Korn shell fc command. Oh well...
|
|
||||||
*/
|
|
||||||
int
|
|
||||||
histcmd(int argc, char **argv)
|
|
||||||
{
|
|
||||||
int ch;
|
|
||||||
const char *editor = NULL;
|
|
||||||
HistEvent he;
|
|
||||||
int lflg = 0, nflg = 0, rflg = 0, sflg = 0;
|
|
||||||
int i, retval;
|
|
||||||
const char *firststr, *laststr;
|
|
||||||
int first, last, direction;
|
|
||||||
char *pat = NULL, *repl; /* ksh "fc old=new" crap */
|
|
||||||
static int active = 0;
|
|
||||||
struct jmploc jmploc;
|
|
||||||
struct jmploc *volatile savehandler;
|
|
||||||
char editfile[MAXPATHLEN + 1];
|
|
||||||
FILE *efp;
|
|
||||||
#ifdef __GNUC__
|
|
||||||
/* Avoid longjmp clobbering */
|
|
||||||
(void) &editor;
|
|
||||||
(void) &lflg;
|
|
||||||
(void) &nflg;
|
|
||||||
(void) &rflg;
|
|
||||||
(void) &sflg;
|
|
||||||
(void) &firststr;
|
|
||||||
(void) &laststr;
|
|
||||||
(void) &pat;
|
|
||||||
(void) &repl;
|
|
||||||
(void) &efp;
|
|
||||||
(void) &argc;
|
|
||||||
(void) &argv;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (hist == NULL)
|
|
||||||
error("history not active");
|
|
||||||
|
|
||||||
if (argc == 1)
|
|
||||||
error("missing history argument");
|
|
||||||
|
|
||||||
optreset = 1; optind = 1; /* initialize getopt */
|
|
||||||
while (not_fcnumber(argv[optind]) &&
|
|
||||||
(ch = getopt(argc, argv, ":e:lnrs")) != -1)
|
|
||||||
switch ((char)ch) {
|
|
||||||
case 'e':
|
|
||||||
editor = optionarg;
|
|
||||||
break;
|
|
||||||
case 'l':
|
|
||||||
lflg = 1;
|
|
||||||
break;
|
|
||||||
case 'n':
|
|
||||||
nflg = 1;
|
|
||||||
break;
|
|
||||||
case 'r':
|
|
||||||
rflg = 1;
|
|
||||||
break;
|
|
||||||
case 's':
|
|
||||||
sflg = 1;
|
|
||||||
break;
|
|
||||||
case ':':
|
|
||||||
error("option -%c expects argument", optopt);
|
|
||||||
/* NOTREACHED */
|
|
||||||
case '?':
|
|
||||||
default:
|
|
||||||
error("unknown option: -%c", optopt);
|
|
||||||
/* NOTREACHED */
|
|
||||||
}
|
|
||||||
argc -= optind, argv += optind;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* If executing...
|
|
||||||
*/
|
|
||||||
if (lflg == 0 || editor || sflg) {
|
|
||||||
lflg = 0; /* ignore */
|
|
||||||
editfile[0] = '\0';
|
|
||||||
/*
|
|
||||||
* Catch interrupts to reset active counter and
|
|
||||||
* cleanup temp files.
|
|
||||||
*/
|
|
||||||
if (setjmp(jmploc.loc)) {
|
|
||||||
active = 0;
|
|
||||||
if (*editfile)
|
|
||||||
unlink(editfile);
|
|
||||||
handler = savehandler;
|
|
||||||
longjmp(handler->loc, 1);
|
|
||||||
}
|
|
||||||
savehandler = handler;
|
|
||||||
handler = &jmploc;
|
|
||||||
if (++active > MAXHISTLOOPS) {
|
|
||||||
active = 0;
|
|
||||||
displayhist = 0;
|
|
||||||
error("called recursively too many times");
|
|
||||||
}
|
|
||||||
/*
|
|
||||||
* Set editor.
|
|
||||||
*/
|
|
||||||
if (sflg == 0) {
|
|
||||||
if (editor == NULL &&
|
|
||||||
(editor = bltinlookup("FCEDIT", 1)) == NULL &&
|
|
||||||
(editor = bltinlookup("EDITOR", 1)) == NULL)
|
|
||||||
editor = DEFEDITOR;
|
|
||||||
if (editor[0] == '-' && editor[1] == '\0') {
|
|
||||||
sflg = 1; /* no edit */
|
|
||||||
editor = NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* If executing, parse [old=new] now
|
|
||||||
*/
|
|
||||||
if (lflg == 0 && argc > 0 &&
|
|
||||||
((repl = strchr(argv[0], '=')) != NULL)) {
|
|
||||||
pat = argv[0];
|
|
||||||
*repl++ = '\0';
|
|
||||||
argc--, argv++;
|
|
||||||
}
|
|
||||||
/*
|
|
||||||
* determine [first] and [last]
|
|
||||||
*/
|
|
||||||
switch (argc) {
|
|
||||||
case 0:
|
|
||||||
firststr = lflg ? "-16" : "-1";
|
|
||||||
laststr = "-1";
|
|
||||||
break;
|
|
||||||
case 1:
|
|
||||||
firststr = argv[0];
|
|
||||||
laststr = lflg ? "-1" : argv[0];
|
|
||||||
break;
|
|
||||||
case 2:
|
|
||||||
firststr = argv[0];
|
|
||||||
laststr = argv[1];
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
error("too many args");
|
|
||||||
/* NOTREACHED */
|
|
||||||
}
|
|
||||||
/*
|
|
||||||
* Turn into event numbers.
|
|
||||||
*/
|
|
||||||
first = str_to_event(firststr, 0);
|
|
||||||
last = str_to_event(laststr, 1);
|
|
||||||
|
|
||||||
if (rflg) {
|
|
||||||
i = last;
|
|
||||||
last = first;
|
|
||||||
first = i;
|
|
||||||
}
|
|
||||||
/*
|
|
||||||
* XXX - this should not depend on the event numbers
|
|
||||||
* always increasing. Add sequence numbers or offset
|
|
||||||
* to the history element in next (diskbased) release.
|
|
||||||
*/
|
|
||||||
direction = first < last ? H_PREV : H_NEXT;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* If editing, grab a temp file.
|
|
||||||
*/
|
|
||||||
if (editor) {
|
|
||||||
int fd;
|
|
||||||
INTOFF; /* easier */
|
|
||||||
snprintf(editfile, sizeof(editfile), "%s_shXXXXXX", _PATH_TMP);
|
|
||||||
if ((fd = mkstemp(editfile)) < 0)
|
|
||||||
error("can't create temporary file %s", editfile);
|
|
||||||
if ((efp = fdopen(fd, "w")) == NULL) {
|
|
||||||
close(fd);
|
|
||||||
error("can't allocate stdio buffer for temp");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Loop through selected history events. If listing or executing,
|
|
||||||
* do it now. Otherwise, put into temp file and call the editor
|
|
||||||
* after.
|
|
||||||
*
|
|
||||||
* The history interface needs rethinking, as the following
|
|
||||||
* convolutions will demonstrate.
|
|
||||||
*/
|
|
||||||
history(hist, &he, H_FIRST);
|
|
||||||
retval = history(hist, &he, H_NEXT_EVENT, first);
|
|
||||||
for (;retval != -1; retval = history(hist, &he, direction)) {
|
|
||||||
if (lflg) {
|
|
||||||
if (!nflg)
|
|
||||||
out1fmt("%5d ", he.num);
|
|
||||||
out1str(he.str);
|
|
||||||
} else {
|
|
||||||
const char *s = pat ?
|
|
||||||
fc_replace(he.str, pat, repl) : he.str;
|
|
||||||
|
|
||||||
if (sflg) {
|
|
||||||
if (displayhist) {
|
|
||||||
out2str(s);
|
|
||||||
}
|
|
||||||
|
|
||||||
evalstring(strcpy(stalloc(strlen(s) + 1), s), 0);
|
|
||||||
if (displayhist && hist) {
|
|
||||||
/*
|
|
||||||
* XXX what about recursive and
|
|
||||||
* relative histnums.
|
|
||||||
*/
|
|
||||||
history(hist, &he, H_ENTER, s);
|
|
||||||
}
|
|
||||||
} else
|
|
||||||
fputs(s, efp);
|
|
||||||
}
|
|
||||||
/*
|
|
||||||
* At end? (if we were to lose last, we'd sure be
|
|
||||||
* messed up).
|
|
||||||
*/
|
|
||||||
if (he.num == last)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (editor) {
|
|
||||||
char *editcmd;
|
|
||||||
|
|
||||||
fclose(efp);
|
|
||||||
editcmd = stalloc(strlen(editor) + strlen(editfile) + 2);
|
|
||||||
sprintf(editcmd, "%s %s", editor, editfile);
|
|
||||||
evalstring(editcmd, 0); /* XXX - should use no JC command */
|
|
||||||
INTON;
|
|
||||||
readcmdfile(editfile); /* XXX - should read back - quick tst */
|
|
||||||
unlink(editfile);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (lflg == 0 && active > 0)
|
|
||||||
--active;
|
|
||||||
if (displayhist)
|
|
||||||
displayhist = 0;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
STATIC const char *
|
|
||||||
fc_replace(const char *s, char *p, char *r)
|
|
||||||
{
|
|
||||||
char *dest;
|
|
||||||
int plen = strlen(p);
|
|
||||||
|
|
||||||
STARTSTACKSTR(dest);
|
|
||||||
while (*s) {
|
|
||||||
if (*s == *p && strncmp(s, p, plen) == 0) {
|
|
||||||
while (*r)
|
|
||||||
STPUTC(*r++, dest);
|
|
||||||
s += plen;
|
|
||||||
*p = '\0'; /* so no more matches */
|
|
||||||
} else
|
|
||||||
STPUTC(*s++, dest);
|
|
||||||
}
|
|
||||||
STACKSTRNUL(dest);
|
|
||||||
dest = grabstackstr(dest);
|
|
||||||
|
|
||||||
return (dest);
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
not_fcnumber(char *s)
|
|
||||||
{
|
|
||||||
if (s == NULL)
|
|
||||||
return 0;
|
|
||||||
if (*s == '-')
|
|
||||||
s++;
|
|
||||||
return (!is_number(s));
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
str_to_event(const char *str, int last)
|
|
||||||
{
|
|
||||||
HistEvent he;
|
|
||||||
const char *s = str;
|
|
||||||
int relative = 0;
|
|
||||||
int i, retval;
|
|
||||||
|
|
||||||
retval = history(hist, &he, H_FIRST);
|
|
||||||
switch (*s) {
|
|
||||||
case '-':
|
|
||||||
relative = 1;
|
|
||||||
/*FALLTHROUGH*/
|
|
||||||
case '+':
|
|
||||||
s++;
|
|
||||||
}
|
|
||||||
if (is_number(s)) {
|
|
||||||
i = atoi(s);
|
|
||||||
if (relative) {
|
|
||||||
while (retval != -1 && i--) {
|
|
||||||
retval = history(hist, &he, H_NEXT);
|
|
||||||
}
|
|
||||||
if (retval == -1)
|
|
||||||
retval = history(hist, &he, H_LAST);
|
|
||||||
} else {
|
|
||||||
retval = history(hist, &he, H_NEXT_EVENT, i);
|
|
||||||
if (retval == -1) {
|
|
||||||
/*
|
|
||||||
* the notion of first and last is
|
|
||||||
* backwards to that of the history package
|
|
||||||
*/
|
|
||||||
retval = history(hist, &he,
|
|
||||||
last ? H_FIRST : H_LAST);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (retval == -1)
|
|
||||||
error("history number %s not found (internal error)",
|
|
||||||
str);
|
|
||||||
} else {
|
|
||||||
/*
|
|
||||||
* pattern
|
|
||||||
*/
|
|
||||||
retval = history(hist, &he, H_PREV_STR, str);
|
|
||||||
if (retval == -1)
|
|
||||||
error("history pattern not found: %s", str);
|
|
||||||
}
|
|
||||||
return (he.num);
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
int
|
|
||||||
histcmd(int argc, char **argv)
|
|
||||||
{
|
|
||||||
error("not compiled with history support");
|
|
||||||
/* NOTREACHED */
|
|
||||||
}
|
|
||||||
int
|
|
||||||
inputrc(int argc, char **argv)
|
|
||||||
{
|
|
||||||
error("not compiled with history support");
|
|
||||||
/* NOTREACHED */
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
39
sh/init.h
39
sh/init.h
|
|
@ -1,39 +0,0 @@
|
||||||
/* $NetBSD: init.h,v 1.10 2003/08/07 09:05:32 agc Exp $ */
|
|
||||||
|
|
||||||
/*-
|
|
||||||
* Copyright (c) 1991, 1993
|
|
||||||
* The Regents of the University of California. All rights reserved.
|
|
||||||
*
|
|
||||||
* This code is derived from software contributed to Berkeley by
|
|
||||||
* Kenneth Almquist.
|
|
||||||
*
|
|
||||||
* Redistribution and use in source and binary forms, with or without
|
|
||||||
* modification, are permitted provided that the following conditions
|
|
||||||
* are met:
|
|
||||||
* 1. Redistributions of source code must retain the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer.
|
|
||||||
* 2. Redistributions in binary form must reproduce the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer in the
|
|
||||||
* documentation and/or other materials provided with the distribution.
|
|
||||||
* 3. Neither the name of the University nor the names of its contributors
|
|
||||||
* may be used to endorse or promote products derived from this software
|
|
||||||
* without specific prior written permission.
|
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
|
||||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
||||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
||||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
|
||||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
||||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
|
||||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
|
||||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
||||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
|
||||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
|
||||||
* SUCH DAMAGE.
|
|
||||||
*
|
|
||||||
* @(#)init.h 8.2 (Berkeley) 5/4/95
|
|
||||||
*/
|
|
||||||
|
|
||||||
void init(void);
|
|
||||||
void reset(void);
|
|
||||||
void initshellproc(void);
|
|
||||||
577
sh/input.c
577
sh/input.c
|
|
@ -1,577 +0,0 @@
|
||||||
/* $NetBSD: input.c,v 1.39 2003/08/07 09:05:32 agc Exp $ */
|
|
||||||
|
|
||||||
/*-
|
|
||||||
* Copyright (c) 1991, 1993
|
|
||||||
* The Regents of the University of California. All rights reserved.
|
|
||||||
*
|
|
||||||
* This code is derived from software contributed to Berkeley by
|
|
||||||
* Kenneth Almquist.
|
|
||||||
*
|
|
||||||
* Redistribution and use in source and binary forms, with or without
|
|
||||||
* modification, are permitted provided that the following conditions
|
|
||||||
* are met:
|
|
||||||
* 1. Redistributions of source code must retain the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer.
|
|
||||||
* 2. Redistributions in binary form must reproduce the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer in the
|
|
||||||
* documentation and/or other materials provided with the distribution.
|
|
||||||
* 3. Neither the name of the University nor the names of its contributors
|
|
||||||
* may be used to endorse or promote products derived from this software
|
|
||||||
* without specific prior written permission.
|
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
|
||||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
||||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
||||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
|
||||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
||||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
|
||||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
|
||||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
||||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
|
||||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
|
||||||
* SUCH DAMAGE.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <sys/cdefs.h>
|
|
||||||
#ifndef lint
|
|
||||||
#if 0
|
|
||||||
static char sccsid[] = "@(#)input.c 8.3 (Berkeley) 6/9/95";
|
|
||||||
#else
|
|
||||||
__RCSID("$NetBSD: input.c,v 1.39 2003/08/07 09:05:32 agc Exp $");
|
|
||||||
#endif
|
|
||||||
#endif /* not lint */
|
|
||||||
|
|
||||||
#include <stdio.h> /* defines BUFSIZ */
|
|
||||||
#include <fcntl.h>
|
|
||||||
#include <errno.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
/*
|
|
||||||
* This file implements the input routines used by the parser.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "shell.h"
|
|
||||||
#include "redir.h"
|
|
||||||
#include "syntax.h"
|
|
||||||
#include "input.h"
|
|
||||||
#include "output.h"
|
|
||||||
#include "options.h"
|
|
||||||
#include "memalloc.h"
|
|
||||||
#include "error.h"
|
|
||||||
#include "alias.h"
|
|
||||||
#include "parser.h"
|
|
||||||
#include "myhistedit.h"
|
|
||||||
|
|
||||||
#ifdef WITH_LINENOISE
|
|
||||||
#include "linenoise.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define EOF_NLEFT -99 /* value of parsenleft when EOF pushed back */
|
|
||||||
|
|
||||||
MKINIT
|
|
||||||
struct strpush {
|
|
||||||
struct strpush *prev; /* preceding string on stack */
|
|
||||||
char *prevstring;
|
|
||||||
int prevnleft;
|
|
||||||
int prevlleft;
|
|
||||||
struct alias *ap; /* if push was associated with an alias */
|
|
||||||
};
|
|
||||||
|
|
||||||
/*
|
|
||||||
* The parsefile structure pointed to by the global variable parsefile
|
|
||||||
* contains information about the current file being read.
|
|
||||||
*/
|
|
||||||
|
|
||||||
MKINIT
|
|
||||||
struct parsefile {
|
|
||||||
struct parsefile *prev; /* preceding file on stack */
|
|
||||||
int linno; /* current line */
|
|
||||||
int fd; /* file descriptor (or -1 if string) */
|
|
||||||
int nleft; /* number of chars left in this line */
|
|
||||||
int lleft; /* number of chars left in this buffer */
|
|
||||||
char *nextc; /* next char in buffer */
|
|
||||||
char *buf; /* input buffer */
|
|
||||||
struct strpush *strpush; /* for pushing strings at this level */
|
|
||||||
struct strpush basestrpush; /* so pushing one is fast */
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
int plinno = 1; /* input line number */
|
|
||||||
int parsenleft; /* copy of parsefile->nleft */
|
|
||||||
MKINIT int parselleft; /* copy of parsefile->lleft */
|
|
||||||
char *parsenextc; /* copy of parsefile->nextc */
|
|
||||||
MKINIT struct parsefile basepf; /* top level input file */
|
|
||||||
MKINIT char basebuf[BUFSIZ]; /* buffer for top level input file */
|
|
||||||
struct parsefile *parsefile = &basepf; /* current input file */
|
|
||||||
int init_editline = 0; /* editline library initialized? */
|
|
||||||
int whichprompt; /* 1 == PS1, 2 == PS2 */
|
|
||||||
|
|
||||||
#if WITH_HISTORY
|
|
||||||
EditLine *el; /* cookie for editline package */
|
|
||||||
#endif
|
|
||||||
|
|
||||||
STATIC void pushfile(void);
|
|
||||||
static int preadfd(void);
|
|
||||||
|
|
||||||
#ifdef mkinit
|
|
||||||
INCLUDE <stdio.h>
|
|
||||||
INCLUDE "input.h"
|
|
||||||
INCLUDE "error.h"
|
|
||||||
|
|
||||||
INIT {
|
|
||||||
basepf.nextc = basepf.buf = basebuf;
|
|
||||||
}
|
|
||||||
|
|
||||||
RESET {
|
|
||||||
if (exception != EXSHELLPROC)
|
|
||||||
parselleft = parsenleft = 0; /* clear input buffer */
|
|
||||||
popallfiles();
|
|
||||||
}
|
|
||||||
|
|
||||||
SHELLPROC {
|
|
||||||
popallfiles();
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Read a line from the script.
|
|
||||||
*/
|
|
||||||
|
|
||||||
char *
|
|
||||||
pfgets(char *line, int len)
|
|
||||||
{
|
|
||||||
char *p = line;
|
|
||||||
int nleft = len;
|
|
||||||
int c;
|
|
||||||
|
|
||||||
while (--nleft > 0) {
|
|
||||||
c = pgetc_macro();
|
|
||||||
if (c == PEOF) {
|
|
||||||
if (p == line)
|
|
||||||
return NULL;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
*p++ = c;
|
|
||||||
if (c == '\n')
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
*p = '\0';
|
|
||||||
return line;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Read a character from the script, returning PEOF on end of file.
|
|
||||||
* Nul characters in the input are silently discarded.
|
|
||||||
*/
|
|
||||||
|
|
||||||
int
|
|
||||||
pgetc(void)
|
|
||||||
{
|
|
||||||
return pgetc_macro();
|
|
||||||
}
|
|
||||||
|
|
||||||
int in_interactive_mode() {
|
|
||||||
return parsefile != NULL && parsefile->fd == 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
|
||||||
preadfd(void)
|
|
||||||
{
|
|
||||||
int nr;
|
|
||||||
char *buf = parsefile->buf;
|
|
||||||
parsenextc = buf;
|
|
||||||
|
|
||||||
retry:
|
|
||||||
#ifdef WITH_HISTORY
|
|
||||||
if (parsefile->fd == 0 && el) {
|
|
||||||
static const char *rl_cp;
|
|
||||||
static int el_len;
|
|
||||||
|
|
||||||
if (rl_cp == NULL)
|
|
||||||
rl_cp = el_gets(el, &el_len);
|
|
||||||
if (rl_cp == NULL)
|
|
||||||
nr = 0;
|
|
||||||
else {
|
|
||||||
nr = el_len;
|
|
||||||
if (nr > BUFSIZ - 8)
|
|
||||||
nr = BUFSIZ - 8;
|
|
||||||
memcpy(buf, rl_cp, nr);
|
|
||||||
if (nr != el_len) {
|
|
||||||
el_len -= nr;
|
|
||||||
rl_cp += nr;
|
|
||||||
} else
|
|
||||||
rl_cp = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
} else
|
|
||||||
#endif
|
|
||||||
#ifdef WITH_LINENOISE
|
|
||||||
if (parsefile->fd == 0) {
|
|
||||||
static char *rl_start;
|
|
||||||
static const char *rl_cp;
|
|
||||||
static int el_len;
|
|
||||||
|
|
||||||
if (rl_cp == NULL) {
|
|
||||||
rl_cp = rl_start = linenoise(getprompt(""));
|
|
||||||
if (rl_cp != NULL) {
|
|
||||||
el_len = strlen(rl_start);
|
|
||||||
if (el_len != 0) {
|
|
||||||
/* Add non-blank lines to history. */
|
|
||||||
linenoiseHistoryAdd(rl_start);
|
|
||||||
}
|
|
||||||
out2str("\n");
|
|
||||||
/* Client expects a newline at end of input, doesn't expect null */
|
|
||||||
rl_start[el_len++] = '\n';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (rl_cp == NULL)
|
|
||||||
nr = 0;
|
|
||||||
else {
|
|
||||||
nr = el_len;
|
|
||||||
if (nr > BUFSIZ - 8)
|
|
||||||
nr = BUFSIZ - 8;
|
|
||||||
memcpy(buf, rl_cp, nr);
|
|
||||||
if (nr != el_len) {
|
|
||||||
el_len -= nr;
|
|
||||||
rl_cp += nr;
|
|
||||||
} else {
|
|
||||||
rl_cp = 0;
|
|
||||||
if (rl_start != NULL) {
|
|
||||||
free(rl_start);
|
|
||||||
rl_start = NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else
|
|
||||||
#endif
|
|
||||||
nr = read(parsefile->fd, buf, BUFSIZ - 8);
|
|
||||||
|
|
||||||
|
|
||||||
if (nr <= 0) {
|
|
||||||
if (nr < 0) {
|
|
||||||
if (errno == EINTR)
|
|
||||||
goto retry;
|
|
||||||
if (parsefile->fd == 0 && errno == EWOULDBLOCK) {
|
|
||||||
int flags = fcntl(0, F_GETFL, 0);
|
|
||||||
if (flags >= 0 && flags & O_NONBLOCK) {
|
|
||||||
flags &=~ O_NONBLOCK;
|
|
||||||
if (fcntl(0, F_SETFL, flags) >= 0) {
|
|
||||||
out2str("sh: turning off NDELAY mode\n");
|
|
||||||
goto retry;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
nr = -1;
|
|
||||||
}
|
|
||||||
return nr;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Refill the input buffer and return the next input character:
|
|
||||||
*
|
|
||||||
* 1) If a string was pushed back on the input, pop it;
|
|
||||||
* 2) If an EOF was pushed back (parsenleft == EOF_NLEFT) or we are reading
|
|
||||||
* from a string so we can't refill the buffer, return EOF.
|
|
||||||
* 3) If the is more stuff in this buffer, use it else call read to fill it.
|
|
||||||
* 4) Process input up to the next newline, deleting nul characters.
|
|
||||||
*/
|
|
||||||
|
|
||||||
int
|
|
||||||
preadbuffer(void)
|
|
||||||
{
|
|
||||||
char *p, *q;
|
|
||||||
int more;
|
|
||||||
int something;
|
|
||||||
char savec;
|
|
||||||
|
|
||||||
if (parsefile->strpush) {
|
|
||||||
popstring();
|
|
||||||
if (--parsenleft >= 0)
|
|
||||||
return (*parsenextc++);
|
|
||||||
}
|
|
||||||
if (parsenleft == EOF_NLEFT || parsefile->buf == NULL)
|
|
||||||
return PEOF;
|
|
||||||
flushout(&output);
|
|
||||||
flushout(&errout);
|
|
||||||
|
|
||||||
again:
|
|
||||||
if (parselleft <= 0) {
|
|
||||||
if ((parselleft = preadfd()) == -1) {
|
|
||||||
parselleft = parsenleft = EOF_NLEFT;
|
|
||||||
return PEOF;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
q = p = parsenextc;
|
|
||||||
|
|
||||||
/* delete nul characters */
|
|
||||||
something = 0;
|
|
||||||
for (more = 1; more;) {
|
|
||||||
switch (*p) {
|
|
||||||
case '\0':
|
|
||||||
p++; /* Skip nul */
|
|
||||||
goto check;
|
|
||||||
|
|
||||||
case '\t':
|
|
||||||
case ' ':
|
|
||||||
break;
|
|
||||||
|
|
||||||
case '\n':
|
|
||||||
parsenleft = q - parsenextc;
|
|
||||||
more = 0; /* Stop processing here */
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
something = 1;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
*q++ = *p++;
|
|
||||||
check:
|
|
||||||
if (--parselleft <= 0) {
|
|
||||||
parsenleft = q - parsenextc - 1;
|
|
||||||
if (parsenleft < 0)
|
|
||||||
goto again;
|
|
||||||
*q = '\0';
|
|
||||||
more = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
savec = *q;
|
|
||||||
*q = '\0';
|
|
||||||
|
|
||||||
#ifdef WITH_HISTORY
|
|
||||||
if (parsefile->fd == 0 && hist && something) {
|
|
||||||
HistEvent he;
|
|
||||||
INTOFF;
|
|
||||||
history(hist, &he, whichprompt == 1? H_ENTER : H_APPEND,
|
|
||||||
parsenextc);
|
|
||||||
INTON;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (vflag) {
|
|
||||||
out2str(parsenextc);
|
|
||||||
flushout(out2);
|
|
||||||
}
|
|
||||||
|
|
||||||
*q = savec;
|
|
||||||
|
|
||||||
return *parsenextc++;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Undo the last call to pgetc. Only one character may be pushed back.
|
|
||||||
* PEOF may be pushed back.
|
|
||||||
*/
|
|
||||||
|
|
||||||
void
|
|
||||||
pungetc(void)
|
|
||||||
{
|
|
||||||
parsenleft++;
|
|
||||||
parsenextc--;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Push a string back onto the input at this current parsefile level.
|
|
||||||
* We handle aliases this way.
|
|
||||||
*/
|
|
||||||
void
|
|
||||||
pushstring(char *s, int len, void *ap)
|
|
||||||
{
|
|
||||||
struct strpush *sp;
|
|
||||||
|
|
||||||
INTOFF;
|
|
||||||
/*dprintf("*** calling pushstring: %s, %d\n", s, len);*/
|
|
||||||
if (parsefile->strpush) {
|
|
||||||
sp = ckmalloc(sizeof (struct strpush));
|
|
||||||
sp->prev = parsefile->strpush;
|
|
||||||
parsefile->strpush = sp;
|
|
||||||
} else
|
|
||||||
sp = parsefile->strpush = &(parsefile->basestrpush);
|
|
||||||
sp->prevstring = parsenextc;
|
|
||||||
sp->prevnleft = parsenleft;
|
|
||||||
sp->prevlleft = parselleft;
|
|
||||||
sp->ap = (struct alias *)ap;
|
|
||||||
if (ap)
|
|
||||||
((struct alias *)ap)->flag |= ALIASINUSE;
|
|
||||||
parsenextc = s;
|
|
||||||
parsenleft = len;
|
|
||||||
INTON;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
popstring(void)
|
|
||||||
{
|
|
||||||
struct strpush *sp = parsefile->strpush;
|
|
||||||
|
|
||||||
INTOFF;
|
|
||||||
parsenextc = sp->prevstring;
|
|
||||||
parsenleft = sp->prevnleft;
|
|
||||||
parselleft = sp->prevlleft;
|
|
||||||
/*dprintf("*** calling popstring: restoring to '%s'\n", parsenextc);*/
|
|
||||||
if (sp->ap)
|
|
||||||
sp->ap->flag &= ~ALIASINUSE;
|
|
||||||
parsefile->strpush = sp->prev;
|
|
||||||
if (sp != &(parsefile->basestrpush))
|
|
||||||
ckfree(sp);
|
|
||||||
INTON;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Set the input to take input from a file. If push is set, push the
|
|
||||||
* old input onto the stack first.
|
|
||||||
*/
|
|
||||||
|
|
||||||
void
|
|
||||||
setinputfile(const char *fname, int push)
|
|
||||||
{
|
|
||||||
int fd;
|
|
||||||
int fd2;
|
|
||||||
|
|
||||||
INTOFF;
|
|
||||||
if ((fd = open(fname, O_RDONLY)) < 0)
|
|
||||||
error("Can't open %s", fname);
|
|
||||||
if (fd < 10) {
|
|
||||||
fd2 = copyfd(fd, 10);
|
|
||||||
close(fd);
|
|
||||||
if (fd2 < 0)
|
|
||||||
error("Out of file descriptors");
|
|
||||||
fd = fd2;
|
|
||||||
}
|
|
||||||
setinputfd(fd, push);
|
|
||||||
INTON;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Like setinputfile, but takes an open file descriptor. Call this with
|
|
||||||
* interrupts off.
|
|
||||||
*/
|
|
||||||
|
|
||||||
void
|
|
||||||
setinputfd(int fd, int push)
|
|
||||||
{
|
|
||||||
(void) fcntl(fd, F_SETFD, FD_CLOEXEC);
|
|
||||||
if (push) {
|
|
||||||
pushfile();
|
|
||||||
parsefile->buf = ckmalloc(BUFSIZ);
|
|
||||||
}
|
|
||||||
if (parsefile->fd > 0)
|
|
||||||
close(parsefile->fd);
|
|
||||||
parsefile->fd = fd;
|
|
||||||
if (parsefile->buf == NULL)
|
|
||||||
parsefile->buf = ckmalloc(BUFSIZ);
|
|
||||||
parselleft = parsenleft = 0;
|
|
||||||
plinno = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Like setinputfile, but takes input from a string.
|
|
||||||
*/
|
|
||||||
|
|
||||||
void
|
|
||||||
setinputstring(char *string, int push)
|
|
||||||
{
|
|
||||||
INTOFF;
|
|
||||||
if (push)
|
|
||||||
pushfile();
|
|
||||||
parsenextc = string;
|
|
||||||
parselleft = parsenleft = strlen(string);
|
|
||||||
parsefile->buf = NULL;
|
|
||||||
plinno = 1;
|
|
||||||
INTON;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* To handle the "." command, a stack of input files is used. Pushfile
|
|
||||||
* adds a new entry to the stack and popfile restores the previous level.
|
|
||||||
*/
|
|
||||||
|
|
||||||
STATIC void
|
|
||||||
pushfile(void)
|
|
||||||
{
|
|
||||||
struct parsefile *pf;
|
|
||||||
|
|
||||||
parsefile->nleft = parsenleft;
|
|
||||||
parsefile->lleft = parselleft;
|
|
||||||
parsefile->nextc = parsenextc;
|
|
||||||
parsefile->linno = plinno;
|
|
||||||
pf = (struct parsefile *)ckmalloc(sizeof (struct parsefile));
|
|
||||||
pf->prev = parsefile;
|
|
||||||
pf->fd = -1;
|
|
||||||
pf->strpush = NULL;
|
|
||||||
pf->basestrpush.prev = NULL;
|
|
||||||
parsefile = pf;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
popfile(void)
|
|
||||||
{
|
|
||||||
struct parsefile *pf = parsefile;
|
|
||||||
|
|
||||||
INTOFF;
|
|
||||||
if (pf->fd >= 0)
|
|
||||||
close(pf->fd);
|
|
||||||
if (pf->buf)
|
|
||||||
ckfree(pf->buf);
|
|
||||||
while (pf->strpush)
|
|
||||||
popstring();
|
|
||||||
parsefile = pf->prev;
|
|
||||||
ckfree(pf);
|
|
||||||
parsenleft = parsefile->nleft;
|
|
||||||
parselleft = parsefile->lleft;
|
|
||||||
parsenextc = parsefile->nextc;
|
|
||||||
plinno = parsefile->linno;
|
|
||||||
INTON;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Return to top level.
|
|
||||||
*/
|
|
||||||
|
|
||||||
void
|
|
||||||
popallfiles(void)
|
|
||||||
{
|
|
||||||
while (parsefile != &basepf)
|
|
||||||
popfile();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Close the file(s) that the shell is reading commands from. Called
|
|
||||||
* after a fork is done.
|
|
||||||
*
|
|
||||||
* Takes one arg, vfork, which tells it to not modify its global vars
|
|
||||||
* as it is still running in the parent.
|
|
||||||
*
|
|
||||||
* This code is (probably) unnecessary as the 'close on exec' flag is
|
|
||||||
* set and should be enough. In the vfork case it is definitely wrong
|
|
||||||
* to close the fds as another fork() may be done later to feed data
|
|
||||||
* from a 'here' document into a pipe and we don't want to close the
|
|
||||||
* pipe!
|
|
||||||
*/
|
|
||||||
|
|
||||||
void
|
|
||||||
closescript(int vforked)
|
|
||||||
{
|
|
||||||
if (vforked)
|
|
||||||
return;
|
|
||||||
popallfiles();
|
|
||||||
if (parsefile->fd > 0) {
|
|
||||||
close(parsefile->fd);
|
|
||||||
parsefile->fd = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
63
sh/input.h
63
sh/input.h
|
|
@ -1,63 +0,0 @@
|
||||||
/* $NetBSD: input.h,v 1.15 2003/08/07 09:05:33 agc Exp $ */
|
|
||||||
|
|
||||||
/*-
|
|
||||||
* Copyright (c) 1991, 1993
|
|
||||||
* The Regents of the University of California. All rights reserved.
|
|
||||||
*
|
|
||||||
* This code is derived from software contributed to Berkeley by
|
|
||||||
* Kenneth Almquist.
|
|
||||||
*
|
|
||||||
* Redistribution and use in source and binary forms, with or without
|
|
||||||
* modification, are permitted provided that the following conditions
|
|
||||||
* are met:
|
|
||||||
* 1. Redistributions of source code must retain the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer.
|
|
||||||
* 2. Redistributions in binary form must reproduce the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer in the
|
|
||||||
* documentation and/or other materials provided with the distribution.
|
|
||||||
* 3. Neither the name of the University nor the names of its contributors
|
|
||||||
* may be used to endorse or promote products derived from this software
|
|
||||||
* without specific prior written permission.
|
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
|
||||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
||||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
||||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
|
||||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
||||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
|
||||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
|
||||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
||||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
|
||||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
|
||||||
* SUCH DAMAGE.
|
|
||||||
*
|
|
||||||
* @(#)input.h 8.2 (Berkeley) 5/4/95
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* PEOF (the end of file marker) is defined in syntax.h */
|
|
||||||
|
|
||||||
/*
|
|
||||||
* The input line number. Input.c just defines this variable, and saves
|
|
||||||
* and restores it when files are pushed and popped. The user of this
|
|
||||||
* package must set its value.
|
|
||||||
*/
|
|
||||||
extern int plinno;
|
|
||||||
extern int parsenleft; /* number of characters left in input buffer */
|
|
||||||
extern char *parsenextc; /* next character in input buffer */
|
|
||||||
extern int init_editline; /* 0 == not setup, 1 == OK, -1 == failed */
|
|
||||||
|
|
||||||
int in_interactive_mode();
|
|
||||||
char *pfgets(char *, int);
|
|
||||||
int pgetc(void);
|
|
||||||
int preadbuffer(void);
|
|
||||||
void pungetc(void);
|
|
||||||
void pushstring(char *, int, void *);
|
|
||||||
void popstring(void);
|
|
||||||
void setinputfile(const char *, int);
|
|
||||||
void setinputfd(int, int);
|
|
||||||
void setinputstring(char *, int);
|
|
||||||
void popfile(void);
|
|
||||||
void popallfiles(void);
|
|
||||||
void closescript(int);
|
|
||||||
|
|
||||||
#define pgetc_macro() (--parsenleft >= 0? *parsenextc++ : preadbuffer())
|
|
||||||
106
sh/jobs.h
106
sh/jobs.h
|
|
@ -1,106 +0,0 @@
|
||||||
/* $NetBSD: jobs.h,v 1.19 2003/11/27 21:16:14 dsl Exp $ */
|
|
||||||
|
|
||||||
/*-
|
|
||||||
* Copyright (c) 1991, 1993
|
|
||||||
* The Regents of the University of California. All rights reserved.
|
|
||||||
*
|
|
||||||
* This code is derived from software contributed to Berkeley by
|
|
||||||
* Kenneth Almquist.
|
|
||||||
*
|
|
||||||
* Redistribution and use in source and binary forms, with or without
|
|
||||||
* modification, are permitted provided that the following conditions
|
|
||||||
* are met:
|
|
||||||
* 1. Redistributions of source code must retain the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer.
|
|
||||||
* 2. Redistributions in binary form must reproduce the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer in the
|
|
||||||
* documentation and/or other materials provided with the distribution.
|
|
||||||
* 3. Neither the name of the University nor the names of its contributors
|
|
||||||
* may be used to endorse or promote products derived from this software
|
|
||||||
* without specific prior written permission.
|
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
|
||||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
||||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
||||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
|
||||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
||||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
|
||||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
|
||||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
||||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
|
||||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
|
||||||
* SUCH DAMAGE.
|
|
||||||
*
|
|
||||||
* @(#)jobs.h 8.2 (Berkeley) 5/4/95
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "output.h"
|
|
||||||
|
|
||||||
/* Mode argument to forkshell. Don't change FORK_FG or FORK_BG. */
|
|
||||||
#define FORK_FG 0
|
|
||||||
#define FORK_BG 1
|
|
||||||
#define FORK_NOJOB 2
|
|
||||||
|
|
||||||
/* mode flags for showjob(s) */
|
|
||||||
#define SHOW_PGID 0x01 /* only show pgid - for jobs -p */
|
|
||||||
#define SHOW_MULTILINE 0x02 /* one line per process */
|
|
||||||
#define SHOW_PID 0x04 /* include process pid */
|
|
||||||
#define SHOW_CHANGED 0x08 /* only jobs whose state has changed */
|
|
||||||
#define SHOW_SIGNALLED 0x10 /* only if stopped/exited on signal */
|
|
||||||
#define SHOW_ISSIG 0x20 /* job was signalled */
|
|
||||||
#define SHOW_NO_FREE 0x40 /* do not free job */
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* A job structure contains information about a job. A job is either a
|
|
||||||
* single process or a set of processes contained in a pipeline. In the
|
|
||||||
* latter case, pidlist will be non-NULL, and will point to a -1 terminated
|
|
||||||
* array of pids.
|
|
||||||
*/
|
|
||||||
#define MAXCMDTEXT 200
|
|
||||||
|
|
||||||
struct procstat {
|
|
||||||
pid_t pid; /* process id */
|
|
||||||
int status; /* last process status from wait() */
|
|
||||||
char cmd[MAXCMDTEXT];/* text of command being run */
|
|
||||||
};
|
|
||||||
|
|
||||||
struct job {
|
|
||||||
struct procstat ps0; /* status of process */
|
|
||||||
struct procstat *ps; /* status or processes when more than one */
|
|
||||||
int nprocs; /* number of processes */
|
|
||||||
pid_t pgrp; /* process group of this job */
|
|
||||||
char state;
|
|
||||||
#define JOBRUNNING 0 /* at least one proc running */
|
|
||||||
#define JOBSTOPPED 1 /* all procs are stopped */
|
|
||||||
#define JOBDONE 2 /* all procs are completed */
|
|
||||||
char used; /* true if this entry is in used */
|
|
||||||
char changed; /* true if status has changed */
|
|
||||||
#if JOBS
|
|
||||||
char jobctl; /* job running under job control */
|
|
||||||
int prev_job; /* previous job index */
|
|
||||||
#endif
|
|
||||||
};
|
|
||||||
|
|
||||||
extern pid_t backgndpid; /* pid of last background process */
|
|
||||||
extern int job_warning; /* user was warned about stopped jobs */
|
|
||||||
|
|
||||||
void setjobctl(int);
|
|
||||||
int fgcmd(int, char **);
|
|
||||||
int bgcmd(int, char **);
|
|
||||||
int jobscmd(int, char **);
|
|
||||||
void showjobs(struct output *, int);
|
|
||||||
int waitcmd(int, char **);
|
|
||||||
int jobidcmd(int, char **);
|
|
||||||
struct job *makejob(union node *, int);
|
|
||||||
int forkshell(struct job *, union node *, int);
|
|
||||||
void forkchild(struct job *, union node *, int, int);
|
|
||||||
int forkparent(struct job *, union node *, int, pid_t);
|
|
||||||
int waitforjob(struct job *);
|
|
||||||
int stoppedjobs(void);
|
|
||||||
void commandtext(struct procstat *, union node *);
|
|
||||||
int getjobpgrp(const char *);
|
|
||||||
|
|
||||||
#if ! JOBS
|
|
||||||
#define setjobctl(on) /* do nothing */
|
|
||||||
#endif
|
|
||||||
47
sh/machdep.h
47
sh/machdep.h
|
|
@ -1,47 +0,0 @@
|
||||||
/* $NetBSD: machdep.h,v 1.11 2003/08/07 09:05:33 agc Exp $ */
|
|
||||||
|
|
||||||
/*-
|
|
||||||
* Copyright (c) 1991, 1993
|
|
||||||
* The Regents of the University of California. All rights reserved.
|
|
||||||
*
|
|
||||||
* This code is derived from software contributed to Berkeley by
|
|
||||||
* Kenneth Almquist.
|
|
||||||
*
|
|
||||||
* Redistribution and use in source and binary forms, with or without
|
|
||||||
* modification, are permitted provided that the following conditions
|
|
||||||
* are met:
|
|
||||||
* 1. Redistributions of source code must retain the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer.
|
|
||||||
* 2. Redistributions in binary form must reproduce the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer in the
|
|
||||||
* documentation and/or other materials provided with the distribution.
|
|
||||||
* 3. Neither the name of the University nor the names of its contributors
|
|
||||||
* may be used to endorse or promote products derived from this software
|
|
||||||
* without specific prior written permission.
|
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
|
||||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
||||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
||||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
|
||||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
||||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
|
||||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
|
||||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
||||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
|
||||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
|
||||||
* SUCH DAMAGE.
|
|
||||||
*
|
|
||||||
* @(#)machdep.h 8.2 (Berkeley) 5/4/95
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Most machines require the value returned from malloc to be aligned
|
|
||||||
* in some way. The following macro will get this right on many machines.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#define SHELL_SIZE (sizeof(union {int i; char *cp; double d; }) - 1)
|
|
||||||
/*
|
|
||||||
* It appears that grabstackstr() will barf with such alignments
|
|
||||||
* because stalloc() will return a string allocated in a new stackblock.
|
|
||||||
*/
|
|
||||||
#define SHELL_ALIGN(nbytes) (((nbytes) + SHELL_SIZE) & ~SHELL_SIZE)
|
|
||||||
394
sh/main.c
394
sh/main.c
|
|
@ -1,394 +0,0 @@
|
||||||
/* $NetBSD: main.c,v 1.48 2003/09/14 12:09:29 jmmv Exp $ */
|
|
||||||
|
|
||||||
/*-
|
|
||||||
* Copyright (c) 1991, 1993
|
|
||||||
* The Regents of the University of California. All rights reserved.
|
|
||||||
*
|
|
||||||
* This code is derived from software contributed to Berkeley by
|
|
||||||
* Kenneth Almquist.
|
|
||||||
*
|
|
||||||
* Redistribution and use in source and binary forms, with or without
|
|
||||||
* modification, are permitted provided that the following conditions
|
|
||||||
* are met:
|
|
||||||
* 1. Redistributions of source code must retain the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer.
|
|
||||||
* 2. Redistributions in binary form must reproduce the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer in the
|
|
||||||
* documentation and/or other materials provided with the distribution.
|
|
||||||
* 3. Neither the name of the University nor the names of its contributors
|
|
||||||
* may be used to endorse or promote products derived from this software
|
|
||||||
* without specific prior written permission.
|
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
|
||||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
||||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
||||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
|
||||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
||||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
|
||||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
|
||||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
||||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
|
||||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
|
||||||
* SUCH DAMAGE.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <sys/cdefs.h>
|
|
||||||
#ifndef lint
|
|
||||||
__COPYRIGHT("@(#) Copyright (c) 1991, 1993\n\
|
|
||||||
The Regents of the University of California. All rights reserved.\n");
|
|
||||||
#endif /* not lint */
|
|
||||||
|
|
||||||
#ifndef lint
|
|
||||||
#if 0
|
|
||||||
static char sccsid[] = "@(#)main.c 8.7 (Berkeley) 7/19/95";
|
|
||||||
#else
|
|
||||||
__RCSID("$NetBSD: main.c,v 1.48 2003/09/14 12:09:29 jmmv Exp $");
|
|
||||||
#endif
|
|
||||||
#endif /* not lint */
|
|
||||||
|
|
||||||
#include <errno.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <signal.h>
|
|
||||||
#include <sys/stat.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <fcntl.h>
|
|
||||||
|
|
||||||
|
|
||||||
#include "shell.h"
|
|
||||||
#include "main.h"
|
|
||||||
#include "options.h"
|
|
||||||
#include "output.h"
|
|
||||||
#include "parser.h"
|
|
||||||
#include "nodes.h"
|
|
||||||
#include "expand.h"
|
|
||||||
#include "eval.h"
|
|
||||||
#include "jobs.h"
|
|
||||||
#include "input.h"
|
|
||||||
#include "trap.h"
|
|
||||||
#include "var.h"
|
|
||||||
#include "show.h"
|
|
||||||
#include "memalloc.h"
|
|
||||||
#include "error.h"
|
|
||||||
#include "init.h"
|
|
||||||
#include "mystring.h"
|
|
||||||
#include "exec.h"
|
|
||||||
#include "cd.h"
|
|
||||||
|
|
||||||
#define PROFILE 0
|
|
||||||
|
|
||||||
int rootpid;
|
|
||||||
int rootshell;
|
|
||||||
STATIC union node *curcmd;
|
|
||||||
STATIC union node *prevcmd;
|
|
||||||
#if PROFILE
|
|
||||||
short profile_buf[16384];
|
|
||||||
extern int etext();
|
|
||||||
#endif
|
|
||||||
|
|
||||||
STATIC void read_profile(const char *);
|
|
||||||
STATIC char *find_dot_file(char *);
|
|
||||||
int main(int, char **);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Main routine. We initialize things, parse the arguments, execute
|
|
||||||
* profiles if we're a login shell, and then call cmdloop to execute
|
|
||||||
* commands. The setjmp call sets up the location to jump to when an
|
|
||||||
* exception occurs. When an exception occurs the variable "state"
|
|
||||||
* is used to figure out how far we had gotten.
|
|
||||||
*/
|
|
||||||
|
|
||||||
int
|
|
||||||
main(int argc, char **argv)
|
|
||||||
{
|
|
||||||
struct jmploc jmploc;
|
|
||||||
struct stackmark smark;
|
|
||||||
volatile int state;
|
|
||||||
char *shinit;
|
|
||||||
|
|
||||||
#if PROFILE
|
|
||||||
monitor(4, etext, profile_buf, sizeof profile_buf, 50);
|
|
||||||
#endif
|
|
||||||
state = 0;
|
|
||||||
if (setjmp(jmploc.loc)) {
|
|
||||||
/*
|
|
||||||
* When a shell procedure is executed, we raise the
|
|
||||||
* exception EXSHELLPROC to clean up before executing
|
|
||||||
* the shell procedure.
|
|
||||||
*/
|
|
||||||
switch (exception) {
|
|
||||||
case EXSHELLPROC:
|
|
||||||
rootpid = getpid();
|
|
||||||
rootshell = 1;
|
|
||||||
minusc = NULL;
|
|
||||||
state = 3;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case EXEXEC:
|
|
||||||
exitstatus = exerrno;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case EXERROR:
|
|
||||||
exitstatus = 2;
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (exception != EXSHELLPROC) {
|
|
||||||
if (state == 0 || iflag == 0 || ! rootshell)
|
|
||||||
exitshell(exitstatus);
|
|
||||||
}
|
|
||||||
reset();
|
|
||||||
if (exception == EXINT
|
|
||||||
#if ATTY
|
|
||||||
&& (! attyset() || equal(termval(), "emacs"))
|
|
||||||
#endif
|
|
||||||
) {
|
|
||||||
out2c('\n');
|
|
||||||
flushout(&errout);
|
|
||||||
}
|
|
||||||
popstackmark(&smark);
|
|
||||||
FORCEINTON; /* enable interrupts */
|
|
||||||
if (state == 1)
|
|
||||||
goto state1;
|
|
||||||
else if (state == 2)
|
|
||||||
goto state2;
|
|
||||||
else if (state == 3)
|
|
||||||
goto state3;
|
|
||||||
else
|
|
||||||
goto state4;
|
|
||||||
}
|
|
||||||
handler = &jmploc;
|
|
||||||
#ifdef DEBUG
|
|
||||||
#if DEBUG == 2
|
|
||||||
debug = 1;
|
|
||||||
#endif
|
|
||||||
opentrace();
|
|
||||||
trputs("Shell args: "); trargs(argv);
|
|
||||||
#endif
|
|
||||||
rootpid = getpid();
|
|
||||||
rootshell = 1;
|
|
||||||
init();
|
|
||||||
setstackmark(&smark);
|
|
||||||
procargs(argc, argv);
|
|
||||||
if (argv[0] && argv[0][0] == '-') {
|
|
||||||
state = 1;
|
|
||||||
read_profile("/etc/profile");
|
|
||||||
state1:
|
|
||||||
state = 2;
|
|
||||||
read_profile(".profile");
|
|
||||||
}
|
|
||||||
state2:
|
|
||||||
state = 3;
|
|
||||||
if (getuid() == geteuid() && getgid() == getegid()) {
|
|
||||||
if ((shinit = lookupvar("ENV")) != NULL && *shinit != '\0') {
|
|
||||||
state = 3;
|
|
||||||
read_profile(shinit);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
state3:
|
|
||||||
state = 4;
|
|
||||||
if (sflag == 0 || minusc) {
|
|
||||||
static int sigs[] = {
|
|
||||||
SIGINT, SIGQUIT, SIGHUP,
|
|
||||||
#ifdef SIGTSTP
|
|
||||||
SIGTSTP,
|
|
||||||
#endif
|
|
||||||
SIGPIPE
|
|
||||||
};
|
|
||||||
#define SIGSSIZE (sizeof(sigs)/sizeof(sigs[0]))
|
|
||||||
int i;
|
|
||||||
|
|
||||||
for (i = 0; i < SIGSSIZE; i++)
|
|
||||||
setsignal(sigs[i], 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (minusc)
|
|
||||||
evalstring(minusc, 0);
|
|
||||||
|
|
||||||
if (sflag || minusc == NULL) {
|
|
||||||
state4: /* XXX ??? - why isn't this before the "if" statement */
|
|
||||||
cmdloop(1);
|
|
||||||
}
|
|
||||||
#if PROFILE
|
|
||||||
monitor(0);
|
|
||||||
#endif
|
|
||||||
exitshell(exitstatus);
|
|
||||||
/* NOTREACHED */
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Read and execute commands. "Top" is nonzero for the top level command
|
|
||||||
* loop; it turns on prompting if the shell is interactive.
|
|
||||||
*/
|
|
||||||
|
|
||||||
void
|
|
||||||
cmdloop(int top)
|
|
||||||
{
|
|
||||||
union node *n;
|
|
||||||
struct stackmark smark;
|
|
||||||
int inter;
|
|
||||||
int numeof = 0;
|
|
||||||
|
|
||||||
TRACE(("cmdloop(%d) called\n", top));
|
|
||||||
setstackmark(&smark);
|
|
||||||
for (;;) {
|
|
||||||
if (pendingsigs)
|
|
||||||
dotrap();
|
|
||||||
inter = 0;
|
|
||||||
if (iflag && top) {
|
|
||||||
inter = 1;
|
|
||||||
showjobs(out2, SHOW_CHANGED);
|
|
||||||
flushout(&errout);
|
|
||||||
}
|
|
||||||
n = parsecmd(inter);
|
|
||||||
/* showtree(n); DEBUG */
|
|
||||||
if (n == NEOF) {
|
|
||||||
if (!top || numeof >= 50)
|
|
||||||
break;
|
|
||||||
if (!stoppedjobs()) {
|
|
||||||
if (!Iflag)
|
|
||||||
break;
|
|
||||||
out2str("\nUse \"exit\" to leave shell.\n");
|
|
||||||
}
|
|
||||||
numeof++;
|
|
||||||
} else if (n != NULL && nflag == 0) {
|
|
||||||
job_warning = (job_warning == 2) ? 1 : 0;
|
|
||||||
numeof = 0;
|
|
||||||
evaltree(n, 0);
|
|
||||||
}
|
|
||||||
popstackmark(&smark);
|
|
||||||
setstackmark(&smark);
|
|
||||||
if (evalskip == SKIPFILE) {
|
|
||||||
evalskip = 0;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
popstackmark(&smark);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Read /etc/profile or .profile. Return on error.
|
|
||||||
*/
|
|
||||||
|
|
||||||
STATIC void
|
|
||||||
read_profile(const char *name)
|
|
||||||
{
|
|
||||||
int fd;
|
|
||||||
int xflag_set = 0;
|
|
||||||
int vflag_set = 0;
|
|
||||||
|
|
||||||
INTOFF;
|
|
||||||
if ((fd = open(name, O_RDONLY)) >= 0)
|
|
||||||
setinputfd(fd, 1);
|
|
||||||
INTON;
|
|
||||||
if (fd < 0)
|
|
||||||
return;
|
|
||||||
/* -q turns off -x and -v just when executing init files */
|
|
||||||
if (qflag) {
|
|
||||||
if (xflag)
|
|
||||||
xflag = 0, xflag_set = 1;
|
|
||||||
if (vflag)
|
|
||||||
vflag = 0, vflag_set = 1;
|
|
||||||
}
|
|
||||||
cmdloop(0);
|
|
||||||
if (qflag) {
|
|
||||||
if (xflag_set)
|
|
||||||
xflag = 1;
|
|
||||||
if (vflag_set)
|
|
||||||
vflag = 1;
|
|
||||||
}
|
|
||||||
popfile();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Read a file containing shell functions.
|
|
||||||
*/
|
|
||||||
|
|
||||||
void
|
|
||||||
readcmdfile(char *name)
|
|
||||||
{
|
|
||||||
int fd;
|
|
||||||
|
|
||||||
INTOFF;
|
|
||||||
if ((fd = open(name, O_RDONLY)) >= 0)
|
|
||||||
setinputfd(fd, 1);
|
|
||||||
else
|
|
||||||
error("Can't open %s", name);
|
|
||||||
INTON;
|
|
||||||
cmdloop(0);
|
|
||||||
popfile();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Take commands from a file. To be compatible we should do a path
|
|
||||||
* search for the file, which is necessary to find sub-commands.
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
STATIC char *
|
|
||||||
find_dot_file(char *basename)
|
|
||||||
{
|
|
||||||
char *fullname;
|
|
||||||
const char *path = pathval();
|
|
||||||
struct stat statb;
|
|
||||||
|
|
||||||
/* don't try this for absolute or relative paths */
|
|
||||||
if (strchr(basename, '/'))
|
|
||||||
return basename;
|
|
||||||
|
|
||||||
while ((fullname = padvance(&path, basename)) != NULL) {
|
|
||||||
if ((stat(fullname, &statb) == 0) && S_ISREG(statb.st_mode)) {
|
|
||||||
/*
|
|
||||||
* Don't bother freeing here, since it will
|
|
||||||
* be freed by the caller.
|
|
||||||
*/
|
|
||||||
return fullname;
|
|
||||||
}
|
|
||||||
stunalloc(fullname);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* not found in the PATH */
|
|
||||||
error("%s: not found", basename);
|
|
||||||
/* NOTREACHED */
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
dotcmd(int argc, char **argv)
|
|
||||||
{
|
|
||||||
exitstatus = 0;
|
|
||||||
|
|
||||||
if (argc >= 2) { /* That's what SVR2 does */
|
|
||||||
char *fullname;
|
|
||||||
struct stackmark smark;
|
|
||||||
|
|
||||||
setstackmark(&smark);
|
|
||||||
fullname = find_dot_file(argv[1]);
|
|
||||||
setinputfile(fullname, 1);
|
|
||||||
commandname = fullname;
|
|
||||||
cmdloop(0);
|
|
||||||
popfile();
|
|
||||||
popstackmark(&smark);
|
|
||||||
}
|
|
||||||
return exitstatus;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int
|
|
||||||
exitcmd(int argc, char **argv)
|
|
||||||
{
|
|
||||||
if (stoppedjobs())
|
|
||||||
return 0;
|
|
||||||
if (argc > 1)
|
|
||||||
exitstatus = number(argv[1]);
|
|
||||||
exitshell(exitstatus);
|
|
||||||
/* NOTREACHED */
|
|
||||||
}
|
|
||||||
43
sh/main.h
43
sh/main.h
|
|
@ -1,43 +0,0 @@
|
||||||
/* $NetBSD: main.h,v 1.10 2003/08/07 09:05:34 agc Exp $ */
|
|
||||||
|
|
||||||
/*-
|
|
||||||
* Copyright (c) 1991, 1993
|
|
||||||
* The Regents of the University of California. All rights reserved.
|
|
||||||
*
|
|
||||||
* This code is derived from software contributed to Berkeley by
|
|
||||||
* Kenneth Almquist.
|
|
||||||
*
|
|
||||||
* Redistribution and use in source and binary forms, with or without
|
|
||||||
* modification, are permitted provided that the following conditions
|
|
||||||
* are met:
|
|
||||||
* 1. Redistributions of source code must retain the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer.
|
|
||||||
* 2. Redistributions in binary form must reproduce the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer in the
|
|
||||||
* documentation and/or other materials provided with the distribution.
|
|
||||||
* 3. Neither the name of the University nor the names of its contributors
|
|
||||||
* may be used to endorse or promote products derived from this software
|
|
||||||
* without specific prior written permission.
|
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
|
||||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
||||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
||||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
|
||||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
||||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
|
||||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
|
||||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
||||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
|
||||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
|
||||||
* SUCH DAMAGE.
|
|
||||||
*
|
|
||||||
* @(#)main.h 8.2 (Berkeley) 5/4/95
|
|
||||||
*/
|
|
||||||
|
|
||||||
extern int rootpid; /* pid of main shell */
|
|
||||||
extern int rootshell; /* true if we aren't a child of the main shell */
|
|
||||||
|
|
||||||
void readcmdfile(char *);
|
|
||||||
void cmdloop(int);
|
|
||||||
int dotcmd(int, char **);
|
|
||||||
int exitcmd(int, char **);
|
|
||||||
307
sh/memalloc.c
307
sh/memalloc.c
|
|
@ -1,307 +0,0 @@
|
||||||
/* $NetBSD: memalloc.c,v 1.28 2003/08/07 09:05:34 agc Exp $ */
|
|
||||||
|
|
||||||
/*-
|
|
||||||
* Copyright (c) 1991, 1993
|
|
||||||
* The Regents of the University of California. All rights reserved.
|
|
||||||
*
|
|
||||||
* This code is derived from software contributed to Berkeley by
|
|
||||||
* Kenneth Almquist.
|
|
||||||
*
|
|
||||||
* Redistribution and use in source and binary forms, with or without
|
|
||||||
* modification, are permitted provided that the following conditions
|
|
||||||
* are met:
|
|
||||||
* 1. Redistributions of source code must retain the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer.
|
|
||||||
* 2. Redistributions in binary form must reproduce the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer in the
|
|
||||||
* documentation and/or other materials provided with the distribution.
|
|
||||||
* 3. Neither the name of the University nor the names of its contributors
|
|
||||||
* may be used to endorse or promote products derived from this software
|
|
||||||
* without specific prior written permission.
|
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
|
||||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
||||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
||||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
|
||||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
||||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
|
||||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
|
||||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
||||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
|
||||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
|
||||||
* SUCH DAMAGE.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <sys/cdefs.h>
|
|
||||||
#ifndef lint
|
|
||||||
#if 0
|
|
||||||
static char sccsid[] = "@(#)memalloc.c 8.3 (Berkeley) 5/4/95";
|
|
||||||
#else
|
|
||||||
__RCSID("$NetBSD: memalloc.c,v 1.28 2003/08/07 09:05:34 agc Exp $");
|
|
||||||
#endif
|
|
||||||
#endif /* not lint */
|
|
||||||
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
|
|
||||||
#include "shell.h"
|
|
||||||
#include "output.h"
|
|
||||||
#include "memalloc.h"
|
|
||||||
#include "error.h"
|
|
||||||
#include "machdep.h"
|
|
||||||
#include "mystring.h"
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Like malloc, but returns an error when out of space.
|
|
||||||
*/
|
|
||||||
|
|
||||||
pointer
|
|
||||||
ckmalloc(int nbytes)
|
|
||||||
{
|
|
||||||
pointer p;
|
|
||||||
|
|
||||||
p = malloc(nbytes);
|
|
||||||
if (p == NULL)
|
|
||||||
error("Out of space");
|
|
||||||
return p;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Same for realloc.
|
|
||||||
*/
|
|
||||||
|
|
||||||
pointer
|
|
||||||
ckrealloc(pointer p, int nbytes)
|
|
||||||
{
|
|
||||||
p = realloc(p, nbytes);
|
|
||||||
if (p == NULL)
|
|
||||||
error("Out of space");
|
|
||||||
return p;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Make a copy of a string in safe storage.
|
|
||||||
*/
|
|
||||||
|
|
||||||
char *
|
|
||||||
savestr(const char *s)
|
|
||||||
{
|
|
||||||
char *p;
|
|
||||||
|
|
||||||
p = ckmalloc(strlen(s) + 1);
|
|
||||||
scopy(s, p);
|
|
||||||
return p;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Parse trees for commands are allocated in lifo order, so we use a stack
|
|
||||||
* to make this more efficient, and also to avoid all sorts of exception
|
|
||||||
* handling code to handle interrupts in the middle of a parse.
|
|
||||||
*
|
|
||||||
* The size 504 was chosen because the Ultrix malloc handles that size
|
|
||||||
* well.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#define MINSIZE 504 /* minimum size of a block */
|
|
||||||
|
|
||||||
struct stack_block {
|
|
||||||
struct stack_block *prev;
|
|
||||||
char space[MINSIZE];
|
|
||||||
};
|
|
||||||
|
|
||||||
struct stack_block stackbase;
|
|
||||||
struct stack_block *stackp = &stackbase;
|
|
||||||
struct stackmark *markp;
|
|
||||||
char *stacknxt = stackbase.space;
|
|
||||||
int stacknleft = MINSIZE;
|
|
||||||
int sstrnleft;
|
|
||||||
int herefd = -1;
|
|
||||||
|
|
||||||
pointer
|
|
||||||
stalloc(int nbytes)
|
|
||||||
{
|
|
||||||
char *p;
|
|
||||||
|
|
||||||
nbytes = SHELL_ALIGN(nbytes);
|
|
||||||
if (nbytes > stacknleft) {
|
|
||||||
int blocksize;
|
|
||||||
struct stack_block *sp;
|
|
||||||
|
|
||||||
blocksize = nbytes;
|
|
||||||
if (blocksize < MINSIZE)
|
|
||||||
blocksize = MINSIZE;
|
|
||||||
INTOFF;
|
|
||||||
sp = ckmalloc(sizeof(struct stack_block) - MINSIZE + blocksize);
|
|
||||||
sp->prev = stackp;
|
|
||||||
stacknxt = sp->space;
|
|
||||||
stacknleft = blocksize;
|
|
||||||
stackp = sp;
|
|
||||||
INTON;
|
|
||||||
}
|
|
||||||
p = stacknxt;
|
|
||||||
stacknxt += nbytes;
|
|
||||||
stacknleft -= nbytes;
|
|
||||||
return p;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
stunalloc(pointer p)
|
|
||||||
{
|
|
||||||
if (p == NULL) { /*DEBUG */
|
|
||||||
write(2, "stunalloc\n", 10);
|
|
||||||
abort();
|
|
||||||
}
|
|
||||||
stacknleft += stacknxt - (char *)p;
|
|
||||||
stacknxt = p;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
setstackmark(struct stackmark *mark)
|
|
||||||
{
|
|
||||||
mark->stackp = stackp;
|
|
||||||
mark->stacknxt = stacknxt;
|
|
||||||
mark->stacknleft = stacknleft;
|
|
||||||
mark->marknext = markp;
|
|
||||||
markp = mark;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
popstackmark(struct stackmark *mark)
|
|
||||||
{
|
|
||||||
struct stack_block *sp;
|
|
||||||
|
|
||||||
INTOFF;
|
|
||||||
markp = mark->marknext;
|
|
||||||
while (stackp != mark->stackp) {
|
|
||||||
sp = stackp;
|
|
||||||
stackp = sp->prev;
|
|
||||||
ckfree(sp);
|
|
||||||
}
|
|
||||||
stacknxt = mark->stacknxt;
|
|
||||||
stacknleft = mark->stacknleft;
|
|
||||||
INTON;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* When the parser reads in a string, it wants to stick the string on the
|
|
||||||
* stack and only adjust the stack pointer when it knows how big the
|
|
||||||
* string is. Stackblock (defined in stack.h) returns a pointer to a block
|
|
||||||
* of space on top of the stack and stackblocklen returns the length of
|
|
||||||
* this block. Growstackblock will grow this space by at least one byte,
|
|
||||||
* possibly moving it (like realloc). Grabstackblock actually allocates the
|
|
||||||
* part of the block that has been used.
|
|
||||||
*/
|
|
||||||
|
|
||||||
void
|
|
||||||
growstackblock(void)
|
|
||||||
{
|
|
||||||
int newlen = SHELL_ALIGN(stacknleft * 2 + 100);
|
|
||||||
|
|
||||||
if (stacknxt == stackp->space && stackp != &stackbase) {
|
|
||||||
struct stack_block *oldstackp;
|
|
||||||
struct stackmark *xmark;
|
|
||||||
struct stack_block *sp;
|
|
||||||
|
|
||||||
INTOFF;
|
|
||||||
oldstackp = stackp;
|
|
||||||
sp = stackp;
|
|
||||||
stackp = sp->prev;
|
|
||||||
sp = ckrealloc((pointer)sp,
|
|
||||||
sizeof(struct stack_block) - MINSIZE + newlen);
|
|
||||||
sp->prev = stackp;
|
|
||||||
stackp = sp;
|
|
||||||
stacknxt = sp->space;
|
|
||||||
stacknleft = newlen;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Stack marks pointing to the start of the old block
|
|
||||||
* must be relocated to point to the new block
|
|
||||||
*/
|
|
||||||
xmark = markp;
|
|
||||||
while (xmark != NULL && xmark->stackp == oldstackp) {
|
|
||||||
xmark->stackp = stackp;
|
|
||||||
xmark->stacknxt = stacknxt;
|
|
||||||
xmark->stacknleft = stacknleft;
|
|
||||||
xmark = xmark->marknext;
|
|
||||||
}
|
|
||||||
INTON;
|
|
||||||
} else {
|
|
||||||
char *oldspace = stacknxt;
|
|
||||||
int oldlen = stacknleft;
|
|
||||||
char *p = stalloc(newlen);
|
|
||||||
|
|
||||||
(void)memcpy(p, oldspace, oldlen);
|
|
||||||
stacknxt = p; /* free the space */
|
|
||||||
stacknleft += newlen; /* we just allocated */
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
grabstackblock(int len)
|
|
||||||
{
|
|
||||||
len = SHELL_ALIGN(len);
|
|
||||||
stacknxt += len;
|
|
||||||
stacknleft -= len;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* The following routines are somewhat easier to use than the above.
|
|
||||||
* The user declares a variable of type STACKSTR, which may be declared
|
|
||||||
* to be a register. The macro STARTSTACKSTR initializes things. Then
|
|
||||||
* the user uses the macro STPUTC to add characters to the string. In
|
|
||||||
* effect, STPUTC(c, p) is the same as *p++ = c except that the stack is
|
|
||||||
* grown as necessary. When the user is done, she can just leave the
|
|
||||||
* string there and refer to it using stackblock(). Or she can allocate
|
|
||||||
* the space for it using grabstackstr(). If it is necessary to allow
|
|
||||||
* someone else to use the stack temporarily and then continue to grow
|
|
||||||
* the string, the user should use grabstack to allocate the space, and
|
|
||||||
* then call ungrabstr(p) to return to the previous mode of operation.
|
|
||||||
*
|
|
||||||
* USTPUTC is like STPUTC except that it doesn't check for overflow.
|
|
||||||
* CHECKSTACKSPACE can be called before USTPUTC to ensure that there
|
|
||||||
* is space for at least one character.
|
|
||||||
*/
|
|
||||||
|
|
||||||
char *
|
|
||||||
growstackstr(void)
|
|
||||||
{
|
|
||||||
int len = stackblocksize();
|
|
||||||
if (herefd >= 0 && len >= 1024) {
|
|
||||||
xwrite(herefd, stackblock(), len);
|
|
||||||
sstrnleft = len - 1;
|
|
||||||
return stackblock();
|
|
||||||
}
|
|
||||||
growstackblock();
|
|
||||||
sstrnleft = stackblocksize() - len - 1;
|
|
||||||
return stackblock() + len;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Called from CHECKSTRSPACE.
|
|
||||||
*/
|
|
||||||
|
|
||||||
char *
|
|
||||||
makestrspace(void)
|
|
||||||
{
|
|
||||||
int len = stackblocksize() - sstrnleft;
|
|
||||||
growstackblock();
|
|
||||||
sstrnleft = stackblocksize() - len;
|
|
||||||
return stackblock() + len;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
ungrabstackstr(char *s, char *p)
|
|
||||||
{
|
|
||||||
stacknleft += stacknxt - s;
|
|
||||||
stacknxt = s;
|
|
||||||
sstrnleft = stacknleft - (p - s);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -1,77 +0,0 @@
|
||||||
/* $NetBSD: memalloc.h,v 1.14 2003/08/07 09:05:34 agc Exp $ */
|
|
||||||
|
|
||||||
/*-
|
|
||||||
* Copyright (c) 1991, 1993
|
|
||||||
* The Regents of the University of California. All rights reserved.
|
|
||||||
*
|
|
||||||
* This code is derived from software contributed to Berkeley by
|
|
||||||
* Kenneth Almquist.
|
|
||||||
*
|
|
||||||
* Redistribution and use in source and binary forms, with or without
|
|
||||||
* modification, are permitted provided that the following conditions
|
|
||||||
* are met:
|
|
||||||
* 1. Redistributions of source code must retain the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer.
|
|
||||||
* 2. Redistributions in binary form must reproduce the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer in the
|
|
||||||
* documentation and/or other materials provided with the distribution.
|
|
||||||
* 3. Neither the name of the University nor the names of its contributors
|
|
||||||
* may be used to endorse or promote products derived from this software
|
|
||||||
* without specific prior written permission.
|
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
|
||||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
||||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
||||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
|
||||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
||||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
|
||||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
|
||||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
||||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
|
||||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
|
||||||
* SUCH DAMAGE.
|
|
||||||
*
|
|
||||||
* @(#)memalloc.h 8.2 (Berkeley) 5/4/95
|
|
||||||
*/
|
|
||||||
|
|
||||||
struct stackmark {
|
|
||||||
struct stack_block *stackp;
|
|
||||||
char *stacknxt;
|
|
||||||
int stacknleft;
|
|
||||||
struct stackmark *marknext;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
extern char *stacknxt;
|
|
||||||
extern int stacknleft;
|
|
||||||
extern int sstrnleft;
|
|
||||||
extern int herefd;
|
|
||||||
|
|
||||||
pointer ckmalloc(int);
|
|
||||||
pointer ckrealloc(pointer, int);
|
|
||||||
char *savestr(const char *);
|
|
||||||
pointer stalloc(int);
|
|
||||||
void stunalloc(pointer);
|
|
||||||
void setstackmark(struct stackmark *);
|
|
||||||
void popstackmark(struct stackmark *);
|
|
||||||
void growstackblock(void);
|
|
||||||
void grabstackblock(int);
|
|
||||||
char *growstackstr(void);
|
|
||||||
char *makestrspace(void);
|
|
||||||
void ungrabstackstr(char *, char *);
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#define stackblock() stacknxt
|
|
||||||
#define stackblocksize() stacknleft
|
|
||||||
#define STARTSTACKSTR(p) p = stackblock(), sstrnleft = stackblocksize()
|
|
||||||
#define STPUTC(c, p) (--sstrnleft >= 0? (*p++ = (c)) : (p = growstackstr(), *p++ = (c)))
|
|
||||||
#define CHECKSTRSPACE(n, p) { if (sstrnleft < n) p = makestrspace(); }
|
|
||||||
#define USTPUTC(c, p) (--sstrnleft, *p++ = (c))
|
|
||||||
#define STACKSTRNUL(p) (sstrnleft == 0? (p = growstackstr(), *p = '\0') : (*p = '\0'))
|
|
||||||
#define STUNPUTC(p) (++sstrnleft, --p)
|
|
||||||
#define STTOPC(p) p[-1]
|
|
||||||
#define STADJUST(amount, p) (p += (amount), sstrnleft -= (amount))
|
|
||||||
#define grabstackstr(p) stalloc(stackblocksize() - sstrnleft)
|
|
||||||
|
|
||||||
#define ckfree(p) free((pointer)(p))
|
|
||||||
445
sh/miscbltin.c
445
sh/miscbltin.c
|
|
@ -1,445 +0,0 @@
|
||||||
/* $NetBSD: miscbltin.c,v 1.34.2.1 2005/04/07 11:34:20 tron Exp $ */
|
|
||||||
|
|
||||||
/*-
|
|
||||||
* Copyright (c) 1991, 1993
|
|
||||||
* The Regents of the University of California. All rights reserved.
|
|
||||||
*
|
|
||||||
* This code is derived from software contributed to Berkeley by
|
|
||||||
* Kenneth Almquist.
|
|
||||||
*
|
|
||||||
* Redistribution and use in source and binary forms, with or without
|
|
||||||
* modification, are permitted provided that the following conditions
|
|
||||||
* are met:
|
|
||||||
* 1. Redistributions of source code must retain the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer.
|
|
||||||
* 2. Redistributions in binary form must reproduce the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer in the
|
|
||||||
* documentation and/or other materials provided with the distribution.
|
|
||||||
* 3. Neither the name of the University nor the names of its contributors
|
|
||||||
* may be used to endorse or promote products derived from this software
|
|
||||||
* without specific prior written permission.
|
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
|
||||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
||||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
||||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
|
||||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
||||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
|
||||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
|
||||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
||||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
|
||||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
|
||||||
* SUCH DAMAGE.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <sys/cdefs.h>
|
|
||||||
#ifndef lint
|
|
||||||
#if 0
|
|
||||||
static char sccsid[] = "@(#)miscbltin.c 8.4 (Berkeley) 5/4/95";
|
|
||||||
#else
|
|
||||||
__RCSID("$NetBSD: miscbltin.c,v 1.34.2.1 2005/04/07 11:34:20 tron Exp $");
|
|
||||||
#endif
|
|
||||||
#endif /* not lint */
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Miscelaneous builtins.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <sys/types.h> /* quad_t */
|
|
||||||
#include <sys/param.h> /* BSD4_4 */
|
|
||||||
#include <sys/stat.h>
|
|
||||||
#include <sys/time.h>
|
|
||||||
#include <sys/resource.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <ctype.h>
|
|
||||||
#include <errno.h>
|
|
||||||
|
|
||||||
#include "shell.h"
|
|
||||||
#include "options.h"
|
|
||||||
#include "var.h"
|
|
||||||
#include "output.h"
|
|
||||||
#include "memalloc.h"
|
|
||||||
#include "error.h"
|
|
||||||
#include "miscbltin.h"
|
|
||||||
#include "mystring.h"
|
|
||||||
|
|
||||||
#undef rflag
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* The read builtin.
|
|
||||||
* Backslahes escape the next char unless -r is specified.
|
|
||||||
*
|
|
||||||
* This uses unbuffered input, which may be avoidable in some cases.
|
|
||||||
*
|
|
||||||
* Note that if IFS=' :' then read x y should work so that:
|
|
||||||
* 'a b' x='a', y='b'
|
|
||||||
* ' a b ' x='a', y='b'
|
|
||||||
* ':b' x='', y='b'
|
|
||||||
* ':' x='', y=''
|
|
||||||
* '::' x='', y=''
|
|
||||||
* ': :' x='', y=''
|
|
||||||
* ':::' x='', y='::'
|
|
||||||
* ':b c:' x='', y='b c:'
|
|
||||||
*/
|
|
||||||
|
|
||||||
int
|
|
||||||
readcmd(int argc, char **argv)
|
|
||||||
{
|
|
||||||
char **ap;
|
|
||||||
char c;
|
|
||||||
int rflag;
|
|
||||||
char *prompt;
|
|
||||||
const char *ifs;
|
|
||||||
char *p;
|
|
||||||
int startword;
|
|
||||||
int status;
|
|
||||||
int i;
|
|
||||||
int is_ifs;
|
|
||||||
int saveall = 0;
|
|
||||||
|
|
||||||
rflag = 0;
|
|
||||||
prompt = NULL;
|
|
||||||
while ((i = nextopt("p:r")) != '\0') {
|
|
||||||
if (i == 'p')
|
|
||||||
prompt = optionarg;
|
|
||||||
else
|
|
||||||
rflag = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (prompt && isatty(0)) {
|
|
||||||
out2str(prompt);
|
|
||||||
flushall();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (*(ap = argptr) == NULL)
|
|
||||||
error("arg count");
|
|
||||||
|
|
||||||
if ((ifs = bltinlookup("IFS", 1)) == NULL)
|
|
||||||
ifs = " \t\n";
|
|
||||||
|
|
||||||
status = 0;
|
|
||||||
startword = 2;
|
|
||||||
STARTSTACKSTR(p);
|
|
||||||
for (;;) {
|
|
||||||
if (read(0, &c, 1) != 1) {
|
|
||||||
status = 1;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (c == '\0')
|
|
||||||
continue;
|
|
||||||
if (c == '\\' && !rflag) {
|
|
||||||
if (read(0, &c, 1) != 1) {
|
|
||||||
status = 1;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (c != '\n')
|
|
||||||
STPUTC(c, p);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (c == '\n')
|
|
||||||
break;
|
|
||||||
if (strchr(ifs, c))
|
|
||||||
is_ifs = strchr(" \t\n", c) ? 1 : 2;
|
|
||||||
else
|
|
||||||
is_ifs = 0;
|
|
||||||
|
|
||||||
if (startword != 0) {
|
|
||||||
if (is_ifs == 1) {
|
|
||||||
/* Ignore leading IFS whitespace */
|
|
||||||
if (saveall)
|
|
||||||
STPUTC(c, p);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (is_ifs == 2 && startword == 1) {
|
|
||||||
/* Only one non-whitespace IFS per word */
|
|
||||||
startword = 2;
|
|
||||||
if (saveall)
|
|
||||||
STPUTC(c, p);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (is_ifs == 0) {
|
|
||||||
/* append this character to the current variable */
|
|
||||||
startword = 0;
|
|
||||||
if (saveall)
|
|
||||||
/* Not just a spare terminator */
|
|
||||||
saveall++;
|
|
||||||
STPUTC(c, p);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* end of variable... */
|
|
||||||
startword = is_ifs;
|
|
||||||
|
|
||||||
if (ap[1] == NULL) {
|
|
||||||
/* Last variable needs all IFS chars */
|
|
||||||
saveall++;
|
|
||||||
STPUTC(c, p);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
STACKSTRNUL(p);
|
|
||||||
setvar(*ap, stackblock(), 0);
|
|
||||||
ap++;
|
|
||||||
STARTSTACKSTR(p);
|
|
||||||
}
|
|
||||||
STACKSTRNUL(p);
|
|
||||||
|
|
||||||
/* Remove trailing IFS chars */
|
|
||||||
for (; stackblock() <= --p; *p = 0) {
|
|
||||||
if (!strchr(ifs, *p))
|
|
||||||
break;
|
|
||||||
if (strchr(" \t\n", *p))
|
|
||||||
/* Always remove whitespace */
|
|
||||||
continue;
|
|
||||||
if (saveall > 1)
|
|
||||||
/* Don't remove non-whitespace unless it was naked */
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
setvar(*ap, stackblock(), 0);
|
|
||||||
|
|
||||||
/* Set any remaining args to "" */
|
|
||||||
while (*++ap != NULL)
|
|
||||||
setvar(*ap, nullstr, 0);
|
|
||||||
return status;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
int
|
|
||||||
umaskcmd(int argc, char **argv)
|
|
||||||
{
|
|
||||||
char *ap;
|
|
||||||
int mask;
|
|
||||||
int i;
|
|
||||||
int symbolic_mode = 0;
|
|
||||||
|
|
||||||
while ((i = nextopt("S")) != '\0') {
|
|
||||||
symbolic_mode = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
INTOFF;
|
|
||||||
mask = umask(0);
|
|
||||||
umask(mask);
|
|
||||||
INTON;
|
|
||||||
|
|
||||||
if ((ap = *argptr) == NULL) {
|
|
||||||
if (symbolic_mode) {
|
|
||||||
char u[4], g[4], o[4];
|
|
||||||
|
|
||||||
i = 0;
|
|
||||||
if ((mask & S_IRUSR) == 0)
|
|
||||||
u[i++] = 'r';
|
|
||||||
if ((mask & S_IWUSR) == 0)
|
|
||||||
u[i++] = 'w';
|
|
||||||
if ((mask & S_IXUSR) == 0)
|
|
||||||
u[i++] = 'x';
|
|
||||||
u[i] = '\0';
|
|
||||||
|
|
||||||
i = 0;
|
|
||||||
if ((mask & S_IRGRP) == 0)
|
|
||||||
g[i++] = 'r';
|
|
||||||
if ((mask & S_IWGRP) == 0)
|
|
||||||
g[i++] = 'w';
|
|
||||||
if ((mask & S_IXGRP) == 0)
|
|
||||||
g[i++] = 'x';
|
|
||||||
g[i] = '\0';
|
|
||||||
|
|
||||||
i = 0;
|
|
||||||
if ((mask & S_IROTH) == 0)
|
|
||||||
o[i++] = 'r';
|
|
||||||
if ((mask & S_IWOTH) == 0)
|
|
||||||
o[i++] = 'w';
|
|
||||||
if ((mask & S_IXOTH) == 0)
|
|
||||||
o[i++] = 'x';
|
|
||||||
o[i] = '\0';
|
|
||||||
|
|
||||||
out1fmt("u=%s,g=%s,o=%s\n", u, g, o);
|
|
||||||
} else {
|
|
||||||
out1fmt("%.4o\n", mask);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (isdigit((unsigned char)*ap)) {
|
|
||||||
mask = 0;
|
|
||||||
do {
|
|
||||||
if (*ap >= '8' || *ap < '0')
|
|
||||||
error("Illegal number: %s", argv[1]);
|
|
||||||
mask = (mask << 3) + (*ap - '0');
|
|
||||||
} while (*++ap != '\0');
|
|
||||||
umask(mask);
|
|
||||||
} else
|
|
||||||
error("Illegal mode: %s", ap);
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
#if 1
|
|
||||||
/*
|
|
||||||
* ulimit builtin
|
|
||||||
*
|
|
||||||
* This code, originally by Doug Gwyn, Doug Kingston, Eric Gisin, and
|
|
||||||
* Michael Rendell was ripped from pdksh 5.0.8 and hacked for use with
|
|
||||||
* ash by J.T. Conklin.
|
|
||||||
*
|
|
||||||
* Public domain.
|
|
||||||
*/
|
|
||||||
|
|
||||||
struct limits {
|
|
||||||
const char *name;
|
|
||||||
int cmd;
|
|
||||||
int factor; /* multiply by to get rlim_{cur,max} values */
|
|
||||||
char option;
|
|
||||||
};
|
|
||||||
|
|
||||||
static const struct limits limits[] = {
|
|
||||||
#ifdef RLIMIT_CPU
|
|
||||||
{ "time(seconds)", RLIMIT_CPU, 1, 't' },
|
|
||||||
#endif
|
|
||||||
#ifdef RLIMIT_FSIZE
|
|
||||||
{ "file(blocks)", RLIMIT_FSIZE, 512, 'f' },
|
|
||||||
#endif
|
|
||||||
#ifdef RLIMIT_DATA
|
|
||||||
{ "data(kbytes)", RLIMIT_DATA, 1024, 'd' },
|
|
||||||
#endif
|
|
||||||
#ifdef RLIMIT_STACK
|
|
||||||
{ "stack(kbytes)", RLIMIT_STACK, 1024, 's' },
|
|
||||||
#endif
|
|
||||||
#ifdef RLIMIT_CORE
|
|
||||||
{ "coredump(blocks)", RLIMIT_CORE, 512, 'c' },
|
|
||||||
#endif
|
|
||||||
#ifdef RLIMIT_RSS
|
|
||||||
{ "memory(kbytes)", RLIMIT_RSS, 1024, 'm' },
|
|
||||||
#endif
|
|
||||||
#ifdef RLIMIT_MEMLOCK
|
|
||||||
{ "locked memory(kbytes)", RLIMIT_MEMLOCK, 1024, 'l' },
|
|
||||||
#endif
|
|
||||||
#ifdef RLIMIT_NPROC
|
|
||||||
{ "process(processes)", RLIMIT_NPROC, 1, 'p' },
|
|
||||||
#endif
|
|
||||||
#ifdef RLIMIT_NOFILE
|
|
||||||
{ "nofiles(descriptors)", RLIMIT_NOFILE, 1, 'n' },
|
|
||||||
#endif
|
|
||||||
#ifdef RLIMIT_VMEM
|
|
||||||
{ "vmemory(kbytes)", RLIMIT_VMEM, 1024, 'v' },
|
|
||||||
#endif
|
|
||||||
#ifdef RLIMIT_SWAP
|
|
||||||
{ "swap(kbytes)", RLIMIT_SWAP, 1024, 'w' },
|
|
||||||
#endif
|
|
||||||
#ifdef RLIMIT_SBSIZE
|
|
||||||
{ "sbsize(bytes)", RLIMIT_SBSIZE, 1, 'b' },
|
|
||||||
#endif
|
|
||||||
{ (char *) 0, 0, 0, '\0' }
|
|
||||||
};
|
|
||||||
|
|
||||||
int
|
|
||||||
ulimitcmd(int argc, char **argv)
|
|
||||||
{
|
|
||||||
int c;
|
|
||||||
rlim_t val = 0;
|
|
||||||
enum { SOFT = 0x1, HARD = 0x2 }
|
|
||||||
how = SOFT | HARD;
|
|
||||||
const struct limits *l;
|
|
||||||
int set, all = 0;
|
|
||||||
int optc, what;
|
|
||||||
struct rlimit limit;
|
|
||||||
|
|
||||||
what = 'f';
|
|
||||||
while ((optc = nextopt("HSabtfdsmcnpl")) != '\0')
|
|
||||||
switch (optc) {
|
|
||||||
case 'H':
|
|
||||||
how = HARD;
|
|
||||||
break;
|
|
||||||
case 'S':
|
|
||||||
how = SOFT;
|
|
||||||
break;
|
|
||||||
case 'a':
|
|
||||||
all = 1;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
what = optc;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (l = limits; l->name && l->option != what; l++)
|
|
||||||
;
|
|
||||||
if (!l->name)
|
|
||||||
error("internal error (%c)", what);
|
|
||||||
|
|
||||||
set = *argptr ? 1 : 0;
|
|
||||||
if (set) {
|
|
||||||
char *p = *argptr;
|
|
||||||
|
|
||||||
if (all || argptr[1])
|
|
||||||
error("too many arguments");
|
|
||||||
if (strcmp(p, "unlimited") == 0)
|
|
||||||
val = RLIM_INFINITY;
|
|
||||||
else {
|
|
||||||
val = (rlim_t) 0;
|
|
||||||
|
|
||||||
while ((c = *p++) >= '0' && c <= '9')
|
|
||||||
{
|
|
||||||
val = (val * 10) + (long)(c - '0');
|
|
||||||
if ((long)val < 0)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (c)
|
|
||||||
error("bad number");
|
|
||||||
val *= l->factor;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (all) {
|
|
||||||
for (l = limits; l->name; l++) {
|
|
||||||
getrlimit(l->cmd, &limit);
|
|
||||||
if (how & SOFT)
|
|
||||||
val = limit.rlim_cur;
|
|
||||||
else if (how & HARD)
|
|
||||||
val = limit.rlim_max;
|
|
||||||
|
|
||||||
out1fmt("%-20s ", l->name);
|
|
||||||
if (val == RLIM_INFINITY)
|
|
||||||
out1fmt("unlimited\n");
|
|
||||||
else
|
|
||||||
{
|
|
||||||
val /= l->factor;
|
|
||||||
#ifdef BSD4_4
|
|
||||||
out1fmt("%lld\n", (long long) val);
|
|
||||||
#else
|
|
||||||
out1fmt("%ld\n", (long) val);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
getrlimit(l->cmd, &limit);
|
|
||||||
if (set) {
|
|
||||||
if (how & HARD)
|
|
||||||
limit.rlim_max = val;
|
|
||||||
if (how & SOFT)
|
|
||||||
limit.rlim_cur = val;
|
|
||||||
if (setrlimit(l->cmd, &limit) < 0)
|
|
||||||
error("error setting limit (%s)", strerror(errno));
|
|
||||||
} else {
|
|
||||||
if (how & SOFT)
|
|
||||||
val = limit.rlim_cur;
|
|
||||||
else if (how & HARD)
|
|
||||||
val = limit.rlim_max;
|
|
||||||
|
|
||||||
if (val == RLIM_INFINITY)
|
|
||||||
out1fmt("unlimited\n");
|
|
||||||
else
|
|
||||||
{
|
|
||||||
val /= l->factor;
|
|
||||||
#ifdef BSD4_4
|
|
||||||
out1fmt("%lld\n", (long long) val);
|
|
||||||
#else
|
|
||||||
out1fmt("%ld\n", (long) val);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
@ -1,31 +0,0 @@
|
||||||
/* $NetBSD: miscbltin.h,v 1.3 2003/08/21 17:57:53 christos Exp $ */
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Copyright (c) 1997 Christos Zoulas. All rights reserved.
|
|
||||||
*
|
|
||||||
* Redistribution and use in source and binary forms, with or without
|
|
||||||
* modification, are permitted provided that the following conditions
|
|
||||||
* are met:
|
|
||||||
* 1. Redistributions of source code must retain the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer.
|
|
||||||
* 2. Redistributions in binary form must reproduce the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer in the
|
|
||||||
* documentation and/or other materials provided with the distribution.
|
|
||||||
* 3. The name of the author may not be used to endorse or promote products
|
|
||||||
* derived from this software without specific prior written permission.
|
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
|
||||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
|
||||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
|
||||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
|
||||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
|
||||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
||||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
||||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
||||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
|
||||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
*/
|
|
||||||
|
|
||||||
int readcmd(int, char **);
|
|
||||||
int umaskcmd(int, char **);
|
|
||||||
int ulimitcmd(int, char **);
|
|
||||||
136
sh/mkbuiltins
136
sh/mkbuiltins
|
|
@ -1,136 +0,0 @@
|
||||||
#!/bin/sh -
|
|
||||||
# $NetBSD: mkbuiltins,v 1.21 2004/06/06 07:03:11 christos Exp $
|
|
||||||
#
|
|
||||||
# Copyright (c) 1991, 1993
|
|
||||||
# The Regents of the University of California. All rights reserved.
|
|
||||||
#
|
|
||||||
# This code is derived from software contributed to Berkeley by
|
|
||||||
# Kenneth Almquist.
|
|
||||||
#
|
|
||||||
# Redistribution and use in source and binary forms, with or without
|
|
||||||
# modification, are permitted provided that the following conditions
|
|
||||||
# are met:
|
|
||||||
# 1. Redistributions of source code must retain the above copyright
|
|
||||||
# notice, this list of conditions and the following disclaimer.
|
|
||||||
# 2. Redistributions in binary form must reproduce the above copyright
|
|
||||||
# notice, this list of conditions and the following disclaimer in the
|
|
||||||
# documentation and/or other materials provided with the distribution.
|
|
||||||
# 3. Neither the name of the University nor the names of its contributors
|
|
||||||
# may be used to endorse or promote products derived from this software
|
|
||||||
# without specific prior written permission.
|
|
||||||
#
|
|
||||||
# THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
|
||||||
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
||||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
||||||
# ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
|
||||||
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
||||||
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
|
||||||
# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
|
||||||
# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
||||||
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
|
||||||
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
|
||||||
# SUCH DAMAGE.
|
|
||||||
#
|
|
||||||
# @(#)mkbuiltins 8.2 (Berkeley) 5/4/95
|
|
||||||
|
|
||||||
havehist=1
|
|
||||||
if [ "X$1" = "X-h" ]; then
|
|
||||||
havehist=0
|
|
||||||
shift
|
|
||||||
fi
|
|
||||||
|
|
||||||
shell=$1
|
|
||||||
builtins=$2
|
|
||||||
objdir=$3
|
|
||||||
|
|
||||||
havejobs=0
|
|
||||||
if grep '^#define JOBS[ ]*1' ${shell} > /dev/null
|
|
||||||
then
|
|
||||||
havejobs=1
|
|
||||||
fi
|
|
||||||
|
|
||||||
exec <$builtins 3> ${objdir}/builtins.c 4> ${objdir}/builtins.h
|
|
||||||
|
|
||||||
echo '/*
|
|
||||||
* This file was generated by the mkbuiltins program.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "shell.h"
|
|
||||||
#include "builtins.h"
|
|
||||||
|
|
||||||
const struct builtincmd builtincmd[] = {
|
|
||||||
' >&3
|
|
||||||
|
|
||||||
echo '/*
|
|
||||||
* This file was generated by the mkbuiltins program.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <sys/cdefs.h>
|
|
||||||
|
|
||||||
struct builtincmd {
|
|
||||||
const char *name;
|
|
||||||
int (*builtin)(int, char **);
|
|
||||||
};
|
|
||||||
|
|
||||||
extern const struct builtincmd builtincmd[];
|
|
||||||
extern const struct builtincmd splbltincmd[];
|
|
||||||
|
|
||||||
' >&4
|
|
||||||
|
|
||||||
specials=
|
|
||||||
|
|
||||||
while read line
|
|
||||||
do
|
|
||||||
set -- $line
|
|
||||||
[ -z "$1" ] && continue
|
|
||||||
case "$1" in
|
|
||||||
\#if*|\#def*|\#end*)
|
|
||||||
echo $line >&3
|
|
||||||
echo $line >&4
|
|
||||||
continue
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
l1="${line###}"
|
|
||||||
[ "$l1" != "$line" ] && continue
|
|
||||||
|
|
||||||
|
|
||||||
func=$1
|
|
||||||
shift
|
|
||||||
[ x"$1" = x'-j' ] && {
|
|
||||||
[ $havejobs = 0 ] && continue
|
|
||||||
shift
|
|
||||||
}
|
|
||||||
[ x"$1" = x'-h' ] && {
|
|
||||||
[ $havehist = 0 ] && continue
|
|
||||||
shift
|
|
||||||
}
|
|
||||||
echo 'int '"$func"'(int, char **);' >&4
|
|
||||||
while
|
|
||||||
[ $# != 0 -a "$1" != '#' ]
|
|
||||||
do
|
|
||||||
[ "$1" = '-s' ] && {
|
|
||||||
specials="$specials $2 $func"
|
|
||||||
shift 2
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
[ "$1" = '-u' ] && shift
|
|
||||||
echo ' { "'$1'", '"$func"' },' >&3
|
|
||||||
shift
|
|
||||||
done
|
|
||||||
done
|
|
||||||
|
|
||||||
echo ' { 0, 0 },' >&3
|
|
||||||
echo '};' >&3
|
|
||||||
echo >&3
|
|
||||||
echo 'const struct builtincmd splbltincmd[] = {' >&3
|
|
||||||
|
|
||||||
set -- $specials
|
|
||||||
while
|
|
||||||
[ $# != 0 ]
|
|
||||||
do
|
|
||||||
echo ' { "'$1'", '"$2"' },' >&3
|
|
||||||
shift 2
|
|
||||||
done
|
|
||||||
|
|
||||||
echo ' { 0, 0 },' >&3
|
|
||||||
echo "};" >&3
|
|
||||||
197
sh/mkinit.sh
197
sh/mkinit.sh
|
|
@ -1,197 +0,0 @@
|
||||||
#! /bin/sh
|
|
||||||
# $NetBSD: mkinit.sh,v 1.2 2004/06/15 23:09:54 dsl Exp $
|
|
||||||
|
|
||||||
# Copyright (c) 2003 The NetBSD Foundation, Inc.
|
|
||||||
# All rights reserved.
|
|
||||||
#
|
|
||||||
# This code is derived from software contributed to The NetBSD Foundation
|
|
||||||
# by David Laight.
|
|
||||||
#
|
|
||||||
# Redistribution and use in source and binary forms, with or without
|
|
||||||
# modification, are permitted provided that the following conditions
|
|
||||||
# are met:
|
|
||||||
# 1. Redistributions of source code must retain the above copyright
|
|
||||||
# notice, this list of conditions and the following disclaimer.
|
|
||||||
# 2. Redistributions in binary form must reproduce the above copyright
|
|
||||||
# notice, this list of conditions and the following disclaimer in the
|
|
||||||
# documentation and/or other materials provided with the distribution.
|
|
||||||
# 3. Neither the name of The NetBSD Foundation nor the names of its
|
|
||||||
# contributors may be used to endorse or promote products derived
|
|
||||||
# from this software without specific prior written permission.
|
|
||||||
#
|
|
||||||
# THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
|
|
||||||
# ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
|
||||||
# TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
|
||||||
# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
|
|
||||||
# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
|
||||||
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
|
||||||
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
|
||||||
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
|
||||||
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
|
||||||
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
|
||||||
# POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
|
|
||||||
srcs="$*"
|
|
||||||
|
|
||||||
nl='
|
|
||||||
'
|
|
||||||
openparen='('
|
|
||||||
backslash='\'
|
|
||||||
|
|
||||||
includes=' "shell.h" "mystring.h" "init.h" '
|
|
||||||
defines=
|
|
||||||
decles=
|
|
||||||
event_init=
|
|
||||||
event_reset=
|
|
||||||
event_shellproc=
|
|
||||||
|
|
||||||
for src in $srcs; do
|
|
||||||
exec <$src
|
|
||||||
decnl="$nl"
|
|
||||||
while IFS=; read -r line; do
|
|
||||||
[ "$line" = x ]
|
|
||||||
case "$line " in
|
|
||||||
INIT["{ "]* ) event=init;;
|
|
||||||
RESET["{ "]* ) event=reset;;
|
|
||||||
SHELLPROC["{ "]* ) event=shellproc;;
|
|
||||||
INCLUDE[\ \ ]* )
|
|
||||||
IFS=' '
|
|
||||||
set -- $line
|
|
||||||
# ignore duplicates
|
|
||||||
[ "${includes}" != "${includes%* $2 }" ] && continue
|
|
||||||
includes="$includes$2 "
|
|
||||||
continue
|
|
||||||
;;
|
|
||||||
MKINIT\ )
|
|
||||||
# struct declaration
|
|
||||||
decles="$decles$nl"
|
|
||||||
while
|
|
||||||
read -r line
|
|
||||||
decles="${decles}${line}${nl}"
|
|
||||||
[ "$line" != "};" ]
|
|
||||||
do
|
|
||||||
:
|
|
||||||
done
|
|
||||||
decnl="$nl"
|
|
||||||
continue
|
|
||||||
;;
|
|
||||||
MKINIT["{ "]* )
|
|
||||||
# strip initialiser
|
|
||||||
def=${line#MKINIT}
|
|
||||||
comment="${def#*;}"
|
|
||||||
def="${def%;$comment}"
|
|
||||||
def="${def%%=*}"
|
|
||||||
def="${def% }"
|
|
||||||
decles="${decles}${decnl}extern${def};${comment}${nl}"
|
|
||||||
decnl=
|
|
||||||
continue
|
|
||||||
;;
|
|
||||||
\#define[\ \ ]* )
|
|
||||||
IFS=' '
|
|
||||||
set -- $line
|
|
||||||
# Ignore those with arguments
|
|
||||||
[ "$2" = "${2##*$openparen}" ] || continue
|
|
||||||
# and multiline definitions
|
|
||||||
[ "$line" = "${line%$backslash}" ] || continue
|
|
||||||
defines="${defines}#undef $2${nl}${line}${nl}"
|
|
||||||
continue
|
|
||||||
;;
|
|
||||||
* ) continue;;
|
|
||||||
esac
|
|
||||||
# code for events
|
|
||||||
ev="${nl} /* from $src: */${nl} {${nl}"
|
|
||||||
while
|
|
||||||
read -r line
|
|
||||||
[ "$line" != "}" ]
|
|
||||||
do
|
|
||||||
# The C program indented by an extra 6 chars using
|
|
||||||
# tabs then spaces. I need to compare the output :-(
|
|
||||||
indent=6
|
|
||||||
while
|
|
||||||
l=${line# }
|
|
||||||
[ "$l" != "$line" ]
|
|
||||||
do
|
|
||||||
indent=$(($indent + 8))
|
|
||||||
line="$l"
|
|
||||||
done
|
|
||||||
while
|
|
||||||
l=${line# }
|
|
||||||
[ "$l" != "$line" ]
|
|
||||||
do
|
|
||||||
indent=$(($indent + 1))
|
|
||||||
line="$l"
|
|
||||||
done
|
|
||||||
[ -z "$line" -o "$line" != "${line###}" ] && indent=0
|
|
||||||
while
|
|
||||||
[ $indent -ge 8 ]
|
|
||||||
do
|
|
||||||
ev="$ev "
|
|
||||||
indent="$(($indent - 8))"
|
|
||||||
done
|
|
||||||
while
|
|
||||||
[ $indent -gt 0 ]
|
|
||||||
do
|
|
||||||
ev="$ev "
|
|
||||||
indent="$(($indent - 1))"
|
|
||||||
done
|
|
||||||
ev="${ev}${line}${nl}"
|
|
||||||
done
|
|
||||||
ev="${ev} }${nl}"
|
|
||||||
eval event_$event=\"\$event_$event\$ev\"
|
|
||||||
done
|
|
||||||
done
|
|
||||||
|
|
||||||
exec >init.c.tmp
|
|
||||||
|
|
||||||
echo "/*"
|
|
||||||
echo " * This file was generated by the mkinit program."
|
|
||||||
echo " */"
|
|
||||||
echo
|
|
||||||
|
|
||||||
IFS=' '
|
|
||||||
for f in $includes; do
|
|
||||||
echo "#include $f"
|
|
||||||
done
|
|
||||||
|
|
||||||
echo
|
|
||||||
echo
|
|
||||||
echo
|
|
||||||
echo "$defines"
|
|
||||||
echo
|
|
||||||
echo "$decles"
|
|
||||||
echo
|
|
||||||
echo
|
|
||||||
echo "/*"
|
|
||||||
echo " * Initialization code."
|
|
||||||
echo " */"
|
|
||||||
echo
|
|
||||||
echo "void"
|
|
||||||
echo "init() {"
|
|
||||||
echo "${event_init%$nl}"
|
|
||||||
echo "}"
|
|
||||||
echo
|
|
||||||
echo
|
|
||||||
echo
|
|
||||||
echo "/*"
|
|
||||||
echo " * This routine is called when an error or an interrupt occurs in an"
|
|
||||||
echo " * interactive shell and control is returned to the main command loop."
|
|
||||||
echo " */"
|
|
||||||
echo
|
|
||||||
echo "void"
|
|
||||||
echo "reset() {"
|
|
||||||
echo "${event_reset%$nl}"
|
|
||||||
echo "}"
|
|
||||||
echo
|
|
||||||
echo
|
|
||||||
echo
|
|
||||||
echo "/*"
|
|
||||||
echo " * This routine is called to initialize the shell to run a shell procedure."
|
|
||||||
echo " */"
|
|
||||||
echo
|
|
||||||
echo "void"
|
|
||||||
echo "initshellproc() {"
|
|
||||||
echo "${event_shellproc%$nl}"
|
|
||||||
echo "}"
|
|
||||||
|
|
||||||
exec >&-
|
|
||||||
mv init.c.tmp init.c
|
|
||||||
217
sh/mknodes.sh
217
sh/mknodes.sh
|
|
@ -1,217 +0,0 @@
|
||||||
#! /bin/sh
|
|
||||||
# $NetBSD: mknodes.sh,v 1.1 2004/01/16 23:24:38 dsl Exp $
|
|
||||||
|
|
||||||
# Copyright (c) 2003 The NetBSD Foundation, Inc.
|
|
||||||
# All rights reserved.
|
|
||||||
#
|
|
||||||
# This code is derived from software contributed to The NetBSD Foundation
|
|
||||||
# by David Laight.
|
|
||||||
#
|
|
||||||
# Redistribution and use in source and binary forms, with or without
|
|
||||||
# modification, are permitted provided that the following conditions
|
|
||||||
# are met:
|
|
||||||
# 1. Redistributions of source code must retain the above copyright
|
|
||||||
# notice, this list of conditions and the following disclaimer.
|
|
||||||
# 2. Redistributions in binary form must reproduce the above copyright
|
|
||||||
# notice, this list of conditions and the following disclaimer in the
|
|
||||||
# documentation and/or other materials provided with the distribution.
|
|
||||||
# 3. Neither the name of The NetBSD Foundation nor the names of its
|
|
||||||
# contributors may be used to endorse or promote products derived
|
|
||||||
# from this software without specific prior written permission.
|
|
||||||
#
|
|
||||||
# THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
|
|
||||||
# ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
|
||||||
# TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
|
||||||
# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
|
|
||||||
# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
|
||||||
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
|
||||||
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
|
||||||
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
|
||||||
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
|
||||||
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
|
||||||
# POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
|
|
||||||
nodetypes=$1
|
|
||||||
nodes_pat=$2
|
|
||||||
objdir="$3"
|
|
||||||
|
|
||||||
exec <$nodetypes
|
|
||||||
exec >$objdir/nodes.h.tmp
|
|
||||||
|
|
||||||
echo "/*"
|
|
||||||
echo " * This file was generated by mknodes.sh"
|
|
||||||
echo " */"
|
|
||||||
echo
|
|
||||||
|
|
||||||
tagno=0
|
|
||||||
while IFS=; read -r line; do
|
|
||||||
line="${line%%#*}"
|
|
||||||
IFS=' '
|
|
||||||
set -- $line
|
|
||||||
IFS=
|
|
||||||
[ -z "$2" ] && continue
|
|
||||||
case "$line" in
|
|
||||||
[" "]* )
|
|
||||||
IFS=' '
|
|
||||||
[ $field = 0 ] && struct_list="$struct_list $struct"
|
|
||||||
eval field_${struct}_$field=\"\$*\"
|
|
||||||
eval numfld_$struct=\$field
|
|
||||||
field=$(($field + 1))
|
|
||||||
;;
|
|
||||||
* )
|
|
||||||
define=$1
|
|
||||||
struct=$2
|
|
||||||
echo "#define $define $tagno"
|
|
||||||
tagno=$(($tagno + 1))
|
|
||||||
eval define_$struct=\"\$define_$struct \$define\"
|
|
||||||
struct_define="$struct_define $struct"
|
|
||||||
field=0
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
done
|
|
||||||
|
|
||||||
echo
|
|
||||||
|
|
||||||
IFS=' '
|
|
||||||
for struct in $struct_list; do
|
|
||||||
echo
|
|
||||||
echo
|
|
||||||
echo "struct $struct {"
|
|
||||||
field=0
|
|
||||||
while
|
|
||||||
eval line=\"\$field_${struct}_$field\"
|
|
||||||
field=$(($field + 1))
|
|
||||||
[ -n "$line" ]
|
|
||||||
do
|
|
||||||
IFS=' '
|
|
||||||
set -- $line
|
|
||||||
name=$1
|
|
||||||
case $2 in
|
|
||||||
nodeptr ) type="union node *";;
|
|
||||||
nodelist ) type="struct nodelist *";;
|
|
||||||
string ) type="char *";;
|
|
||||||
int ) type="int ";;
|
|
||||||
* ) name=; shift 2; type="$*";;
|
|
||||||
esac
|
|
||||||
echo " $type$name;"
|
|
||||||
done
|
|
||||||
echo "};"
|
|
||||||
done
|
|
||||||
|
|
||||||
echo
|
|
||||||
echo
|
|
||||||
echo "union node {"
|
|
||||||
echo " int type;"
|
|
||||||
for struct in $struct_list; do
|
|
||||||
echo " struct $struct $struct;"
|
|
||||||
done
|
|
||||||
echo "};"
|
|
||||||
echo
|
|
||||||
echo
|
|
||||||
echo "struct nodelist {"
|
|
||||||
echo " struct nodelist *next;"
|
|
||||||
echo " union node *n;"
|
|
||||||
echo "};"
|
|
||||||
echo
|
|
||||||
echo
|
|
||||||
echo "union node *copyfunc(union node *);"
|
|
||||||
echo "void freefunc(union node *);"
|
|
||||||
|
|
||||||
mv $objdir/nodes.h.tmp $objdir/nodes.h || exit 1
|
|
||||||
|
|
||||||
exec <$nodes_pat
|
|
||||||
exec >$objdir/nodes.c.tmp
|
|
||||||
|
|
||||||
echo "/*"
|
|
||||||
echo " * This file was generated by mknodes.sh"
|
|
||||||
echo " */"
|
|
||||||
echo
|
|
||||||
|
|
||||||
while IFS=; read -r line; do
|
|
||||||
IFS=' '
|
|
||||||
set -- $line
|
|
||||||
IFS=
|
|
||||||
case "$1" in
|
|
||||||
'%SIZES' )
|
|
||||||
echo "static const short nodesize[$tagno] = {"
|
|
||||||
IFS=' '
|
|
||||||
for struct in $struct_define; do
|
|
||||||
echo " SHELL_ALIGN(sizeof (struct $struct)),"
|
|
||||||
done
|
|
||||||
echo "};"
|
|
||||||
;;
|
|
||||||
'%CALCSIZE' )
|
|
||||||
echo " if (n == NULL)"
|
|
||||||
echo " return;"
|
|
||||||
echo " funcblocksize += nodesize[n->type];"
|
|
||||||
echo " switch (n->type) {"
|
|
||||||
IFS=' '
|
|
||||||
for struct in $struct_list; do
|
|
||||||
eval defines=\"\$define_$struct\"
|
|
||||||
for define in $defines; do
|
|
||||||
echo " case $define:"
|
|
||||||
done
|
|
||||||
eval field=\$numfld_$struct
|
|
||||||
while
|
|
||||||
[ $field != 0 ]
|
|
||||||
do
|
|
||||||
eval line=\"\$field_${struct}_$field\"
|
|
||||||
field=$(($field - 1))
|
|
||||||
IFS=' '
|
|
||||||
set -- $line
|
|
||||||
name=$1
|
|
||||||
cl=")"
|
|
||||||
case $2 in
|
|
||||||
nodeptr ) fn=calcsize;;
|
|
||||||
nodelist ) fn=sizenodelist;;
|
|
||||||
string ) fn="funcstringsize += strlen"
|
|
||||||
cl=") + 1";;
|
|
||||||
* ) continue;;
|
|
||||||
esac
|
|
||||||
echo " ${fn}(n->$struct.$name${cl};"
|
|
||||||
done
|
|
||||||
echo " break;"
|
|
||||||
done
|
|
||||||
echo " };"
|
|
||||||
;;
|
|
||||||
'%COPY' )
|
|
||||||
echo " if (n == NULL)"
|
|
||||||
echo " return NULL;"
|
|
||||||
echo " new = funcblock;"
|
|
||||||
echo " funcblock = (char *) funcblock + nodesize[n->type];"
|
|
||||||
echo " switch (n->type) {"
|
|
||||||
IFS=' '
|
|
||||||
for struct in $struct_list; do
|
|
||||||
eval defines=\"\$define_$struct\"
|
|
||||||
for define in $defines; do
|
|
||||||
echo " case $define:"
|
|
||||||
done
|
|
||||||
eval field=\$numfld_$struct
|
|
||||||
while
|
|
||||||
[ $field != 0 ]
|
|
||||||
do
|
|
||||||
eval line=\"\$field_${struct}_$field\"
|
|
||||||
field=$(($field - 1))
|
|
||||||
IFS=' '
|
|
||||||
set -- $line
|
|
||||||
name=$1
|
|
||||||
case $2 in
|
|
||||||
nodeptr ) fn="copynode(";;
|
|
||||||
nodelist ) fn="copynodelist(";;
|
|
||||||
string ) fn="nodesavestr(";;
|
|
||||||
int ) fn=;;
|
|
||||||
* ) continue;;
|
|
||||||
esac
|
|
||||||
f="$struct.$name"
|
|
||||||
echo " new->$f = ${fn}n->$f${fn:+)};"
|
|
||||||
done
|
|
||||||
echo " break;"
|
|
||||||
done
|
|
||||||
echo " };"
|
|
||||||
echo " new->type = n->type;"
|
|
||||||
;;
|
|
||||||
* ) echo "$line";;
|
|
||||||
esac
|
|
||||||
done
|
|
||||||
|
|
||||||
mv $objdir/nodes.c.tmp $objdir/nodes.c || exit 1
|
|
||||||
92
sh/mktokens
92
sh/mktokens
|
|
@ -1,92 +0,0 @@
|
||||||
#!/bin/sh -
|
|
||||||
# $NetBSD: mktokens,v 1.10 2003/08/22 11:22:23 agc Exp $
|
|
||||||
#
|
|
||||||
# Copyright (c) 1991, 1993
|
|
||||||
# The Regents of the University of California. All rights reserved.
|
|
||||||
#
|
|
||||||
# This code is derived from software contributed to Berkeley by
|
|
||||||
# Kenneth Almquist.
|
|
||||||
#
|
|
||||||
# Redistribution and use in source and binary forms, with or without
|
|
||||||
# modification, are permitted provided that the following conditions
|
|
||||||
# are met:
|
|
||||||
# 1. Redistributions of source code must retain the above copyright
|
|
||||||
# notice, this list of conditions and the following disclaimer.
|
|
||||||
# 2. Redistributions in binary form must reproduce the above copyright
|
|
||||||
# notice, this list of conditions and the following disclaimer in the
|
|
||||||
# documentation and/or other materials provided with the distribution.
|
|
||||||
# 3. Neither the name of the University nor the names of its contributors
|
|
||||||
# may be used to endorse or promote products derived from this software
|
|
||||||
# without specific prior written permission.
|
|
||||||
#
|
|
||||||
# THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
|
||||||
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
||||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
||||||
# ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
|
||||||
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
||||||
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
|
||||||
# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
|
||||||
# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
||||||
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
|
||||||
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
|
||||||
# SUCH DAMAGE.
|
|
||||||
#
|
|
||||||
# @(#)mktokens 8.1 (Berkeley) 5/31/93
|
|
||||||
|
|
||||||
# The following is a list of tokens. The second column is nonzero if the
|
|
||||||
# token marks the end of a list. The third column is the name to print in
|
|
||||||
# error messages.
|
|
||||||
|
|
||||||
cat > /tmp/ka$$ <<\!
|
|
||||||
TEOF 1 end of file
|
|
||||||
TNL 0 newline
|
|
||||||
TSEMI 0 ";"
|
|
||||||
TBACKGND 0 "&"
|
|
||||||
TAND 0 "&&"
|
|
||||||
TOR 0 "||"
|
|
||||||
TPIPE 0 "|"
|
|
||||||
TLP 0 "("
|
|
||||||
TRP 1 ")"
|
|
||||||
TENDCASE 1 ";;"
|
|
||||||
TENDBQUOTE 1 "`"
|
|
||||||
TREDIR 0 redirection
|
|
||||||
TWORD 0 word
|
|
||||||
TIF 0 "if"
|
|
||||||
TTHEN 1 "then"
|
|
||||||
TELSE 1 "else"
|
|
||||||
TELIF 1 "elif"
|
|
||||||
TFI 1 "fi"
|
|
||||||
TWHILE 0 "while"
|
|
||||||
TUNTIL 0 "until"
|
|
||||||
TFOR 0 "for"
|
|
||||||
TDO 1 "do"
|
|
||||||
TDONE 1 "done"
|
|
||||||
TBEGIN 0 "{"
|
|
||||||
TEND 1 "}"
|
|
||||||
TCASE 0 "case"
|
|
||||||
TESAC 1 "esac"
|
|
||||||
TNOT 0 "!"
|
|
||||||
!
|
|
||||||
nl=`wc -l /tmp/ka$$`
|
|
||||||
exec > token.h
|
|
||||||
awk '{print "#define " $1 " " NR-1}' /tmp/ka$$
|
|
||||||
echo '
|
|
||||||
/* Array indicating which tokens mark the end of a list */
|
|
||||||
const char tokendlist[] = {'
|
|
||||||
awk '{print "\t" $2 ","}' /tmp/ka$$
|
|
||||||
echo '};
|
|
||||||
|
|
||||||
const char *const tokname[] = {'
|
|
||||||
sed -e 's/"/\\"/g' \
|
|
||||||
-e 's/[^ ]*[ ][ ]*[^ ]*[ ][ ]*\(.*\)/ "\1",/' \
|
|
||||||
/tmp/ka$$
|
|
||||||
echo '};
|
|
||||||
'
|
|
||||||
sed 's/"//g' /tmp/ka$$ | awk '
|
|
||||||
/TIF/{print "#define KWDOFFSET " NR-1; print "";
|
|
||||||
print "const char *const parsekwd[] = {"}
|
|
||||||
/TIF/,/neverfound/{print " \"" $3 "\","}'
|
|
||||||
echo ' 0
|
|
||||||
};'
|
|
||||||
|
|
||||||
rm /tmp/ka$$
|
|
||||||
|
|
@ -1,49 +0,0 @@
|
||||||
/* $NetBSD: myhistedit.h,v 1.10 2003/08/07 09:05:35 agc Exp $ */
|
|
||||||
|
|
||||||
/*-
|
|
||||||
* Copyright (c) 1993
|
|
||||||
* The Regents of the University of California. All rights reserved.
|
|
||||||
*
|
|
||||||
* Redistribution and use in source and binary forms, with or without
|
|
||||||
* modification, are permitted provided that the following conditions
|
|
||||||
* are met:
|
|
||||||
* 1. Redistributions of source code must retain the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer.
|
|
||||||
* 2. Redistributions in binary form must reproduce the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer in the
|
|
||||||
* documentation and/or other materials provided with the distribution.
|
|
||||||
* 3. Neither the name of the University nor the names of its contributors
|
|
||||||
* may be used to endorse or promote products derived from this software
|
|
||||||
* without specific prior written permission.
|
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
|
||||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
||||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
||||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
|
||||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
||||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
|
||||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
|
||||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
||||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
|
||||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
|
||||||
* SUCH DAMAGE.
|
|
||||||
*
|
|
||||||
* @(#)myhistedit.h 8.2 (Berkeley) 5/4/95
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifdef WITH_HISTORY
|
|
||||||
#include <histedit.h>
|
|
||||||
|
|
||||||
extern History *hist;
|
|
||||||
extern EditLine *el;
|
|
||||||
extern int displayhist;
|
|
||||||
|
|
||||||
void histedit(void);
|
|
||||||
void sethistsize(const char *);
|
|
||||||
void setterm(const char *);
|
|
||||||
int histcmd(int, char **);
|
|
||||||
int inputrc(int, char **);
|
|
||||||
int not_fcnumber(char *);
|
|
||||||
int str_to_event(const char *, int);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
133
sh/mystring.c
133
sh/mystring.c
|
|
@ -1,133 +0,0 @@
|
||||||
/* $NetBSD: mystring.c,v 1.16 2003/08/07 09:05:35 agc Exp $ */
|
|
||||||
|
|
||||||
/*-
|
|
||||||
* Copyright (c) 1991, 1993
|
|
||||||
* The Regents of the University of California. All rights reserved.
|
|
||||||
*
|
|
||||||
* This code is derived from software contributed to Berkeley by
|
|
||||||
* Kenneth Almquist.
|
|
||||||
*
|
|
||||||
* Redistribution and use in source and binary forms, with or without
|
|
||||||
* modification, are permitted provided that the following conditions
|
|
||||||
* are met:
|
|
||||||
* 1. Redistributions of source code must retain the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer.
|
|
||||||
* 2. Redistributions in binary form must reproduce the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer in the
|
|
||||||
* documentation and/or other materials provided with the distribution.
|
|
||||||
* 3. Neither the name of the University nor the names of its contributors
|
|
||||||
* may be used to endorse or promote products derived from this software
|
|
||||||
* without specific prior written permission.
|
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
|
||||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
||||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
||||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
|
||||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
||||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
|
||||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
|
||||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
||||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
|
||||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
|
||||||
* SUCH DAMAGE.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <sys/cdefs.h>
|
|
||||||
#ifndef lint
|
|
||||||
#if 0
|
|
||||||
static char sccsid[] = "@(#)mystring.c 8.2 (Berkeley) 5/4/95";
|
|
||||||
#else
|
|
||||||
__RCSID("$NetBSD: mystring.c,v 1.16 2003/08/07 09:05:35 agc Exp $");
|
|
||||||
#endif
|
|
||||||
#endif /* not lint */
|
|
||||||
|
|
||||||
/*
|
|
||||||
* String functions.
|
|
||||||
*
|
|
||||||
* equal(s1, s2) Return true if strings are equal.
|
|
||||||
* scopy(from, to) Copy a string.
|
|
||||||
* scopyn(from, to, n) Like scopy, but checks for overflow.
|
|
||||||
* number(s) Convert a string of digits to an integer.
|
|
||||||
* is_number(s) Return true if s is a string of digits.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include "shell.h"
|
|
||||||
#include "syntax.h"
|
|
||||||
#include "error.h"
|
|
||||||
#include "mystring.h"
|
|
||||||
|
|
||||||
|
|
||||||
char nullstr[1]; /* zero length string */
|
|
||||||
|
|
||||||
/*
|
|
||||||
* equal - #defined in mystring.h
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
* scopy - #defined in mystring.h
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* scopyn - copy a string from "from" to "to", truncating the string
|
|
||||||
* if necessary. "To" is always nul terminated, even if
|
|
||||||
* truncation is performed. "Size" is the size of "to".
|
|
||||||
*/
|
|
||||||
|
|
||||||
void
|
|
||||||
scopyn(const char *from, char *to, int size)
|
|
||||||
{
|
|
||||||
|
|
||||||
while (--size > 0) {
|
|
||||||
if ((*to++ = *from++) == '\0')
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
*to = '\0';
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* prefix -- see if pfx is a prefix of string.
|
|
||||||
*/
|
|
||||||
|
|
||||||
int
|
|
||||||
prefix(const char *pfx, const char *string)
|
|
||||||
{
|
|
||||||
while (*pfx) {
|
|
||||||
if (*pfx++ != *string++)
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Convert a string of digits to an integer, printing an error message on
|
|
||||||
* failure.
|
|
||||||
*/
|
|
||||||
|
|
||||||
int
|
|
||||||
number(const char *s)
|
|
||||||
{
|
|
||||||
|
|
||||||
if (! is_number(s))
|
|
||||||
error("Illegal number: %s", s);
|
|
||||||
return atoi(s);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Check for a valid number. This should be elsewhere.
|
|
||||||
*/
|
|
||||||
|
|
||||||
int
|
|
||||||
is_number(const char *p)
|
|
||||||
{
|
|
||||||
do {
|
|
||||||
if (! is_digit(*p))
|
|
||||||
return 0;
|
|
||||||
} while (*++p != '\0');
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
@ -1,45 +0,0 @@
|
||||||
/* $NetBSD: mystring.h,v 1.11 2003/08/07 09:05:35 agc Exp $ */
|
|
||||||
|
|
||||||
/*-
|
|
||||||
* Copyright (c) 1991, 1993
|
|
||||||
* The Regents of the University of California. All rights reserved.
|
|
||||||
*
|
|
||||||
* This code is derived from software contributed to Berkeley by
|
|
||||||
* Kenneth Almquist.
|
|
||||||
*
|
|
||||||
* Redistribution and use in source and binary forms, with or without
|
|
||||||
* modification, are permitted provided that the following conditions
|
|
||||||
* are met:
|
|
||||||
* 1. Redistributions of source code must retain the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer.
|
|
||||||
* 2. Redistributions in binary form must reproduce the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer in the
|
|
||||||
* documentation and/or other materials provided with the distribution.
|
|
||||||
* 3. Neither the name of the University nor the names of its contributors
|
|
||||||
* may be used to endorse or promote products derived from this software
|
|
||||||
* without specific prior written permission.
|
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
|
||||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
||||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
||||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
|
||||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
||||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
|
||||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
|
||||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
||||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
|
||||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
|
||||||
* SUCH DAMAGE.
|
|
||||||
*
|
|
||||||
* @(#)mystring.h 8.2 (Berkeley) 5/4/95
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
void scopyn(const char *, char *, int);
|
|
||||||
int prefix(const char *, const char *);
|
|
||||||
int number(const char *);
|
|
||||||
int is_number(const char *);
|
|
||||||
|
|
||||||
#define equal(s1, s2) (strcmp(s1, s2) == 0)
|
|
||||||
#define scopy(s1, s2) ((void)strcpy(s2, s1))
|
|
||||||
347
sh/nodes.c
347
sh/nodes.c
|
|
@ -1,347 +0,0 @@
|
||||||
/*
|
|
||||||
* This file was generated by mknodes.sh
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* $NetBSD: nodes.c.pat,v 1.12 2004/06/15 22:57:27 dsl Exp $ */
|
|
||||||
|
|
||||||
/*-
|
|
||||||
* Copyright (c) 1991, 1993
|
|
||||||
* The Regents of the University of California. All rights reserved.
|
|
||||||
*
|
|
||||||
* This code is derived from software contributed to Berkeley by
|
|
||||||
* Kenneth Almquist.
|
|
||||||
*
|
|
||||||
* Redistribution and use in source and binary forms, with or without
|
|
||||||
* modification, are permitted provided that the following conditions
|
|
||||||
* are met:
|
|
||||||
* 1. Redistributions of source code must retain the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer.
|
|
||||||
* 2. Redistributions in binary form must reproduce the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer in the
|
|
||||||
* documentation and/or other materials provided with the distribution.
|
|
||||||
* 3. Neither the name of the University nor the names of its contributors
|
|
||||||
* may be used to endorse or promote products derived from this software
|
|
||||||
* without specific prior written permission.
|
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
|
||||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
||||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
||||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
|
||||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
||||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
|
||||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
|
||||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
||||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
|
||||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
|
||||||
* SUCH DAMAGE.
|
|
||||||
*
|
|
||||||
* @(#)nodes.c.pat 8.2 (Berkeley) 5/4/95
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <stdlib.h>
|
|
||||||
/*
|
|
||||||
* Routine for dealing with parsed shell commands.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "shell.h"
|
|
||||||
#include "nodes.h"
|
|
||||||
#include "memalloc.h"
|
|
||||||
#include "machdep.h"
|
|
||||||
#include "mystring.h"
|
|
||||||
|
|
||||||
|
|
||||||
int funcblocksize; /* size of structures in function */
|
|
||||||
int funcstringsize; /* size of strings in node */
|
|
||||||
pointer funcblock; /* block to allocate function from */
|
|
||||||
char *funcstring; /* block to allocate strings from */
|
|
||||||
|
|
||||||
static const short nodesize[26] = {
|
|
||||||
SHELL_ALIGN(sizeof (struct nbinary)),
|
|
||||||
SHELL_ALIGN(sizeof (struct ncmd)),
|
|
||||||
SHELL_ALIGN(sizeof (struct npipe)),
|
|
||||||
SHELL_ALIGN(sizeof (struct nredir)),
|
|
||||||
SHELL_ALIGN(sizeof (struct nredir)),
|
|
||||||
SHELL_ALIGN(sizeof (struct nredir)),
|
|
||||||
SHELL_ALIGN(sizeof (struct nbinary)),
|
|
||||||
SHELL_ALIGN(sizeof (struct nbinary)),
|
|
||||||
SHELL_ALIGN(sizeof (struct nif)),
|
|
||||||
SHELL_ALIGN(sizeof (struct nbinary)),
|
|
||||||
SHELL_ALIGN(sizeof (struct nbinary)),
|
|
||||||
SHELL_ALIGN(sizeof (struct nfor)),
|
|
||||||
SHELL_ALIGN(sizeof (struct ncase)),
|
|
||||||
SHELL_ALIGN(sizeof (struct nclist)),
|
|
||||||
SHELL_ALIGN(sizeof (struct narg)),
|
|
||||||
SHELL_ALIGN(sizeof (struct narg)),
|
|
||||||
SHELL_ALIGN(sizeof (struct nfile)),
|
|
||||||
SHELL_ALIGN(sizeof (struct nfile)),
|
|
||||||
SHELL_ALIGN(sizeof (struct nfile)),
|
|
||||||
SHELL_ALIGN(sizeof (struct nfile)),
|
|
||||||
SHELL_ALIGN(sizeof (struct nfile)),
|
|
||||||
SHELL_ALIGN(sizeof (struct ndup)),
|
|
||||||
SHELL_ALIGN(sizeof (struct ndup)),
|
|
||||||
SHELL_ALIGN(sizeof (struct nhere)),
|
|
||||||
SHELL_ALIGN(sizeof (struct nhere)),
|
|
||||||
SHELL_ALIGN(sizeof (struct nnot)),
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
STATIC void calcsize(union node *);
|
|
||||||
STATIC void sizenodelist(struct nodelist *);
|
|
||||||
STATIC union node *copynode(union node *);
|
|
||||||
STATIC struct nodelist *copynodelist(struct nodelist *);
|
|
||||||
STATIC char *nodesavestr(char *);
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Make a copy of a parse tree.
|
|
||||||
*/
|
|
||||||
|
|
||||||
union node *
|
|
||||||
copyfunc(n)
|
|
||||||
union node *n;
|
|
||||||
{
|
|
||||||
if (n == NULL)
|
|
||||||
return NULL;
|
|
||||||
funcblocksize = 0;
|
|
||||||
funcstringsize = 0;
|
|
||||||
calcsize(n);
|
|
||||||
funcblock = ckmalloc(funcblocksize + funcstringsize);
|
|
||||||
funcstring = (char *) funcblock + funcblocksize;
|
|
||||||
return copynode(n);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
STATIC void
|
|
||||||
calcsize(n)
|
|
||||||
union node *n;
|
|
||||||
{
|
|
||||||
if (n == NULL)
|
|
||||||
return;
|
|
||||||
funcblocksize += nodesize[n->type];
|
|
||||||
switch (n->type) {
|
|
||||||
case NSEMI:
|
|
||||||
case NAND:
|
|
||||||
case NOR:
|
|
||||||
case NWHILE:
|
|
||||||
case NUNTIL:
|
|
||||||
calcsize(n->nbinary.ch2);
|
|
||||||
calcsize(n->nbinary.ch1);
|
|
||||||
break;
|
|
||||||
case NCMD:
|
|
||||||
calcsize(n->ncmd.redirect);
|
|
||||||
calcsize(n->ncmd.args);
|
|
||||||
break;
|
|
||||||
case NPIPE:
|
|
||||||
sizenodelist(n->npipe.cmdlist);
|
|
||||||
break;
|
|
||||||
case NREDIR:
|
|
||||||
case NBACKGND:
|
|
||||||
case NSUBSHELL:
|
|
||||||
calcsize(n->nredir.redirect);
|
|
||||||
calcsize(n->nredir.n);
|
|
||||||
break;
|
|
||||||
case NIF:
|
|
||||||
calcsize(n->nif.elsepart);
|
|
||||||
calcsize(n->nif.ifpart);
|
|
||||||
calcsize(n->nif.test);
|
|
||||||
break;
|
|
||||||
case NFOR:
|
|
||||||
funcstringsize += strlen(n->nfor.var) + 1;
|
|
||||||
calcsize(n->nfor.body);
|
|
||||||
calcsize(n->nfor.args);
|
|
||||||
break;
|
|
||||||
case NCASE:
|
|
||||||
calcsize(n->ncase.cases);
|
|
||||||
calcsize(n->ncase.expr);
|
|
||||||
break;
|
|
||||||
case NCLIST:
|
|
||||||
calcsize(n->nclist.body);
|
|
||||||
calcsize(n->nclist.pattern);
|
|
||||||
calcsize(n->nclist.next);
|
|
||||||
break;
|
|
||||||
case NDEFUN:
|
|
||||||
case NARG:
|
|
||||||
sizenodelist(n->narg.backquote);
|
|
||||||
funcstringsize += strlen(n->narg.text) + 1;
|
|
||||||
calcsize(n->narg.next);
|
|
||||||
break;
|
|
||||||
case NTO:
|
|
||||||
case NCLOBBER:
|
|
||||||
case NFROM:
|
|
||||||
case NFROMTO:
|
|
||||||
case NAPPEND:
|
|
||||||
calcsize(n->nfile.fname);
|
|
||||||
calcsize(n->nfile.next);
|
|
||||||
break;
|
|
||||||
case NTOFD:
|
|
||||||
case NFROMFD:
|
|
||||||
calcsize(n->ndup.vname);
|
|
||||||
calcsize(n->ndup.next);
|
|
||||||
break;
|
|
||||||
case NHERE:
|
|
||||||
case NXHERE:
|
|
||||||
calcsize(n->nhere.doc);
|
|
||||||
calcsize(n->nhere.next);
|
|
||||||
break;
|
|
||||||
case NNOT:
|
|
||||||
calcsize(n->nnot.com);
|
|
||||||
break;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
STATIC void
|
|
||||||
sizenodelist(lp)
|
|
||||||
struct nodelist *lp;
|
|
||||||
{
|
|
||||||
while (lp) {
|
|
||||||
funcblocksize += SHELL_ALIGN(sizeof(struct nodelist));
|
|
||||||
calcsize(lp->n);
|
|
||||||
lp = lp->next;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
STATIC union node *
|
|
||||||
copynode(n)
|
|
||||||
union node *n;
|
|
||||||
{
|
|
||||||
union node *new;
|
|
||||||
|
|
||||||
if (n == NULL)
|
|
||||||
return NULL;
|
|
||||||
new = funcblock;
|
|
||||||
funcblock = (char *) funcblock + nodesize[n->type];
|
|
||||||
switch (n->type) {
|
|
||||||
case NSEMI:
|
|
||||||
case NAND:
|
|
||||||
case NOR:
|
|
||||||
case NWHILE:
|
|
||||||
case NUNTIL:
|
|
||||||
new->nbinary.ch2 = copynode(n->nbinary.ch2);
|
|
||||||
new->nbinary.ch1 = copynode(n->nbinary.ch1);
|
|
||||||
break;
|
|
||||||
case NCMD:
|
|
||||||
new->ncmd.redirect = copynode(n->ncmd.redirect);
|
|
||||||
new->ncmd.args = copynode(n->ncmd.args);
|
|
||||||
new->ncmd.backgnd = n->ncmd.backgnd;
|
|
||||||
break;
|
|
||||||
case NPIPE:
|
|
||||||
new->npipe.cmdlist = copynodelist(n->npipe.cmdlist);
|
|
||||||
new->npipe.backgnd = n->npipe.backgnd;
|
|
||||||
break;
|
|
||||||
case NREDIR:
|
|
||||||
case NBACKGND:
|
|
||||||
case NSUBSHELL:
|
|
||||||
new->nredir.redirect = copynode(n->nredir.redirect);
|
|
||||||
new->nredir.n = copynode(n->nredir.n);
|
|
||||||
break;
|
|
||||||
case NIF:
|
|
||||||
new->nif.elsepart = copynode(n->nif.elsepart);
|
|
||||||
new->nif.ifpart = copynode(n->nif.ifpart);
|
|
||||||
new->nif.test = copynode(n->nif.test);
|
|
||||||
break;
|
|
||||||
case NFOR:
|
|
||||||
new->nfor.var = nodesavestr(n->nfor.var);
|
|
||||||
new->nfor.body = copynode(n->nfor.body);
|
|
||||||
new->nfor.args = copynode(n->nfor.args);
|
|
||||||
break;
|
|
||||||
case NCASE:
|
|
||||||
new->ncase.cases = copynode(n->ncase.cases);
|
|
||||||
new->ncase.expr = copynode(n->ncase.expr);
|
|
||||||
break;
|
|
||||||
case NCLIST:
|
|
||||||
new->nclist.body = copynode(n->nclist.body);
|
|
||||||
new->nclist.pattern = copynode(n->nclist.pattern);
|
|
||||||
new->nclist.next = copynode(n->nclist.next);
|
|
||||||
break;
|
|
||||||
case NDEFUN:
|
|
||||||
case NARG:
|
|
||||||
new->narg.backquote = copynodelist(n->narg.backquote);
|
|
||||||
new->narg.text = nodesavestr(n->narg.text);
|
|
||||||
new->narg.next = copynode(n->narg.next);
|
|
||||||
break;
|
|
||||||
case NTO:
|
|
||||||
case NCLOBBER:
|
|
||||||
case NFROM:
|
|
||||||
case NFROMTO:
|
|
||||||
case NAPPEND:
|
|
||||||
new->nfile.fname = copynode(n->nfile.fname);
|
|
||||||
new->nfile.fd = n->nfile.fd;
|
|
||||||
new->nfile.next = copynode(n->nfile.next);
|
|
||||||
break;
|
|
||||||
case NTOFD:
|
|
||||||
case NFROMFD:
|
|
||||||
new->ndup.vname = copynode(n->ndup.vname);
|
|
||||||
new->ndup.dupfd = n->ndup.dupfd;
|
|
||||||
new->ndup.fd = n->ndup.fd;
|
|
||||||
new->ndup.next = copynode(n->ndup.next);
|
|
||||||
break;
|
|
||||||
case NHERE:
|
|
||||||
case NXHERE:
|
|
||||||
new->nhere.doc = copynode(n->nhere.doc);
|
|
||||||
new->nhere.fd = n->nhere.fd;
|
|
||||||
new->nhere.next = copynode(n->nhere.next);
|
|
||||||
break;
|
|
||||||
case NNOT:
|
|
||||||
new->nnot.com = copynode(n->nnot.com);
|
|
||||||
break;
|
|
||||||
};
|
|
||||||
new->type = n->type;
|
|
||||||
return new;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
STATIC struct nodelist *
|
|
||||||
copynodelist(lp)
|
|
||||||
struct nodelist *lp;
|
|
||||||
{
|
|
||||||
struct nodelist *start;
|
|
||||||
struct nodelist **lpp;
|
|
||||||
|
|
||||||
lpp = &start;
|
|
||||||
while (lp) {
|
|
||||||
*lpp = funcblock;
|
|
||||||
funcblock = (char *) funcblock +
|
|
||||||
SHELL_ALIGN(sizeof(struct nodelist));
|
|
||||||
(*lpp)->n = copynode(lp->n);
|
|
||||||
lp = lp->next;
|
|
||||||
lpp = &(*lpp)->next;
|
|
||||||
}
|
|
||||||
*lpp = NULL;
|
|
||||||
return start;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
STATIC char *
|
|
||||||
nodesavestr(s)
|
|
||||||
char *s;
|
|
||||||
{
|
|
||||||
register char *p = s;
|
|
||||||
register char *q = funcstring;
|
|
||||||
char *rtn = funcstring;
|
|
||||||
|
|
||||||
while ((*q++ = *p++) != 0)
|
|
||||||
continue;
|
|
||||||
funcstring = q;
|
|
||||||
return rtn;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Free a parse tree.
|
|
||||||
*/
|
|
||||||
|
|
||||||
void
|
|
||||||
freefunc(n)
|
|
||||||
union node *n;
|
|
||||||
{
|
|
||||||
if (n)
|
|
||||||
ckfree(n);
|
|
||||||
}
|
|
||||||
166
sh/nodes.c.pat
166
sh/nodes.c.pat
|
|
@ -1,166 +0,0 @@
|
||||||
/* $NetBSD: nodes.c.pat,v 1.12 2004/06/15 22:57:27 dsl Exp $ */
|
|
||||||
|
|
||||||
/*-
|
|
||||||
* Copyright (c) 1991, 1993
|
|
||||||
* The Regents of the University of California. All rights reserved.
|
|
||||||
*
|
|
||||||
* This code is derived from software contributed to Berkeley by
|
|
||||||
* Kenneth Almquist.
|
|
||||||
*
|
|
||||||
* Redistribution and use in source and binary forms, with or without
|
|
||||||
* modification, are permitted provided that the following conditions
|
|
||||||
* are met:
|
|
||||||
* 1. Redistributions of source code must retain the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer.
|
|
||||||
* 2. Redistributions in binary form must reproduce the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer in the
|
|
||||||
* documentation and/or other materials provided with the distribution.
|
|
||||||
* 3. Neither the name of the University nor the names of its contributors
|
|
||||||
* may be used to endorse or promote products derived from this software
|
|
||||||
* without specific prior written permission.
|
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
|
||||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
||||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
||||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
|
||||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
||||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
|
||||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
|
||||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
||||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
|
||||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
|
||||||
* SUCH DAMAGE.
|
|
||||||
*
|
|
||||||
* @(#)nodes.c.pat 8.2 (Berkeley) 5/4/95
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <stdlib.h>
|
|
||||||
/*
|
|
||||||
* Routine for dealing with parsed shell commands.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "shell.h"
|
|
||||||
#include "nodes.h"
|
|
||||||
#include "memalloc.h"
|
|
||||||
#include "machdep.h"
|
|
||||||
#include "mystring.h"
|
|
||||||
|
|
||||||
|
|
||||||
int funcblocksize; /* size of structures in function */
|
|
||||||
int funcstringsize; /* size of strings in node */
|
|
||||||
pointer funcblock; /* block to allocate function from */
|
|
||||||
char *funcstring; /* block to allocate strings from */
|
|
||||||
|
|
||||||
%SIZES
|
|
||||||
|
|
||||||
|
|
||||||
STATIC void calcsize(union node *);
|
|
||||||
STATIC void sizenodelist(struct nodelist *);
|
|
||||||
STATIC union node *copynode(union node *);
|
|
||||||
STATIC struct nodelist *copynodelist(struct nodelist *);
|
|
||||||
STATIC char *nodesavestr(char *);
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Make a copy of a parse tree.
|
|
||||||
*/
|
|
||||||
|
|
||||||
union node *
|
|
||||||
copyfunc(n)
|
|
||||||
union node *n;
|
|
||||||
{
|
|
||||||
if (n == NULL)
|
|
||||||
return NULL;
|
|
||||||
funcblocksize = 0;
|
|
||||||
funcstringsize = 0;
|
|
||||||
calcsize(n);
|
|
||||||
funcblock = ckmalloc(funcblocksize + funcstringsize);
|
|
||||||
funcstring = (char *) funcblock + funcblocksize;
|
|
||||||
return copynode(n);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
STATIC void
|
|
||||||
calcsize(n)
|
|
||||||
union node *n;
|
|
||||||
{
|
|
||||||
%CALCSIZE
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
STATIC void
|
|
||||||
sizenodelist(lp)
|
|
||||||
struct nodelist *lp;
|
|
||||||
{
|
|
||||||
while (lp) {
|
|
||||||
funcblocksize += SHELL_ALIGN(sizeof(struct nodelist));
|
|
||||||
calcsize(lp->n);
|
|
||||||
lp = lp->next;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
STATIC union node *
|
|
||||||
copynode(n)
|
|
||||||
union node *n;
|
|
||||||
{
|
|
||||||
union node *new;
|
|
||||||
|
|
||||||
%COPY
|
|
||||||
return new;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
STATIC struct nodelist *
|
|
||||||
copynodelist(lp)
|
|
||||||
struct nodelist *lp;
|
|
||||||
{
|
|
||||||
struct nodelist *start;
|
|
||||||
struct nodelist **lpp;
|
|
||||||
|
|
||||||
lpp = &start;
|
|
||||||
while (lp) {
|
|
||||||
*lpp = funcblock;
|
|
||||||
funcblock = (char *) funcblock +
|
|
||||||
SHELL_ALIGN(sizeof(struct nodelist));
|
|
||||||
(*lpp)->n = copynode(lp->n);
|
|
||||||
lp = lp->next;
|
|
||||||
lpp = &(*lpp)->next;
|
|
||||||
}
|
|
||||||
*lpp = NULL;
|
|
||||||
return start;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
STATIC char *
|
|
||||||
nodesavestr(s)
|
|
||||||
char *s;
|
|
||||||
{
|
|
||||||
register char *p = s;
|
|
||||||
register char *q = funcstring;
|
|
||||||
char *rtn = funcstring;
|
|
||||||
|
|
||||||
while ((*q++ = *p++) != 0)
|
|
||||||
continue;
|
|
||||||
funcstring = q;
|
|
||||||
return rtn;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Free a parse tree.
|
|
||||||
*/
|
|
||||||
|
|
||||||
void
|
|
||||||
freefunc(n)
|
|
||||||
union node *n;
|
|
||||||
{
|
|
||||||
if (n)
|
|
||||||
ckfree(n);
|
|
||||||
}
|
|
||||||
159
sh/nodes.h
159
sh/nodes.h
|
|
@ -1,159 +0,0 @@
|
||||||
/*
|
|
||||||
* This file was generated by mknodes.sh
|
|
||||||
*/
|
|
||||||
|
|
||||||
#define NSEMI 0
|
|
||||||
#define NCMD 1
|
|
||||||
#define NPIPE 2
|
|
||||||
#define NREDIR 3
|
|
||||||
#define NBACKGND 4
|
|
||||||
#define NSUBSHELL 5
|
|
||||||
#define NAND 6
|
|
||||||
#define NOR 7
|
|
||||||
#define NIF 8
|
|
||||||
#define NWHILE 9
|
|
||||||
#define NUNTIL 10
|
|
||||||
#define NFOR 11
|
|
||||||
#define NCASE 12
|
|
||||||
#define NCLIST 13
|
|
||||||
#define NDEFUN 14
|
|
||||||
#define NARG 15
|
|
||||||
#define NTO 16
|
|
||||||
#define NCLOBBER 17
|
|
||||||
#define NFROM 18
|
|
||||||
#define NFROMTO 19
|
|
||||||
#define NAPPEND 20
|
|
||||||
#define NTOFD 21
|
|
||||||
#define NFROMFD 22
|
|
||||||
#define NHERE 23
|
|
||||||
#define NXHERE 24
|
|
||||||
#define NNOT 25
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
struct nbinary {
|
|
||||||
int type;
|
|
||||||
union node *ch1;
|
|
||||||
union node *ch2;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
struct ncmd {
|
|
||||||
int type;
|
|
||||||
int backgnd;
|
|
||||||
union node *args;
|
|
||||||
union node *redirect;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
struct npipe {
|
|
||||||
int type;
|
|
||||||
int backgnd;
|
|
||||||
struct nodelist *cmdlist;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
struct nredir {
|
|
||||||
int type;
|
|
||||||
union node *n;
|
|
||||||
union node *redirect;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
struct nif {
|
|
||||||
int type;
|
|
||||||
union node *test;
|
|
||||||
union node *ifpart;
|
|
||||||
union node *elsepart;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
struct nfor {
|
|
||||||
int type;
|
|
||||||
union node *args;
|
|
||||||
union node *body;
|
|
||||||
char *var;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
struct ncase {
|
|
||||||
int type;
|
|
||||||
union node *expr;
|
|
||||||
union node *cases;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
struct nclist {
|
|
||||||
int type;
|
|
||||||
union node *next;
|
|
||||||
union node *pattern;
|
|
||||||
union node *body;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
struct narg {
|
|
||||||
int type;
|
|
||||||
union node *next;
|
|
||||||
char *text;
|
|
||||||
struct nodelist *backquote;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
struct nfile {
|
|
||||||
int type;
|
|
||||||
union node *next;
|
|
||||||
int fd;
|
|
||||||
union node *fname;
|
|
||||||
char *expfname;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
struct ndup {
|
|
||||||
int type;
|
|
||||||
union node *next;
|
|
||||||
int fd;
|
|
||||||
int dupfd;
|
|
||||||
union node *vname;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
struct nhere {
|
|
||||||
int type;
|
|
||||||
union node *next;
|
|
||||||
int fd;
|
|
||||||
union node *doc;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
struct nnot {
|
|
||||||
int type;
|
|
||||||
union node *com;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
union node {
|
|
||||||
int type;
|
|
||||||
struct nbinary nbinary;
|
|
||||||
struct ncmd ncmd;
|
|
||||||
struct npipe npipe;
|
|
||||||
struct nredir nredir;
|
|
||||||
struct nif nif;
|
|
||||||
struct nfor nfor;
|
|
||||||
struct ncase ncase;
|
|
||||||
struct nclist nclist;
|
|
||||||
struct narg narg;
|
|
||||||
struct nfile nfile;
|
|
||||||
struct ndup ndup;
|
|
||||||
struct nhere nhere;
|
|
||||||
struct nnot nnot;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
struct nodelist {
|
|
||||||
struct nodelist *next;
|
|
||||||
union node *n;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
union node *copyfunc(union node *);
|
|
||||||
void freefunc(union node *);
|
|
||||||
143
sh/nodetypes
143
sh/nodetypes
|
|
@ -1,143 +0,0 @@
|
||||||
# $NetBSD: nodetypes,v 1.12 2003/08/22 11:22:23 agc Exp $
|
|
||||||
# Copyright (c) 1991, 1993
|
|
||||||
# The Regents of the University of California. All rights reserved.
|
|
||||||
#
|
|
||||||
# This code is derived from software contributed to Berkeley by
|
|
||||||
# Kenneth Almquist.
|
|
||||||
#
|
|
||||||
# Redistribution and use in source and binary forms, with or without
|
|
||||||
# modification, are permitted provided that the following conditions
|
|
||||||
# are met:
|
|
||||||
# 1. Redistributions of source code must retain the above copyright
|
|
||||||
# notice, this list of conditions and the following disclaimer.
|
|
||||||
# 2. Redistributions in binary form must reproduce the above copyright
|
|
||||||
# notice, this list of conditions and the following disclaimer in the
|
|
||||||
# documentation and/or other materials provided with the distribution.
|
|
||||||
# 3. Neither the name of the University nor the names of its contributors
|
|
||||||
# may be used to endorse or promote products derived from this software
|
|
||||||
# without specific prior written permission.
|
|
||||||
#
|
|
||||||
# THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
|
||||||
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
||||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
||||||
# ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
|
||||||
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
||||||
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
|
||||||
# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
|
||||||
# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
||||||
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
|
||||||
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
|
||||||
# SUCH DAMAGE.
|
|
||||||
#
|
|
||||||
# @(#)nodetypes 8.2 (Berkeley) 5/4/95
|
|
||||||
|
|
||||||
# This file describes the nodes used in parse trees. Unindented lines
|
|
||||||
# contain a node type followed by a structure tag. Subsequent indented
|
|
||||||
# lines specify the fields of the structure. Several node types can share
|
|
||||||
# the same structure, in which case the fields of the structure should be
|
|
||||||
# specified only once.
|
|
||||||
#
|
|
||||||
# A field of a structure is described by the name of the field followed
|
|
||||||
# by a type. The currently implemented types are:
|
|
||||||
# nodeptr - a pointer to a node
|
|
||||||
# nodelist - a pointer to a list of nodes
|
|
||||||
# string - a pointer to a nul terminated string
|
|
||||||
# int - an integer
|
|
||||||
# other - any type that can be copied by assignment
|
|
||||||
# temp - a field that doesn't have to be copied when the node is copied
|
|
||||||
# The last two types should be followed by the text of a C declaration for
|
|
||||||
# the field.
|
|
||||||
|
|
||||||
NSEMI nbinary # two commands separated by a semicolon
|
|
||||||
type int
|
|
||||||
ch1 nodeptr # the first child
|
|
||||||
ch2 nodeptr # the second child
|
|
||||||
|
|
||||||
NCMD ncmd # a simple command
|
|
||||||
type int
|
|
||||||
backgnd int # set to run command in background
|
|
||||||
args nodeptr # the arguments
|
|
||||||
redirect nodeptr # list of file redirections
|
|
||||||
|
|
||||||
NPIPE npipe # a pipeline
|
|
||||||
type int
|
|
||||||
backgnd int # set to run pipeline in background
|
|
||||||
cmdlist nodelist # the commands in the pipeline
|
|
||||||
|
|
||||||
NREDIR nredir # redirection (of a complex command)
|
|
||||||
type int
|
|
||||||
n nodeptr # the command
|
|
||||||
redirect nodeptr # list of file redirections
|
|
||||||
|
|
||||||
NBACKGND nredir # run command in background
|
|
||||||
NSUBSHELL nredir # run command in a subshell
|
|
||||||
|
|
||||||
NAND nbinary # the && operator
|
|
||||||
NOR nbinary # the || operator
|
|
||||||
|
|
||||||
NIF nif # the if statement. Elif clauses are handled
|
|
||||||
type int # using multiple if nodes.
|
|
||||||
test nodeptr # if test
|
|
||||||
ifpart nodeptr # then ifpart
|
|
||||||
elsepart nodeptr # else elsepart
|
|
||||||
|
|
||||||
NWHILE nbinary # the while statement. First child is the test
|
|
||||||
NUNTIL nbinary # the until statement
|
|
||||||
|
|
||||||
NFOR nfor # the for statement
|
|
||||||
type int
|
|
||||||
args nodeptr # for var in args
|
|
||||||
body nodeptr # do body; done
|
|
||||||
var string # the for variable
|
|
||||||
|
|
||||||
NCASE ncase # a case statement
|
|
||||||
type int
|
|
||||||
expr nodeptr # the word to switch on
|
|
||||||
cases nodeptr # the list of cases (NCLIST nodes)
|
|
||||||
|
|
||||||
NCLIST nclist # a case
|
|
||||||
type int
|
|
||||||
next nodeptr # the next case in list
|
|
||||||
pattern nodeptr # list of patterns for this case
|
|
||||||
body nodeptr # code to execute for this case
|
|
||||||
|
|
||||||
|
|
||||||
NDEFUN narg # define a function. The "next" field contains
|
|
||||||
# the body of the function.
|
|
||||||
|
|
||||||
NARG narg # represents a word
|
|
||||||
type int
|
|
||||||
next nodeptr # next word in list
|
|
||||||
text string # the text of the word
|
|
||||||
backquote nodelist # list of commands in back quotes
|
|
||||||
|
|
||||||
NTO nfile # fd> fname
|
|
||||||
NCLOBBER nfile # fd>| fname
|
|
||||||
NFROM nfile # fd< fname
|
|
||||||
NFROMTO nfile # fd<> fname
|
|
||||||
NAPPEND nfile # fd>> fname
|
|
||||||
type int
|
|
||||||
next nodeptr # next redirection in list
|
|
||||||
fd int # file descriptor being redirected
|
|
||||||
fname nodeptr # file name, in a NARG node
|
|
||||||
expfname temp char *expfname # actual file name
|
|
||||||
|
|
||||||
NTOFD ndup # fd<&dupfd
|
|
||||||
NFROMFD ndup # fd>&dupfd
|
|
||||||
type int
|
|
||||||
next nodeptr # next redirection in list
|
|
||||||
fd int # file descriptor being redirected
|
|
||||||
dupfd int # file descriptor to duplicate
|
|
||||||
vname nodeptr # file name if fd>&$var
|
|
||||||
|
|
||||||
|
|
||||||
NHERE nhere # fd<<\!
|
|
||||||
NXHERE nhere # fd<<!
|
|
||||||
type int
|
|
||||||
next nodeptr # next redirection in list
|
|
||||||
fd int # file descriptor being redirected
|
|
||||||
doc nodeptr # input to command (NARG node)
|
|
||||||
|
|
||||||
NNOT nnot # ! command (actually pipeline)
|
|
||||||
type int
|
|
||||||
com nodeptr
|
|
||||||
530
sh/options.c
530
sh/options.c
|
|
@ -1,530 +0,0 @@
|
||||||
/* $NetBSD: options.c,v 1.37 2004/10/30 19:29:27 christos Exp $ */
|
|
||||||
|
|
||||||
/*-
|
|
||||||
* Copyright (c) 1991, 1993
|
|
||||||
* The Regents of the University of California. All rights reserved.
|
|
||||||
*
|
|
||||||
* This code is derived from software contributed to Berkeley by
|
|
||||||
* Kenneth Almquist.
|
|
||||||
*
|
|
||||||
* Redistribution and use in source and binary forms, with or without
|
|
||||||
* modification, are permitted provided that the following conditions
|
|
||||||
* are met:
|
|
||||||
* 1. Redistributions of source code must retain the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer.
|
|
||||||
* 2. Redistributions in binary form must reproduce the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer in the
|
|
||||||
* documentation and/or other materials provided with the distribution.
|
|
||||||
* 3. Neither the name of the University nor the names of its contributors
|
|
||||||
* may be used to endorse or promote products derived from this software
|
|
||||||
* without specific prior written permission.
|
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
|
||||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
||||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
||||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
|
||||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
||||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
|
||||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
|
||||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
||||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
|
||||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
|
||||||
* SUCH DAMAGE.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <sys/cdefs.h>
|
|
||||||
#ifndef lint
|
|
||||||
#if 0
|
|
||||||
static char sccsid[] = "@(#)options.c 8.2 (Berkeley) 5/4/95";
|
|
||||||
#else
|
|
||||||
__RCSID("$NetBSD: options.c,v 1.37 2004/10/30 19:29:27 christos Exp $");
|
|
||||||
#endif
|
|
||||||
#endif /* not lint */
|
|
||||||
|
|
||||||
#include <signal.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
|
|
||||||
#include "shell.h"
|
|
||||||
#define DEFINE_OPTIONS
|
|
||||||
#include "options.h"
|
|
||||||
#undef DEFINE_OPTIONS
|
|
||||||
#include "nodes.h" /* for other header files */
|
|
||||||
#include "eval.h"
|
|
||||||
#include "jobs.h"
|
|
||||||
#include "input.h"
|
|
||||||
#include "output.h"
|
|
||||||
#include "trap.h"
|
|
||||||
#include "var.h"
|
|
||||||
#include "memalloc.h"
|
|
||||||
#include "error.h"
|
|
||||||
#include "mystring.h"
|
|
||||||
#ifndef SMALL
|
|
||||||
#include "myhistedit.h"
|
|
||||||
#endif
|
|
||||||
#include "show.h"
|
|
||||||
|
|
||||||
char *arg0; /* value of $0 */
|
|
||||||
struct shparam shellparam; /* current positional parameters */
|
|
||||||
char **argptr; /* argument list for builtin commands */
|
|
||||||
char *optionarg; /* set by nextopt (like getopt) */
|
|
||||||
char *optptr; /* used by nextopt */
|
|
||||||
|
|
||||||
char *minusc; /* argument to -c option */
|
|
||||||
|
|
||||||
|
|
||||||
STATIC void options(int);
|
|
||||||
STATIC void minus_o(char *, int);
|
|
||||||
STATIC void setoption(int, int);
|
|
||||||
STATIC int getopts(char *, char *, char **, char ***, char **);
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Process the shell command line arguments.
|
|
||||||
*/
|
|
||||||
|
|
||||||
void
|
|
||||||
procargs(int argc, char **argv)
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
|
|
||||||
argptr = argv;
|
|
||||||
if (argc > 0)
|
|
||||||
argptr++;
|
|
||||||
for (i = 0; i < NOPTS; i++)
|
|
||||||
optlist[i].val = 2;
|
|
||||||
options(1);
|
|
||||||
if (*argptr == NULL && minusc == NULL)
|
|
||||||
sflag = 1;
|
|
||||||
if (iflag == 2 && sflag == 1 && isatty(0) && isatty(1))
|
|
||||||
iflag = 1;
|
|
||||||
if (mflag == 2)
|
|
||||||
mflag = iflag;
|
|
||||||
for (i = 0; i < NOPTS; i++)
|
|
||||||
if (optlist[i].val == 2)
|
|
||||||
optlist[i].val = 0;
|
|
||||||
#if DEBUG == 2
|
|
||||||
debug = 1;
|
|
||||||
#endif
|
|
||||||
arg0 = argv[0];
|
|
||||||
if (sflag == 0 && minusc == NULL) {
|
|
||||||
commandname = argv[0];
|
|
||||||
arg0 = *argptr++;
|
|
||||||
setinputfile(arg0, 0);
|
|
||||||
commandname = arg0;
|
|
||||||
}
|
|
||||||
/* POSIX 1003.2: first arg after -c cmd is $0, remainder $1... */
|
|
||||||
if (minusc != NULL) {
|
|
||||||
if (argptr == NULL || *argptr == NULL)
|
|
||||||
error("Bad -c option");
|
|
||||||
minusc = *argptr++;
|
|
||||||
if (*argptr != 0)
|
|
||||||
arg0 = *argptr++;
|
|
||||||
}
|
|
||||||
|
|
||||||
shellparam.p = argptr;
|
|
||||||
shellparam.reset = 1;
|
|
||||||
/* assert(shellparam.malloc == 0 && shellparam.nparam == 0); */
|
|
||||||
while (*argptr) {
|
|
||||||
shellparam.nparam++;
|
|
||||||
argptr++;
|
|
||||||
}
|
|
||||||
optschanged();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
optschanged(void)
|
|
||||||
{
|
|
||||||
setinteractive(iflag);
|
|
||||||
#ifdef WITH_HISTORY
|
|
||||||
histedit();
|
|
||||||
#endif
|
|
||||||
setjobctl(mflag);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Process shell options. The global variable argptr contains a pointer
|
|
||||||
* to the argument list; we advance it past the options.
|
|
||||||
*/
|
|
||||||
|
|
||||||
STATIC void
|
|
||||||
options(int cmdline)
|
|
||||||
{
|
|
||||||
static char empty[] = "";
|
|
||||||
char *p;
|
|
||||||
int val;
|
|
||||||
int c;
|
|
||||||
|
|
||||||
if (cmdline)
|
|
||||||
minusc = NULL;
|
|
||||||
while ((p = *argptr) != NULL) {
|
|
||||||
argptr++;
|
|
||||||
if ((c = *p++) == '-') {
|
|
||||||
val = 1;
|
|
||||||
if (p[0] == '\0' || (p[0] == '-' && p[1] == '\0')) {
|
|
||||||
if (!cmdline) {
|
|
||||||
/* "-" means turn off -x and -v */
|
|
||||||
if (p[0] == '\0')
|
|
||||||
xflag = vflag = 0;
|
|
||||||
/* "--" means reset params */
|
|
||||||
else if (*argptr == NULL)
|
|
||||||
setparam(argptr);
|
|
||||||
}
|
|
||||||
break; /* "-" or "--" terminates options */
|
|
||||||
}
|
|
||||||
} else if (c == '+') {
|
|
||||||
val = 0;
|
|
||||||
} else {
|
|
||||||
argptr--;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
while ((c = *p++) != '\0') {
|
|
||||||
if (c == 'c' && cmdline) {
|
|
||||||
/* command is after shell args*/
|
|
||||||
minusc = empty;
|
|
||||||
} else if (c == 'o') {
|
|
||||||
minus_o(*argptr, val);
|
|
||||||
if (*argptr)
|
|
||||||
argptr++;
|
|
||||||
} else {
|
|
||||||
setoption(c, val);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
set_opt_val(int i, int val)
|
|
||||||
{
|
|
||||||
int j;
|
|
||||||
int flag;
|
|
||||||
|
|
||||||
if (val && (flag = optlist[i].opt_set)) {
|
|
||||||
/* some options (eg vi/emacs) are mutually exclusive */
|
|
||||||
for (j = 0; j < NOPTS; j++)
|
|
||||||
if (optlist[j].opt_set == flag)
|
|
||||||
optlist[j].val = 0;
|
|
||||||
}
|
|
||||||
optlist[i].val = val;
|
|
||||||
#ifdef DEBUG
|
|
||||||
if (&optlist[i].val == &debug)
|
|
||||||
opentrace();
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
STATIC void
|
|
||||||
minus_o(char *name, int val)
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
|
|
||||||
if (name == NULL) {
|
|
||||||
out1str("Current option settings\n");
|
|
||||||
for (i = 0; i < NOPTS; i++)
|
|
||||||
out1fmt("%-16s%s\n", optlist[i].name,
|
|
||||||
optlist[i].val ? "on" : "off");
|
|
||||||
} else {
|
|
||||||
for (i = 0; i < NOPTS; i++)
|
|
||||||
if (equal(name, optlist[i].name)) {
|
|
||||||
set_opt_val(i, val);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
error("Illegal option -o %s", name);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
STATIC void
|
|
||||||
setoption(int flag, int val)
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
|
|
||||||
for (i = 0; i < NOPTS; i++)
|
|
||||||
if (optlist[i].letter == flag) {
|
|
||||||
set_opt_val( i, val );
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
error("Illegal option -%c", flag);
|
|
||||||
/* NOTREACHED */
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef mkinit
|
|
||||||
INCLUDE "options.h"
|
|
||||||
|
|
||||||
SHELLPROC {
|
|
||||||
int i;
|
|
||||||
|
|
||||||
for (i = 0; optlist[i].name; i++)
|
|
||||||
optlist[i].val = 0;
|
|
||||||
optschanged();
|
|
||||||
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Set the shell parameters.
|
|
||||||
*/
|
|
||||||
|
|
||||||
void
|
|
||||||
setparam(char **argv)
|
|
||||||
{
|
|
||||||
char **newparam;
|
|
||||||
char **ap;
|
|
||||||
int nparam;
|
|
||||||
|
|
||||||
for (nparam = 0 ; argv[nparam] ; nparam++);
|
|
||||||
ap = newparam = ckmalloc((nparam + 1) * sizeof *ap);
|
|
||||||
while (*argv) {
|
|
||||||
*ap++ = savestr(*argv++);
|
|
||||||
}
|
|
||||||
*ap = NULL;
|
|
||||||
freeparam(&shellparam);
|
|
||||||
shellparam.malloc = 1;
|
|
||||||
shellparam.nparam = nparam;
|
|
||||||
shellparam.p = newparam;
|
|
||||||
shellparam.optnext = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Free the list of positional parameters.
|
|
||||||
*/
|
|
||||||
|
|
||||||
void
|
|
||||||
freeparam(volatile struct shparam *param)
|
|
||||||
{
|
|
||||||
char **ap;
|
|
||||||
|
|
||||||
if (param->malloc) {
|
|
||||||
for (ap = param->p ; *ap ; ap++)
|
|
||||||
ckfree(*ap);
|
|
||||||
ckfree(param->p);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* The shift builtin command.
|
|
||||||
*/
|
|
||||||
|
|
||||||
int
|
|
||||||
shiftcmd(int argc, char **argv)
|
|
||||||
{
|
|
||||||
int n;
|
|
||||||
char **ap1, **ap2;
|
|
||||||
|
|
||||||
n = 1;
|
|
||||||
if (argc > 1)
|
|
||||||
n = number(argv[1]);
|
|
||||||
if (n > shellparam.nparam)
|
|
||||||
error("can't shift that many");
|
|
||||||
INTOFF;
|
|
||||||
shellparam.nparam -= n;
|
|
||||||
for (ap1 = shellparam.p ; --n >= 0 ; ap1++) {
|
|
||||||
if (shellparam.malloc)
|
|
||||||
ckfree(*ap1);
|
|
||||||
}
|
|
||||||
ap2 = shellparam.p;
|
|
||||||
while ((*ap2++ = *ap1++) != NULL);
|
|
||||||
shellparam.optnext = NULL;
|
|
||||||
INTON;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* The set command builtin.
|
|
||||||
*/
|
|
||||||
|
|
||||||
int
|
|
||||||
setcmd(int argc, char **argv)
|
|
||||||
{
|
|
||||||
if (argc == 1)
|
|
||||||
return showvars(0, 0, 1);
|
|
||||||
INTOFF;
|
|
||||||
options(0);
|
|
||||||
optschanged();
|
|
||||||
if (*argptr != NULL) {
|
|
||||||
setparam(argptr);
|
|
||||||
}
|
|
||||||
INTON;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
getoptsreset(value)
|
|
||||||
const char *value;
|
|
||||||
{
|
|
||||||
if (number(value) == 1) {
|
|
||||||
shellparam.optnext = NULL;
|
|
||||||
shellparam.reset = 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* The getopts builtin. Shellparam.optnext points to the next argument
|
|
||||||
* to be processed. Shellparam.optptr points to the next character to
|
|
||||||
* be processed in the current argument. If shellparam.optnext is NULL,
|
|
||||||
* then it's the first time getopts has been called.
|
|
||||||
*/
|
|
||||||
|
|
||||||
int
|
|
||||||
getoptscmd(int argc, char **argv)
|
|
||||||
{
|
|
||||||
char **optbase;
|
|
||||||
|
|
||||||
if (argc < 3)
|
|
||||||
error("usage: getopts optstring var [arg]");
|
|
||||||
else if (argc == 3)
|
|
||||||
optbase = shellparam.p;
|
|
||||||
else
|
|
||||||
optbase = &argv[3];
|
|
||||||
|
|
||||||
if (shellparam.reset == 1) {
|
|
||||||
shellparam.optnext = optbase;
|
|
||||||
shellparam.optptr = NULL;
|
|
||||||
shellparam.reset = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
return getopts(argv[1], argv[2], optbase, &shellparam.optnext,
|
|
||||||
&shellparam.optptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
STATIC int
|
|
||||||
getopts(char *optstr, char *optvar, char **optfirst, char ***optnext, char **optpptr)
|
|
||||||
{
|
|
||||||
char *p, *q;
|
|
||||||
char c = '?';
|
|
||||||
int done = 0;
|
|
||||||
int ind = 0;
|
|
||||||
int err = 0;
|
|
||||||
char s[12];
|
|
||||||
|
|
||||||
if ((p = *optpptr) == NULL || *p == '\0') {
|
|
||||||
/* Current word is done, advance */
|
|
||||||
if (*optnext == NULL)
|
|
||||||
return 1;
|
|
||||||
p = **optnext;
|
|
||||||
if (p == NULL || *p != '-' || *++p == '\0') {
|
|
||||||
atend:
|
|
||||||
ind = *optnext - optfirst + 1;
|
|
||||||
*optnext = NULL;
|
|
||||||
p = NULL;
|
|
||||||
done = 1;
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
(*optnext)++;
|
|
||||||
if (p[0] == '-' && p[1] == '\0') /* check for "--" */
|
|
||||||
goto atend;
|
|
||||||
}
|
|
||||||
|
|
||||||
c = *p++;
|
|
||||||
for (q = optstr; *q != c; ) {
|
|
||||||
if (*q == '\0') {
|
|
||||||
if (optstr[0] == ':') {
|
|
||||||
s[0] = c;
|
|
||||||
s[1] = '\0';
|
|
||||||
err |= setvarsafe("OPTARG", s, 0);
|
|
||||||
} else {
|
|
||||||
outfmt(&errout, "Illegal option -%c\n", c);
|
|
||||||
(void) unsetvar("OPTARG", 0);
|
|
||||||
}
|
|
||||||
c = '?';
|
|
||||||
goto bad;
|
|
||||||
}
|
|
||||||
if (*++q == ':')
|
|
||||||
q++;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (*++q == ':') {
|
|
||||||
if (*p == '\0' && (p = **optnext) == NULL) {
|
|
||||||
if (optstr[0] == ':') {
|
|
||||||
s[0] = c;
|
|
||||||
s[1] = '\0';
|
|
||||||
err |= setvarsafe("OPTARG", s, 0);
|
|
||||||
c = ':';
|
|
||||||
} else {
|
|
||||||
outfmt(&errout, "No arg for -%c option\n", c);
|
|
||||||
(void) unsetvar("OPTARG", 0);
|
|
||||||
c = '?';
|
|
||||||
}
|
|
||||||
goto bad;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (p == **optnext)
|
|
||||||
(*optnext)++;
|
|
||||||
err |= setvarsafe("OPTARG", p, 0);
|
|
||||||
p = NULL;
|
|
||||||
} else
|
|
||||||
err |= setvarsafe("OPTARG", "", 0);
|
|
||||||
ind = *optnext - optfirst + 1;
|
|
||||||
goto out;
|
|
||||||
|
|
||||||
bad:
|
|
||||||
ind = 1;
|
|
||||||
*optnext = NULL;
|
|
||||||
p = NULL;
|
|
||||||
out:
|
|
||||||
*optpptr = p;
|
|
||||||
fmtstr(s, sizeof(s), "%d", ind);
|
|
||||||
err |= setvarsafe("OPTIND", s, VNOFUNC);
|
|
||||||
s[0] = c;
|
|
||||||
s[1] = '\0';
|
|
||||||
err |= setvarsafe(optvar, s, 0);
|
|
||||||
if (err) {
|
|
||||||
*optnext = NULL;
|
|
||||||
*optpptr = NULL;
|
|
||||||
flushall();
|
|
||||||
exraise(EXERROR);
|
|
||||||
}
|
|
||||||
return done;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* XXX - should get rid of. have all builtins use getopt(3). the
|
|
||||||
* library getopt must have the BSD extension static variable "optreset"
|
|
||||||
* otherwise it can't be used within the shell safely.
|
|
||||||
*
|
|
||||||
* Standard option processing (a la getopt) for builtin routines. The
|
|
||||||
* only argument that is passed to nextopt is the option string; the
|
|
||||||
* other arguments are unnecessary. It return the character, or '\0' on
|
|
||||||
* end of input.
|
|
||||||
*/
|
|
||||||
|
|
||||||
int
|
|
||||||
nextopt(const char *optstring)
|
|
||||||
{
|
|
||||||
char *p;
|
|
||||||
const char *q;
|
|
||||||
char c;
|
|
||||||
|
|
||||||
if ((p = optptr) == NULL || *p == '\0') {
|
|
||||||
p = *argptr;
|
|
||||||
if (p == NULL || *p != '-' || *++p == '\0')
|
|
||||||
return '\0';
|
|
||||||
argptr++;
|
|
||||||
if (p[0] == '-' && p[1] == '\0') /* check for "--" */
|
|
||||||
return '\0';
|
|
||||||
}
|
|
||||||
c = *p++;
|
|
||||||
for (q = optstring ; *q != c ; ) {
|
|
||||||
if (*q == '\0')
|
|
||||||
error("Illegal option -%c", c);
|
|
||||||
if (*++q == ':')
|
|
||||||
q++;
|
|
||||||
}
|
|
||||||
if (*++q == ':') {
|
|
||||||
if (*p == '\0' && (p = *argptr++) == NULL)
|
|
||||||
error("No arg for -%c option", c);
|
|
||||||
optionarg = p;
|
|
||||||
p = NULL;
|
|
||||||
}
|
|
||||||
optptr = p;
|
|
||||||
return c;
|
|
||||||
}
|
|
||||||
131
sh/options.h
131
sh/options.h
|
|
@ -1,131 +0,0 @@
|
||||||
/* $NetBSD: options.h,v 1.17 2003/08/07 09:05:36 agc Exp $ */
|
|
||||||
|
|
||||||
/*-
|
|
||||||
* Copyright (c) 1991, 1993
|
|
||||||
* The Regents of the University of California. All rights reserved.
|
|
||||||
*
|
|
||||||
* This code is derived from software contributed to Berkeley by
|
|
||||||
* Kenneth Almquist.
|
|
||||||
*
|
|
||||||
* Redistribution and use in source and binary forms, with or without
|
|
||||||
* modification, are permitted provided that the following conditions
|
|
||||||
* are met:
|
|
||||||
* 1. Redistributions of source code must retain the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer.
|
|
||||||
* 2. Redistributions in binary form must reproduce the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer in the
|
|
||||||
* documentation and/or other materials provided with the distribution.
|
|
||||||
* 3. Neither the name of the University nor the names of its contributors
|
|
||||||
* may be used to endorse or promote products derived from this software
|
|
||||||
* without specific prior written permission.
|
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
|
||||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
||||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
||||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
|
||||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
||||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
|
||||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
|
||||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
||||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
|
||||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
|
||||||
* SUCH DAMAGE.
|
|
||||||
*
|
|
||||||
* @(#)options.h 8.2 (Berkeley) 5/4/95
|
|
||||||
*/
|
|
||||||
|
|
||||||
struct shparam {
|
|
||||||
int nparam; /* # of positional parameters (without $0) */
|
|
||||||
unsigned char malloc; /* if parameter list dynamically allocated */
|
|
||||||
unsigned char reset; /* if getopts has been reset */
|
|
||||||
char **p; /* parameter list */
|
|
||||||
char **optnext; /* next parameter to be processed by getopts */
|
|
||||||
char *optptr; /* used by getopts */
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
struct optent {
|
|
||||||
const char *name; /* for set -o <name> */
|
|
||||||
const char letter; /* set [+/-]<letter> and $- */
|
|
||||||
const char opt_set; /* mutually exclusive option set */
|
|
||||||
char val; /* value of <letter>flag */
|
|
||||||
};
|
|
||||||
|
|
||||||
/* Those marked [U] are required by posix, but have no effect! */
|
|
||||||
|
|
||||||
#ifdef DEFINE_OPTIONS
|
|
||||||
#define DEF_OPTS(name, letter, opt_set) {name, letter, opt_set, 0},
|
|
||||||
struct optent optlist[] = {
|
|
||||||
#else
|
|
||||||
#define DEF_OPTS(name, letter, opt_set)
|
|
||||||
#endif
|
|
||||||
#define DEF_OPT(name,letter) DEF_OPTS(name, letter, 0)
|
|
||||||
|
|
||||||
DEF_OPT( "errexit", 'e' ) /* exit on error */
|
|
||||||
#define eflag optlist[0].val
|
|
||||||
DEF_OPT( "noglob", 'f' ) /* no pathname expansion */
|
|
||||||
#define fflag optlist[1].val
|
|
||||||
DEF_OPT( "ignoreeof", 'I' ) /* do not exit on EOF */
|
|
||||||
#define Iflag optlist[2].val
|
|
||||||
DEF_OPT( "interactive",'i' ) /* interactive shell */
|
|
||||||
#define iflag optlist[3].val
|
|
||||||
DEF_OPT( "monitor", 'm' ) /* job control */
|
|
||||||
#define mflag optlist[4].val
|
|
||||||
DEF_OPT( "noexec", 'n' ) /* [U] do not exec commands */
|
|
||||||
#define nflag optlist[5].val
|
|
||||||
DEF_OPT( "stdin", 's' ) /* read from stdin */
|
|
||||||
#define sflag optlist[6].val
|
|
||||||
DEF_OPT( "xtrace", 'x' ) /* trace after expansion */
|
|
||||||
#define xflag optlist[7].val
|
|
||||||
DEF_OPT( "verbose", 'v' ) /* trace read input */
|
|
||||||
#define vflag optlist[8].val
|
|
||||||
DEF_OPTS( "vi", 'V', 'V' ) /* vi style editing */
|
|
||||||
#define Vflag optlist[9].val
|
|
||||||
DEF_OPTS( "emacs", 'E', 'V' ) /* emacs style editing */
|
|
||||||
#define Eflag optlist[10].val
|
|
||||||
DEF_OPT( "noclobber", 'C' ) /* do not overwrite files with > */
|
|
||||||
#define Cflag optlist[11].val
|
|
||||||
DEF_OPT( "allexport", 'a' ) /* export all variables */
|
|
||||||
#define aflag optlist[12].val
|
|
||||||
DEF_OPT( "notify", 'b' ) /* [U] report completion of background jobs */
|
|
||||||
#define bflag optlist[13].val
|
|
||||||
DEF_OPT( "nounset", 'u' ) /* error expansion of unset variables */
|
|
||||||
#define uflag optlist[14].val
|
|
||||||
DEF_OPT( "quietprofile", 'q' )
|
|
||||||
#define qflag optlist[15].val
|
|
||||||
DEF_OPT( "nolog", 0 ) /* [U] no functon defs in command history */
|
|
||||||
#define nolog optlist[16].val
|
|
||||||
DEF_OPT( "cdprint", 0 ) /* always print result of cd */
|
|
||||||
#define cdprint optlist[17].val
|
|
||||||
#ifdef DEBUG
|
|
||||||
DEF_OPT( "debug", 0 ) /* enable debug prints */
|
|
||||||
#define debug optlist[18].val
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef DEFINE_OPTIONS
|
|
||||||
{ 0, 0, 0, 0 },
|
|
||||||
};
|
|
||||||
#define NOPTS (sizeof optlist / sizeof optlist[0] - 1)
|
|
||||||
int sizeof_optlist = sizeof optlist;
|
|
||||||
#else
|
|
||||||
extern struct optent optlist[];
|
|
||||||
extern int sizeof_optlist;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
extern char *minusc; /* argument to -c option */
|
|
||||||
extern char *arg0; /* $0 */
|
|
||||||
extern struct shparam shellparam; /* $@ */
|
|
||||||
extern char **argptr; /* argument list for builtin commands */
|
|
||||||
extern char *optionarg; /* set by nextopt */
|
|
||||||
extern char *optptr; /* used by nextopt */
|
|
||||||
|
|
||||||
void procargs(int, char **);
|
|
||||||
void optschanged(void);
|
|
||||||
void setparam(char **);
|
|
||||||
void freeparam(volatile struct shparam *);
|
|
||||||
int shiftcmd(int, char **);
|
|
||||||
int setcmd(int, char **);
|
|
||||||
int getoptscmd(int, char **);
|
|
||||||
int nextopt(const char *);
|
|
||||||
void getoptsreset(const char *);
|
|
||||||
516
sh/output.c
516
sh/output.c
|
|
@ -1,516 +0,0 @@
|
||||||
/* $NetBSD: output.c,v 1.28 2003/08/07 09:05:36 agc Exp $ */
|
|
||||||
|
|
||||||
/*-
|
|
||||||
* Copyright (c) 1991, 1993
|
|
||||||
* The Regents of the University of California. All rights reserved.
|
|
||||||
*
|
|
||||||
* This code is derived from software contributed to Berkeley by
|
|
||||||
* Kenneth Almquist.
|
|
||||||
*
|
|
||||||
* Redistribution and use in source and binary forms, with or without
|
|
||||||
* modification, are permitted provided that the following conditions
|
|
||||||
* are met:
|
|
||||||
* 1. Redistributions of source code must retain the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer.
|
|
||||||
* 2. Redistributions in binary form must reproduce the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer in the
|
|
||||||
* documentation and/or other materials provided with the distribution.
|
|
||||||
* 3. Neither the name of the University nor the names of its contributors
|
|
||||||
* may be used to endorse or promote products derived from this software
|
|
||||||
* without specific prior written permission.
|
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
|
||||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
||||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
||||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
|
||||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
||||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
|
||||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
|
||||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
||||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
|
||||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
|
||||||
* SUCH DAMAGE.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <sys/cdefs.h>
|
|
||||||
#ifndef lint
|
|
||||||
#if 0
|
|
||||||
static char sccsid[] = "@(#)output.c 8.2 (Berkeley) 5/4/95";
|
|
||||||
#else
|
|
||||||
__RCSID("$NetBSD: output.c,v 1.28 2003/08/07 09:05:36 agc Exp $");
|
|
||||||
#endif
|
|
||||||
#endif /* not lint */
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Shell output routines. We use our own output routines because:
|
|
||||||
* When a builtin command is interrupted we have to discard
|
|
||||||
* any pending output.
|
|
||||||
* When a builtin command appears in back quotes, we want to
|
|
||||||
* save the output of the command in a region obtained
|
|
||||||
* via malloc, rather than doing a fork and reading the
|
|
||||||
* output of the command via a pipe.
|
|
||||||
* Our output routines may be smaller than the stdio routines.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <sys/types.h> /* quad_t */
|
|
||||||
#include <sys/param.h> /* BSD4_4 */
|
|
||||||
#include <sys/ioctl.h>
|
|
||||||
|
|
||||||
#include <stdio.h> /* defines BUFSIZ */
|
|
||||||
#include <string.h>
|
|
||||||
#include <errno.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
|
|
||||||
#include "shell.h"
|
|
||||||
#include "syntax.h"
|
|
||||||
#include "output.h"
|
|
||||||
#include "memalloc.h"
|
|
||||||
#include "error.h"
|
|
||||||
|
|
||||||
|
|
||||||
#define OUTBUFSIZ BUFSIZ
|
|
||||||
#define BLOCK_OUT -2 /* output to a fixed block of memory */
|
|
||||||
#define MEM_OUT -3 /* output to dynamically allocated memory */
|
|
||||||
#define OUTPUT_ERR 01 /* error occurred on output */
|
|
||||||
|
|
||||||
|
|
||||||
struct output output = {NULL, 0, NULL, OUTBUFSIZ, 1, 0};
|
|
||||||
struct output errout = {NULL, 0, NULL, 100, 2, 0};
|
|
||||||
struct output memout = {NULL, 0, NULL, 0, MEM_OUT, 0};
|
|
||||||
struct output *out1 = &output;
|
|
||||||
struct output *out2 = &errout;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef mkinit
|
|
||||||
|
|
||||||
INCLUDE "output.h"
|
|
||||||
INCLUDE "memalloc.h"
|
|
||||||
|
|
||||||
RESET {
|
|
||||||
out1 = &output;
|
|
||||||
out2 = &errout;
|
|
||||||
if (memout.buf != NULL) {
|
|
||||||
ckfree(memout.buf);
|
|
||||||
memout.buf = NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef notdef /* no longer used */
|
|
||||||
/*
|
|
||||||
* Set up an output file to write to memory rather than a file.
|
|
||||||
*/
|
|
||||||
|
|
||||||
void
|
|
||||||
open_mem(char *block, int length, struct output *file)
|
|
||||||
{
|
|
||||||
file->nextc = block;
|
|
||||||
file->nleft = --length;
|
|
||||||
file->fd = BLOCK_OUT;
|
|
||||||
file->flags = 0;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
out1str(const char *p)
|
|
||||||
{
|
|
||||||
outstr(p, out1);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
out2str(const char *p)
|
|
||||||
{
|
|
||||||
outstr(p, out2);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
outstr(const char *p, struct output *file)
|
|
||||||
{
|
|
||||||
while (*p)
|
|
||||||
outc(*p++, file);
|
|
||||||
if (file == out2)
|
|
||||||
flushout(file);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
char out_junk[16];
|
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
emptyoutbuf(struct output *dest)
|
|
||||||
{
|
|
||||||
int offset;
|
|
||||||
|
|
||||||
if (dest->fd == BLOCK_OUT) {
|
|
||||||
dest->nextc = out_junk;
|
|
||||||
dest->nleft = sizeof out_junk;
|
|
||||||
dest->flags |= OUTPUT_ERR;
|
|
||||||
} else if (dest->buf == NULL) {
|
|
||||||
INTOFF;
|
|
||||||
dest->buf = ckmalloc(dest->bufsize);
|
|
||||||
dest->nextc = dest->buf;
|
|
||||||
dest->nleft = dest->bufsize;
|
|
||||||
INTON;
|
|
||||||
} else if (dest->fd == MEM_OUT) {
|
|
||||||
offset = dest->bufsize;
|
|
||||||
INTOFF;
|
|
||||||
dest->bufsize <<= 1;
|
|
||||||
dest->buf = ckrealloc(dest->buf, dest->bufsize);
|
|
||||||
dest->nleft = dest->bufsize - offset;
|
|
||||||
dest->nextc = dest->buf + offset;
|
|
||||||
INTON;
|
|
||||||
} else {
|
|
||||||
flushout(dest);
|
|
||||||
}
|
|
||||||
dest->nleft--;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
flushall(void)
|
|
||||||
{
|
|
||||||
flushout(&output);
|
|
||||||
flushout(&errout);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
flushout(struct output *dest)
|
|
||||||
{
|
|
||||||
|
|
||||||
if (dest->buf == NULL || dest->nextc == dest->buf || dest->fd < 0)
|
|
||||||
return;
|
|
||||||
if (xwrite(dest->fd, dest->buf, dest->nextc - dest->buf) < 0)
|
|
||||||
dest->flags |= OUTPUT_ERR;
|
|
||||||
dest->nextc = dest->buf;
|
|
||||||
dest->nleft = dest->bufsize;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
freestdout(void)
|
|
||||||
{
|
|
||||||
INTOFF;
|
|
||||||
if (output.buf) {
|
|
||||||
ckfree(output.buf);
|
|
||||||
output.buf = NULL;
|
|
||||||
output.nleft = 0;
|
|
||||||
}
|
|
||||||
INTON;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
outfmt(struct output *file, const char *fmt, ...)
|
|
||||||
{
|
|
||||||
va_list ap;
|
|
||||||
|
|
||||||
va_start(ap, fmt);
|
|
||||||
doformat(file, fmt, ap);
|
|
||||||
va_end(ap);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
out1fmt(const char *fmt, ...)
|
|
||||||
{
|
|
||||||
va_list ap;
|
|
||||||
|
|
||||||
va_start(ap, fmt);
|
|
||||||
doformat(out1, fmt, ap);
|
|
||||||
va_end(ap);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
dprintf(const char *fmt, ...)
|
|
||||||
{
|
|
||||||
va_list ap;
|
|
||||||
|
|
||||||
va_start(ap, fmt);
|
|
||||||
doformat(out2, fmt, ap);
|
|
||||||
va_end(ap);
|
|
||||||
flushout(out2);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
fmtstr(char *outbuf, size_t length, const char *fmt, ...)
|
|
||||||
{
|
|
||||||
va_list ap;
|
|
||||||
struct output strout;
|
|
||||||
|
|
||||||
va_start(ap, fmt);
|
|
||||||
strout.nextc = outbuf;
|
|
||||||
strout.nleft = length;
|
|
||||||
strout.fd = BLOCK_OUT;
|
|
||||||
strout.flags = 0;
|
|
||||||
doformat(&strout, fmt, ap);
|
|
||||||
outc('\0', &strout);
|
|
||||||
if (strout.flags & OUTPUT_ERR)
|
|
||||||
outbuf[length - 1] = '\0';
|
|
||||||
va_end(ap);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Formatted output. This routine handles a subset of the printf formats:
|
|
||||||
* - Formats supported: d, u, o, p, X, s, and c.
|
|
||||||
* - The x format is also accepted but is treated like X.
|
|
||||||
* - The l, ll and q modifiers are accepted.
|
|
||||||
* - The - and # flags are accepted; # only works with the o format.
|
|
||||||
* - Width and precision may be specified with any format except c.
|
|
||||||
* - An * may be given for the width or precision.
|
|
||||||
* - The obsolete practice of preceding the width with a zero to get
|
|
||||||
* zero padding is not supported; use the precision field.
|
|
||||||
* - A % may be printed by writing %% in the format string.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#define TEMPSIZE 24
|
|
||||||
|
|
||||||
#ifdef BSD4_4
|
|
||||||
#define HAVE_VASPRINTF 1
|
|
||||||
#endif
|
|
||||||
|
|
||||||
void
|
|
||||||
doformat(struct output *dest, const char *f, va_list ap)
|
|
||||||
{
|
|
||||||
#if HAVE_VASPRINTF
|
|
||||||
char *s;
|
|
||||||
|
|
||||||
vasprintf(&s, f, ap);
|
|
||||||
outstr(s, dest);
|
|
||||||
free(s);
|
|
||||||
#else /* !HAVE_VASPRINTF */
|
|
||||||
static const char digit[] = "0123456789ABCDEF";
|
|
||||||
char c;
|
|
||||||
char temp[TEMPSIZE];
|
|
||||||
int flushleft;
|
|
||||||
int sharp;
|
|
||||||
int width;
|
|
||||||
int prec;
|
|
||||||
int islong;
|
|
||||||
int isquad;
|
|
||||||
char *p;
|
|
||||||
int sign;
|
|
||||||
#ifdef BSD4_4
|
|
||||||
quad_t l;
|
|
||||||
u_quad_t num;
|
|
||||||
#else
|
|
||||||
long l;
|
|
||||||
u_long num;
|
|
||||||
#endif
|
|
||||||
unsigned base;
|
|
||||||
int len;
|
|
||||||
int size;
|
|
||||||
int pad;
|
|
||||||
|
|
||||||
while ((c = *f++) != '\0') {
|
|
||||||
if (c != '%') {
|
|
||||||
outc(c, dest);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
flushleft = 0;
|
|
||||||
sharp = 0;
|
|
||||||
width = 0;
|
|
||||||
prec = -1;
|
|
||||||
islong = 0;
|
|
||||||
isquad = 0;
|
|
||||||
for (;;) {
|
|
||||||
if (*f == '-')
|
|
||||||
flushleft++;
|
|
||||||
else if (*f == '#')
|
|
||||||
sharp++;
|
|
||||||
else
|
|
||||||
break;
|
|
||||||
f++;
|
|
||||||
}
|
|
||||||
if (*f == '*') {
|
|
||||||
width = va_arg(ap, int);
|
|
||||||
f++;
|
|
||||||
} else {
|
|
||||||
while (is_digit(*f)) {
|
|
||||||
width = 10 * width + digit_val(*f++);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (*f == '.') {
|
|
||||||
if (*++f == '*') {
|
|
||||||
prec = va_arg(ap, int);
|
|
||||||
f++;
|
|
||||||
} else {
|
|
||||||
prec = 0;
|
|
||||||
while (is_digit(*f)) {
|
|
||||||
prec = 10 * prec + digit_val(*f++);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (*f == 'l') {
|
|
||||||
f++;
|
|
||||||
if (*f == 'l') {
|
|
||||||
isquad++;
|
|
||||||
f++;
|
|
||||||
} else
|
|
||||||
islong++;
|
|
||||||
} else if (*f == 'q') {
|
|
||||||
isquad++;
|
|
||||||
f++;
|
|
||||||
}
|
|
||||||
switch (*f) {
|
|
||||||
case 'd':
|
|
||||||
#ifdef BSD4_4
|
|
||||||
if (isquad)
|
|
||||||
l = va_arg(ap, quad_t);
|
|
||||||
else
|
|
||||||
#endif
|
|
||||||
if (islong)
|
|
||||||
l = va_arg(ap, long);
|
|
||||||
else
|
|
||||||
l = va_arg(ap, int);
|
|
||||||
sign = 0;
|
|
||||||
num = l;
|
|
||||||
if (l < 0) {
|
|
||||||
num = -l;
|
|
||||||
sign = 1;
|
|
||||||
}
|
|
||||||
base = 10;
|
|
||||||
goto number;
|
|
||||||
case 'u':
|
|
||||||
base = 10;
|
|
||||||
goto uns_number;
|
|
||||||
case 'o':
|
|
||||||
base = 8;
|
|
||||||
goto uns_number;
|
|
||||||
case 'p':
|
|
||||||
outc('0', dest);
|
|
||||||
outc('x', dest);
|
|
||||||
/*FALLTHROUGH*/
|
|
||||||
case 'x':
|
|
||||||
/* we don't implement 'x'; treat like 'X' */
|
|
||||||
case 'X':
|
|
||||||
base = 16;
|
|
||||||
uns_number: /* an unsigned number */
|
|
||||||
sign = 0;
|
|
||||||
#ifdef BSD4_4
|
|
||||||
if (isquad)
|
|
||||||
num = va_arg(ap, u_quad_t);
|
|
||||||
else
|
|
||||||
#endif
|
|
||||||
if (islong)
|
|
||||||
num = va_arg(ap, unsigned long);
|
|
||||||
else
|
|
||||||
num = va_arg(ap, unsigned int);
|
|
||||||
number: /* process a number */
|
|
||||||
p = temp + TEMPSIZE - 1;
|
|
||||||
*p = '\0';
|
|
||||||
while (num) {
|
|
||||||
*--p = digit[num % base];
|
|
||||||
num /= base;
|
|
||||||
}
|
|
||||||
len = (temp + TEMPSIZE - 1) - p;
|
|
||||||
if (prec < 0)
|
|
||||||
prec = 1;
|
|
||||||
if (sharp && *f == 'o' && prec <= len)
|
|
||||||
prec = len + 1;
|
|
||||||
pad = 0;
|
|
||||||
if (width) {
|
|
||||||
size = len;
|
|
||||||
if (size < prec)
|
|
||||||
size = prec;
|
|
||||||
size += sign;
|
|
||||||
pad = width - size;
|
|
||||||
if (flushleft == 0) {
|
|
||||||
while (--pad >= 0)
|
|
||||||
outc(' ', dest);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (sign)
|
|
||||||
outc('-', dest);
|
|
||||||
prec -= len;
|
|
||||||
while (--prec >= 0)
|
|
||||||
outc('0', dest);
|
|
||||||
while (*p)
|
|
||||||
outc(*p++, dest);
|
|
||||||
while (--pad >= 0)
|
|
||||||
outc(' ', dest);
|
|
||||||
break;
|
|
||||||
case 's':
|
|
||||||
p = va_arg(ap, char *);
|
|
||||||
pad = 0;
|
|
||||||
if (width) {
|
|
||||||
len = strlen(p);
|
|
||||||
if (prec >= 0 && len > prec)
|
|
||||||
len = prec;
|
|
||||||
pad = width - len;
|
|
||||||
if (flushleft == 0) {
|
|
||||||
while (--pad >= 0)
|
|
||||||
outc(' ', dest);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
prec++;
|
|
||||||
while (--prec != 0 && *p)
|
|
||||||
outc(*p++, dest);
|
|
||||||
while (--pad >= 0)
|
|
||||||
outc(' ', dest);
|
|
||||||
break;
|
|
||||||
case 'c':
|
|
||||||
c = va_arg(ap, int);
|
|
||||||
outc(c, dest);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
outc(*f, dest);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
f++;
|
|
||||||
}
|
|
||||||
#endif /* !HAVE_VASPRINTF */
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Version of write which resumes after a signal is caught.
|
|
||||||
*/
|
|
||||||
|
|
||||||
int
|
|
||||||
xwrite(int fd, char *buf, int nbytes)
|
|
||||||
{
|
|
||||||
int ntry;
|
|
||||||
int i;
|
|
||||||
int n;
|
|
||||||
|
|
||||||
n = nbytes;
|
|
||||||
ntry = 0;
|
|
||||||
for (;;) {
|
|
||||||
i = write(fd, buf, n);
|
|
||||||
if (i > 0) {
|
|
||||||
if ((n -= i) <= 0)
|
|
||||||
return nbytes;
|
|
||||||
buf += i;
|
|
||||||
ntry = 0;
|
|
||||||
} else if (i == 0) {
|
|
||||||
if (++ntry > 10)
|
|
||||||
return nbytes - n;
|
|
||||||
} else if (errno != EINTR) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Version of ioctl that retries after a signal is caught.
|
|
||||||
* XXX unused function
|
|
||||||
*/
|
|
||||||
|
|
||||||
int
|
|
||||||
xioctl(int fd, unsigned long request, char *arg)
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
|
|
||||||
while ((i = ioctl(fd, request, arg)) == -1 && errno == EINTR);
|
|
||||||
return i;
|
|
||||||
}
|
|
||||||
81
sh/output.h
81
sh/output.h
|
|
@ -1,81 +0,0 @@
|
||||||
/* $NetBSD: output.h,v 1.17 2003/08/07 09:05:36 agc Exp $ */
|
|
||||||
|
|
||||||
/*-
|
|
||||||
* Copyright (c) 1991, 1993
|
|
||||||
* The Regents of the University of California. All rights reserved.
|
|
||||||
*
|
|
||||||
* This code is derived from software contributed to Berkeley by
|
|
||||||
* Kenneth Almquist.
|
|
||||||
*
|
|
||||||
* Redistribution and use in source and binary forms, with or without
|
|
||||||
* modification, are permitted provided that the following conditions
|
|
||||||
* are met:
|
|
||||||
* 1. Redistributions of source code must retain the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer.
|
|
||||||
* 2. Redistributions in binary form must reproduce the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer in the
|
|
||||||
* documentation and/or other materials provided with the distribution.
|
|
||||||
* 3. Neither the name of the University nor the names of its contributors
|
|
||||||
* may be used to endorse or promote products derived from this software
|
|
||||||
* without specific prior written permission.
|
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
|
||||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
||||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
||||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
|
||||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
||||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
|
||||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
|
||||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
||||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
|
||||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
|
||||||
* SUCH DAMAGE.
|
|
||||||
*
|
|
||||||
* @(#)output.h 8.2 (Berkeley) 5/4/95
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef OUTPUT_INCL
|
|
||||||
|
|
||||||
#include <stdarg.h>
|
|
||||||
|
|
||||||
struct output {
|
|
||||||
char *nextc;
|
|
||||||
int nleft;
|
|
||||||
char *buf;
|
|
||||||
int bufsize;
|
|
||||||
short fd;
|
|
||||||
short flags;
|
|
||||||
};
|
|
||||||
|
|
||||||
extern struct output output;
|
|
||||||
extern struct output errout;
|
|
||||||
extern struct output memout;
|
|
||||||
extern struct output *out1;
|
|
||||||
extern struct output *out2;
|
|
||||||
|
|
||||||
void open_mem(char *, int, struct output *);
|
|
||||||
void out1str(const char *);
|
|
||||||
void out2str(const char *);
|
|
||||||
void outstr(const char *, struct output *);
|
|
||||||
void emptyoutbuf(struct output *);
|
|
||||||
void flushall(void);
|
|
||||||
void flushout(struct output *);
|
|
||||||
void freestdout(void);
|
|
||||||
void outfmt(struct output *, const char *, ...)
|
|
||||||
__attribute__((__format__(__printf__,2,3)));
|
|
||||||
void out1fmt(const char *, ...)
|
|
||||||
__attribute__((__format__(__printf__,1,2)));
|
|
||||||
void dprintf(const char *, ...)
|
|
||||||
__attribute__((__format__(__printf__,1,2)));
|
|
||||||
void fmtstr(char *, size_t, const char *, ...)
|
|
||||||
__attribute__((__format__(__printf__,3,4)));
|
|
||||||
void doformat(struct output *, const char *, va_list);
|
|
||||||
int xwrite(int, char *, int);
|
|
||||||
int xioctl(int, unsigned long, char *);
|
|
||||||
|
|
||||||
#define outc(c, file) (--(file)->nleft < 0? (emptyoutbuf(file), *(file)->nextc++ = (c)) : (*(file)->nextc++ = (c)))
|
|
||||||
#define out1c(c) outc(c, out1);
|
|
||||||
#define out2c(c) outc(c, out2);
|
|
||||||
|
|
||||||
#define OUTPUT_INCL
|
|
||||||
#endif
|
|
||||||
1654
sh/parser.c
1654
sh/parser.c
File diff suppressed because it is too large
Load diff
82
sh/parser.h
82
sh/parser.h
|
|
@ -1,82 +0,0 @@
|
||||||
/* $NetBSD: parser.h,v 1.17 2004/06/26 22:09:49 dsl Exp $ */
|
|
||||||
|
|
||||||
/*-
|
|
||||||
* Copyright (c) 1991, 1993
|
|
||||||
* The Regents of the University of California. All rights reserved.
|
|
||||||
*
|
|
||||||
* This code is derived from software contributed to Berkeley by
|
|
||||||
* Kenneth Almquist.
|
|
||||||
*
|
|
||||||
* Redistribution and use in source and binary forms, with or without
|
|
||||||
* modification, are permitted provided that the following conditions
|
|
||||||
* are met:
|
|
||||||
* 1. Redistributions of source code must retain the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer.
|
|
||||||
* 2. Redistributions in binary form must reproduce the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer in the
|
|
||||||
* documentation and/or other materials provided with the distribution.
|
|
||||||
* 3. Neither the name of the University nor the names of its contributors
|
|
||||||
* may be used to endorse or promote products derived from this software
|
|
||||||
* without specific prior written permission.
|
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
|
||||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
||||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
||||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
|
||||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
||||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
|
||||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
|
||||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
||||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
|
||||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
|
||||||
* SUCH DAMAGE.
|
|
||||||
*
|
|
||||||
* @(#)parser.h 8.3 (Berkeley) 5/4/95
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* control characters in argument strings */
|
|
||||||
#define CTL_FIRST '\201' /* first 'special' character */
|
|
||||||
#define CTLESC '\201' /* escape next character */
|
|
||||||
#define CTLVAR '\202' /* variable defn */
|
|
||||||
#define CTLENDVAR '\203'
|
|
||||||
#define CTLBACKQ '\204'
|
|
||||||
#define CTLQUOTE 01 /* ored with CTLBACKQ code if in quotes */
|
|
||||||
/* CTLBACKQ | CTLQUOTE == '\205' */
|
|
||||||
#define CTLARI '\206' /* arithmetic expression */
|
|
||||||
#define CTLENDARI '\207'
|
|
||||||
#define CTLQUOTEMARK '\210'
|
|
||||||
#define CTLQUOTEEND '\211' /* only inside ${...} */
|
|
||||||
#define CTL_LAST '\211' /* last 'special' character */
|
|
||||||
|
|
||||||
/* variable substitution byte (follows CTLVAR) */
|
|
||||||
#define VSTYPE 0x0f /* type of variable substitution */
|
|
||||||
#define VSNUL 0x10 /* colon--treat the empty string as unset */
|
|
||||||
#define VSQUOTE 0x80 /* inside double quotes--suppress splitting */
|
|
||||||
|
|
||||||
/* values of VSTYPE field */
|
|
||||||
#define VSNORMAL 0x1 /* normal variable: $var or ${var} */
|
|
||||||
#define VSMINUS 0x2 /* ${var-text} */
|
|
||||||
#define VSPLUS 0x3 /* ${var+text} */
|
|
||||||
#define VSQUESTION 0x4 /* ${var?message} */
|
|
||||||
#define VSASSIGN 0x5 /* ${var=text} */
|
|
||||||
#define VSTRIMLEFT 0x6 /* ${var#pattern} */
|
|
||||||
#define VSTRIMLEFTMAX 0x7 /* ${var##pattern} */
|
|
||||||
#define VSTRIMRIGHT 0x8 /* ${var%pattern} */
|
|
||||||
#define VSTRIMRIGHTMAX 0x9 /* ${var%%pattern} */
|
|
||||||
#define VSLENGTH 0xa /* ${#var} */
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* NEOF is returned by parsecmd when it encounters an end of file. It
|
|
||||||
* must be distinct from NULL, so we use the address of a variable that
|
|
||||||
* happens to be handy.
|
|
||||||
*/
|
|
||||||
extern int tokpushback;
|
|
||||||
#define NEOF ((union node *)&tokpushback)
|
|
||||||
extern int whichprompt; /* 1 == PS1, 2 == PS2 */
|
|
||||||
|
|
||||||
|
|
||||||
union node *parsecmd(int);
|
|
||||||
void fixredir(union node *, const char *, int);
|
|
||||||
int goodname(char *);
|
|
||||||
const char *getprompt(void *);
|
|
||||||
389
sh/redir.c
389
sh/redir.c
|
|
@ -1,389 +0,0 @@
|
||||||
/* $NetBSD: redir.c,v 1.29 2004/07/08 03:57:33 christos Exp $ */
|
|
||||||
|
|
||||||
/*-
|
|
||||||
* Copyright (c) 1991, 1993
|
|
||||||
* The Regents of the University of California. All rights reserved.
|
|
||||||
*
|
|
||||||
* This code is derived from software contributed to Berkeley by
|
|
||||||
* Kenneth Almquist.
|
|
||||||
*
|
|
||||||
* Redistribution and use in source and binary forms, with or without
|
|
||||||
* modification, are permitted provided that the following conditions
|
|
||||||
* are met:
|
|
||||||
* 1. Redistributions of source code must retain the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer.
|
|
||||||
* 2. Redistributions in binary form must reproduce the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer in the
|
|
||||||
* documentation and/or other materials provided with the distribution.
|
|
||||||
* 3. Neither the name of the University nor the names of its contributors
|
|
||||||
* may be used to endorse or promote products derived from this software
|
|
||||||
* without specific prior written permission.
|
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
|
||||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
||||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
||||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
|
||||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
||||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
|
||||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
|
||||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
||||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
|
||||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
|
||||||
* SUCH DAMAGE.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <sys/cdefs.h>
|
|
||||||
#ifndef lint
|
|
||||||
#if 0
|
|
||||||
static char sccsid[] = "@(#)redir.c 8.2 (Berkeley) 5/4/95";
|
|
||||||
#else
|
|
||||||
__RCSID("$NetBSD: redir.c,v 1.29 2004/07/08 03:57:33 christos Exp $");
|
|
||||||
#endif
|
|
||||||
#endif /* not lint */
|
|
||||||
|
|
||||||
#include <sys/types.h>
|
|
||||||
#include <sys/param.h> /* PIPE_BUF */
|
|
||||||
#include <signal.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <fcntl.h>
|
|
||||||
#include <errno.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Code for dealing with input/output redirection.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "main.h"
|
|
||||||
#include "shell.h"
|
|
||||||
#include "nodes.h"
|
|
||||||
#include "jobs.h"
|
|
||||||
#include "options.h"
|
|
||||||
#include "expand.h"
|
|
||||||
#include "redir.h"
|
|
||||||
#include "output.h"
|
|
||||||
#include "memalloc.h"
|
|
||||||
#include "error.h"
|
|
||||||
|
|
||||||
|
|
||||||
#define EMPTY -2 /* marks an unused slot in redirtab */
|
|
||||||
#ifndef PIPE_BUF
|
|
||||||
# define PIPESIZE 4096 /* amount of buffering in a pipe */
|
|
||||||
#else
|
|
||||||
# define PIPESIZE PIPE_BUF
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define signal bsd_signal
|
|
||||||
|
|
||||||
MKINIT
|
|
||||||
struct redirtab {
|
|
||||||
struct redirtab *next;
|
|
||||||
short renamed[10];
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
MKINIT struct redirtab *redirlist;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* We keep track of whether or not fd0 has been redirected. This is for
|
|
||||||
* background commands, where we want to redirect fd0 to /dev/null only
|
|
||||||
* if it hasn't already been redirected.
|
|
||||||
*/
|
|
||||||
int fd0_redirected = 0;
|
|
||||||
|
|
||||||
STATIC void openredirect(union node *, char[10], int);
|
|
||||||
STATIC int openhere(union node *);
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Process a list of redirection commands. If the REDIR_PUSH flag is set,
|
|
||||||
* old file descriptors are stashed away so that the redirection can be
|
|
||||||
* undone by calling popredir. If the REDIR_BACKQ flag is set, then the
|
|
||||||
* standard output, and the standard error if it becomes a duplicate of
|
|
||||||
* stdout, is saved in memory.
|
|
||||||
*/
|
|
||||||
|
|
||||||
void
|
|
||||||
redirect(union node *redir, int flags)
|
|
||||||
{
|
|
||||||
union node *n;
|
|
||||||
struct redirtab *sv = NULL;
|
|
||||||
int i;
|
|
||||||
int fd;
|
|
||||||
int try;
|
|
||||||
char memory[10]; /* file descriptors to write to memory */
|
|
||||||
|
|
||||||
for (i = 10 ; --i >= 0 ; )
|
|
||||||
memory[i] = 0;
|
|
||||||
memory[1] = flags & REDIR_BACKQ;
|
|
||||||
if (flags & REDIR_PUSH) {
|
|
||||||
/* We don't have to worry about REDIR_VFORK here, as
|
|
||||||
* flags & REDIR_PUSH is never true if REDIR_VFORK is set.
|
|
||||||
*/
|
|
||||||
sv = ckmalloc(sizeof (struct redirtab));
|
|
||||||
for (i = 0 ; i < 10 ; i++)
|
|
||||||
sv->renamed[i] = EMPTY;
|
|
||||||
sv->next = redirlist;
|
|
||||||
redirlist = sv;
|
|
||||||
}
|
|
||||||
for (n = redir ; n ; n = n->nfile.next) {
|
|
||||||
fd = n->nfile.fd;
|
|
||||||
try = 0;
|
|
||||||
if ((n->nfile.type == NTOFD || n->nfile.type == NFROMFD) &&
|
|
||||||
n->ndup.dupfd == fd)
|
|
||||||
continue; /* redirect from/to same file descriptor */
|
|
||||||
|
|
||||||
if ((flags & REDIR_PUSH) && sv->renamed[fd] == EMPTY) {
|
|
||||||
INTOFF;
|
|
||||||
again:
|
|
||||||
if ((i = fcntl(fd, F_DUPFD, 10)) == -1) {
|
|
||||||
switch (errno) {
|
|
||||||
case EBADF:
|
|
||||||
if (!try) {
|
|
||||||
openredirect(n, memory, flags);
|
|
||||||
try++;
|
|
||||||
goto again;
|
|
||||||
}
|
|
||||||
/* FALLTHROUGH*/
|
|
||||||
default:
|
|
||||||
INTON;
|
|
||||||
error("%d: %s", fd, strerror(errno));
|
|
||||||
/* NOTREACHED */
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!try) {
|
|
||||||
sv->renamed[fd] = i;
|
|
||||||
close(fd);
|
|
||||||
}
|
|
||||||
INTON;
|
|
||||||
} else {
|
|
||||||
close(fd);
|
|
||||||
}
|
|
||||||
if (fd == 0)
|
|
||||||
fd0_redirected++;
|
|
||||||
if (!try)
|
|
||||||
openredirect(n, memory, flags);
|
|
||||||
}
|
|
||||||
if (memory[1])
|
|
||||||
out1 = &memout;
|
|
||||||
if (memory[2])
|
|
||||||
out2 = &memout;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
STATIC void
|
|
||||||
openredirect(union node *redir, char memory[10], int flags)
|
|
||||||
{
|
|
||||||
int fd = redir->nfile.fd;
|
|
||||||
char *fname;
|
|
||||||
int f;
|
|
||||||
int oflags = O_WRONLY|O_CREAT|O_TRUNC, eflags;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* We suppress interrupts so that we won't leave open file
|
|
||||||
* descriptors around. This may not be such a good idea because
|
|
||||||
* an open of a device or a fifo can block indefinitely.
|
|
||||||
*/
|
|
||||||
INTOFF;
|
|
||||||
memory[fd] = 0;
|
|
||||||
switch (redir->nfile.type) {
|
|
||||||
case NFROM:
|
|
||||||
fname = redir->nfile.expfname;
|
|
||||||
if (flags & REDIR_VFORK)
|
|
||||||
eflags = O_NONBLOCK;
|
|
||||||
else
|
|
||||||
eflags = 0;
|
|
||||||
if ((f = open(fname, O_RDONLY|eflags)) < 0)
|
|
||||||
goto eopen;
|
|
||||||
if (eflags)
|
|
||||||
(void)fcntl(f, F_SETFL, fcntl(f, F_GETFL, 0) & ~eflags);
|
|
||||||
break;
|
|
||||||
case NFROMTO:
|
|
||||||
fname = redir->nfile.expfname;
|
|
||||||
if ((f = open(fname, O_RDWR|O_CREAT|O_TRUNC, 0666)) < 0)
|
|
||||||
goto ecreate;
|
|
||||||
break;
|
|
||||||
case NTO:
|
|
||||||
if (Cflag)
|
|
||||||
oflags |= O_EXCL;
|
|
||||||
/* FALLTHROUGH */
|
|
||||||
case NCLOBBER:
|
|
||||||
fname = redir->nfile.expfname;
|
|
||||||
if ((f = open(fname, oflags, 0666)) < 0)
|
|
||||||
goto ecreate;
|
|
||||||
break;
|
|
||||||
case NAPPEND:
|
|
||||||
fname = redir->nfile.expfname;
|
|
||||||
if ((f = open(fname, O_WRONLY|O_CREAT|O_APPEND, 0666)) < 0)
|
|
||||||
goto ecreate;
|
|
||||||
break;
|
|
||||||
case NTOFD:
|
|
||||||
case NFROMFD:
|
|
||||||
if (redir->ndup.dupfd >= 0) { /* if not ">&-" */
|
|
||||||
if (memory[redir->ndup.dupfd])
|
|
||||||
memory[fd] = 1;
|
|
||||||
else
|
|
||||||
copyfd(redir->ndup.dupfd, fd);
|
|
||||||
}
|
|
||||||
INTON;
|
|
||||||
return;
|
|
||||||
case NHERE:
|
|
||||||
case NXHERE:
|
|
||||||
f = openhere(redir);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
abort();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (f != fd) {
|
|
||||||
copyfd(f, fd);
|
|
||||||
close(f);
|
|
||||||
}
|
|
||||||
INTON;
|
|
||||||
return;
|
|
||||||
ecreate:
|
|
||||||
error("cannot create %s: %s", fname, errmsg(errno, E_CREAT));
|
|
||||||
eopen:
|
|
||||||
error("cannot open %s: %s", fname, errmsg(errno, E_OPEN));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Handle here documents. Normally we fork off a process to write the
|
|
||||||
* data to a pipe. If the document is short, we can stuff the data in
|
|
||||||
* the pipe without forking.
|
|
||||||
*/
|
|
||||||
|
|
||||||
STATIC int
|
|
||||||
openhere(union node *redir)
|
|
||||||
{
|
|
||||||
int pip[2];
|
|
||||||
int len = 0;
|
|
||||||
|
|
||||||
if (pipe(pip) < 0)
|
|
||||||
error("Pipe call failed");
|
|
||||||
if (redir->type == NHERE) {
|
|
||||||
len = strlen(redir->nhere.doc->narg.text);
|
|
||||||
if (len <= PIPESIZE) {
|
|
||||||
xwrite(pip[1], redir->nhere.doc->narg.text, len);
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (forkshell((struct job *)NULL, (union node *)NULL, FORK_NOJOB) == 0) {
|
|
||||||
close(pip[0]);
|
|
||||||
signal(SIGINT, SIG_IGN);
|
|
||||||
signal(SIGQUIT, SIG_IGN);
|
|
||||||
signal(SIGHUP, SIG_IGN);
|
|
||||||
#ifdef SIGTSTP
|
|
||||||
signal(SIGTSTP, SIG_IGN);
|
|
||||||
#endif
|
|
||||||
signal(SIGPIPE, SIG_DFL);
|
|
||||||
if (redir->type == NHERE)
|
|
||||||
xwrite(pip[1], redir->nhere.doc->narg.text, len);
|
|
||||||
else
|
|
||||||
expandhere(redir->nhere.doc, pip[1]);
|
|
||||||
_exit(0);
|
|
||||||
}
|
|
||||||
out:
|
|
||||||
close(pip[1]);
|
|
||||||
return pip[0];
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Undo the effects of the last redirection.
|
|
||||||
*/
|
|
||||||
|
|
||||||
void
|
|
||||||
popredir(void)
|
|
||||||
{
|
|
||||||
struct redirtab *rp = redirlist;
|
|
||||||
int i;
|
|
||||||
|
|
||||||
for (i = 0 ; i < 10 ; i++) {
|
|
||||||
if (rp->renamed[i] != EMPTY) {
|
|
||||||
if (i == 0)
|
|
||||||
fd0_redirected--;
|
|
||||||
close(i);
|
|
||||||
if (rp->renamed[i] >= 0) {
|
|
||||||
copyfd(rp->renamed[i], i);
|
|
||||||
close(rp->renamed[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
INTOFF;
|
|
||||||
redirlist = rp->next;
|
|
||||||
ckfree(rp);
|
|
||||||
INTON;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Undo all redirections. Called on error or interrupt.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifdef mkinit
|
|
||||||
|
|
||||||
INCLUDE "redir.h"
|
|
||||||
|
|
||||||
RESET {
|
|
||||||
while (redirlist)
|
|
||||||
popredir();
|
|
||||||
}
|
|
||||||
|
|
||||||
SHELLPROC {
|
|
||||||
clearredir(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Return true if fd 0 has already been redirected at least once. */
|
|
||||||
int
|
|
||||||
fd0_redirected_p () {
|
|
||||||
return fd0_redirected != 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Discard all saved file descriptors.
|
|
||||||
*/
|
|
||||||
|
|
||||||
void
|
|
||||||
clearredir(vforked)
|
|
||||||
int vforked;
|
|
||||||
{
|
|
||||||
struct redirtab *rp;
|
|
||||||
int i;
|
|
||||||
|
|
||||||
for (rp = redirlist ; rp ; rp = rp->next) {
|
|
||||||
for (i = 0 ; i < 10 ; i++) {
|
|
||||||
if (rp->renamed[i] >= 0) {
|
|
||||||
close(rp->renamed[i]);
|
|
||||||
}
|
|
||||||
if (!vforked)
|
|
||||||
rp->renamed[i] = EMPTY;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Copy a file descriptor to be >= to. Returns -1
|
|
||||||
* if the source file descriptor is closed, EMPTY if there are no unused
|
|
||||||
* file descriptors left.
|
|
||||||
*/
|
|
||||||
|
|
||||||
int
|
|
||||||
copyfd(int from, int to)
|
|
||||||
{
|
|
||||||
int newfd;
|
|
||||||
|
|
||||||
newfd = fcntl(from, F_DUPFD, to);
|
|
||||||
if (newfd < 0) {
|
|
||||||
if (errno == EMFILE)
|
|
||||||
return EMPTY;
|
|
||||||
else
|
|
||||||
error("%d: %s", from, strerror(errno));
|
|
||||||
}
|
|
||||||
return newfd;
|
|
||||||
}
|
|
||||||
48
sh/redir.h
48
sh/redir.h
|
|
@ -1,48 +0,0 @@
|
||||||
/* $NetBSD: redir.h,v 1.15 2003/08/07 09:05:37 agc Exp $ */
|
|
||||||
|
|
||||||
/*-
|
|
||||||
* Copyright (c) 1991, 1993
|
|
||||||
* The Regents of the University of California. All rights reserved.
|
|
||||||
*
|
|
||||||
* This code is derived from software contributed to Berkeley by
|
|
||||||
* Kenneth Almquist.
|
|
||||||
*
|
|
||||||
* Redistribution and use in source and binary forms, with or without
|
|
||||||
* modification, are permitted provided that the following conditions
|
|
||||||
* are met:
|
|
||||||
* 1. Redistributions of source code must retain the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer.
|
|
||||||
* 2. Redistributions in binary form must reproduce the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer in the
|
|
||||||
* documentation and/or other materials provided with the distribution.
|
|
||||||
* 3. Neither the name of the University nor the names of its contributors
|
|
||||||
* may be used to endorse or promote products derived from this software
|
|
||||||
* without specific prior written permission.
|
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
|
||||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
||||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
||||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
|
||||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
||||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
|
||||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
|
||||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
||||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
|
||||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
|
||||||
* SUCH DAMAGE.
|
|
||||||
*
|
|
||||||
* @(#)redir.h 8.2 (Berkeley) 5/4/95
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* flags passed to redirect */
|
|
||||||
#define REDIR_PUSH 01 /* save previous values of file descriptors */
|
|
||||||
#define REDIR_BACKQ 02 /* save the command output in memory */
|
|
||||||
#define REDIR_VFORK 04 /* running under vfork(2), be careful */
|
|
||||||
|
|
||||||
union node;
|
|
||||||
void redirect(union node *, int);
|
|
||||||
void popredir(void);
|
|
||||||
int fd0_redirected_p(void);
|
|
||||||
void clearredir(int);
|
|
||||||
int copyfd(int, int);
|
|
||||||
|
|
||||||
83
sh/shell.h
83
sh/shell.h
|
|
@ -1,83 +0,0 @@
|
||||||
/* $NetBSD: shell.h,v 1.17 2003/08/07 09:05:38 agc Exp $ */
|
|
||||||
|
|
||||||
/*-
|
|
||||||
* Copyright (c) 1991, 1993
|
|
||||||
* The Regents of the University of California. All rights reserved.
|
|
||||||
*
|
|
||||||
* This code is derived from software contributed to Berkeley by
|
|
||||||
* Kenneth Almquist.
|
|
||||||
*
|
|
||||||
* Redistribution and use in source and binary forms, with or without
|
|
||||||
* modification, are permitted provided that the following conditions
|
|
||||||
* are met:
|
|
||||||
* 1. Redistributions of source code must retain the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer.
|
|
||||||
* 2. Redistributions in binary form must reproduce the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer in the
|
|
||||||
* documentation and/or other materials provided with the distribution.
|
|
||||||
* 3. Neither the name of the University nor the names of its contributors
|
|
||||||
* may be used to endorse or promote products derived from this software
|
|
||||||
* without specific prior written permission.
|
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
|
||||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
||||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
||||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
|
||||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
||||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
|
||||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
|
||||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
||||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
|
||||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
|
||||||
* SUCH DAMAGE.
|
|
||||||
*
|
|
||||||
* @(#)shell.h 8.2 (Berkeley) 5/4/95
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
* The follow should be set to reflect the type of system you have:
|
|
||||||
* JOBS -> 1 if you have Berkeley job control, 0 otherwise.
|
|
||||||
* SHORTNAMES -> 1 if your linker cannot handle long names.
|
|
||||||
* define BSD if you are running 4.2 BSD or later.
|
|
||||||
* define SYSV if you are running under System V.
|
|
||||||
* define DEBUG=1 to compile in debugging ('set -o debug' to turn on)
|
|
||||||
* define DEBUG=2 to compile in and turn on debugging.
|
|
||||||
* define DO_SHAREDVFORK to indicate that vfork(2) shares its address
|
|
||||||
* with its parent.
|
|
||||||
*
|
|
||||||
* When debugging is on, debugging info will be written to ./trace and
|
|
||||||
* a quit signal will generate a core dump.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <sys/param.h>
|
|
||||||
|
|
||||||
#define JOBS 1
|
|
||||||
#ifndef BSD
|
|
||||||
#define BSD 1
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef DO_SHAREDVFORK
|
|
||||||
#if __NetBSD_Version__ >= 104000000
|
|
||||||
#define DO_SHAREDVFORK
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
typedef void *pointer;
|
|
||||||
#ifndef NULL
|
|
||||||
#define NULL (void *)0
|
|
||||||
#endif
|
|
||||||
#define STATIC /* empty */
|
|
||||||
#define MKINIT /* empty */
|
|
||||||
|
|
||||||
#include <sys/cdefs.h>
|
|
||||||
|
|
||||||
extern char nullstr[1]; /* null string */
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef DEBUG
|
|
||||||
#define TRACE(param) trace param
|
|
||||||
#define TRACEV(param) tracev param
|
|
||||||
#else
|
|
||||||
#define TRACE(param)
|
|
||||||
#define TRACEV(param)
|
|
||||||
#endif
|
|
||||||
425
sh/show.c
425
sh/show.c
|
|
@ -1,425 +0,0 @@
|
||||||
/* $NetBSD: show.c,v 1.26 2003/11/14 10:46:13 dsl Exp $ */
|
|
||||||
|
|
||||||
/*-
|
|
||||||
* Copyright (c) 1991, 1993
|
|
||||||
* The Regents of the University of California. All rights reserved.
|
|
||||||
*
|
|
||||||
* This code is derived from software contributed to Berkeley by
|
|
||||||
* Kenneth Almquist.
|
|
||||||
*
|
|
||||||
* Redistribution and use in source and binary forms, with or without
|
|
||||||
* modification, are permitted provided that the following conditions
|
|
||||||
* are met:
|
|
||||||
* 1. Redistributions of source code must retain the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer.
|
|
||||||
* 2. Redistributions in binary form must reproduce the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer in the
|
|
||||||
* documentation and/or other materials provided with the distribution.
|
|
||||||
* 3. Neither the name of the University nor the names of its contributors
|
|
||||||
* may be used to endorse or promote products derived from this software
|
|
||||||
* without specific prior written permission.
|
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
|
||||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
||||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
||||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
|
||||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
||||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
|
||||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
|
||||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
||||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
|
||||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
|
||||||
* SUCH DAMAGE.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <sys/cdefs.h>
|
|
||||||
#ifndef lint
|
|
||||||
#if 0
|
|
||||||
static char sccsid[] = "@(#)show.c 8.3 (Berkeley) 5/4/95";
|
|
||||||
#else
|
|
||||||
__RCSID("$NetBSD: show.c,v 1.26 2003/11/14 10:46:13 dsl Exp $");
|
|
||||||
#endif
|
|
||||||
#endif /* not lint */
|
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdarg.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
|
|
||||||
#include "shell.h"
|
|
||||||
#include "parser.h"
|
|
||||||
#include "nodes.h"
|
|
||||||
#include "mystring.h"
|
|
||||||
#include "show.h"
|
|
||||||
#include "options.h"
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef DEBUG
|
|
||||||
static void shtree(union node *, int, char *, FILE*);
|
|
||||||
static void shcmd(union node *, FILE *);
|
|
||||||
static void sharg(union node *, FILE *);
|
|
||||||
static void indent(int, char *, FILE *);
|
|
||||||
static void trstring(char *);
|
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
showtree(union node *n)
|
|
||||||
{
|
|
||||||
trputs("showtree called\n");
|
|
||||||
shtree(n, 1, NULL, stdout);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static void
|
|
||||||
shtree(union node *n, int ind, char *pfx, FILE *fp)
|
|
||||||
{
|
|
||||||
struct nodelist *lp;
|
|
||||||
const char *s;
|
|
||||||
|
|
||||||
if (n == NULL)
|
|
||||||
return;
|
|
||||||
|
|
||||||
indent(ind, pfx, fp);
|
|
||||||
switch(n->type) {
|
|
||||||
case NSEMI:
|
|
||||||
s = "; ";
|
|
||||||
goto binop;
|
|
||||||
case NAND:
|
|
||||||
s = " && ";
|
|
||||||
goto binop;
|
|
||||||
case NOR:
|
|
||||||
s = " || ";
|
|
||||||
binop:
|
|
||||||
shtree(n->nbinary.ch1, ind, NULL, fp);
|
|
||||||
/* if (ind < 0) */
|
|
||||||
fputs(s, fp);
|
|
||||||
shtree(n->nbinary.ch2, ind, NULL, fp);
|
|
||||||
break;
|
|
||||||
case NCMD:
|
|
||||||
shcmd(n, fp);
|
|
||||||
if (ind >= 0)
|
|
||||||
putc('\n', fp);
|
|
||||||
break;
|
|
||||||
case NPIPE:
|
|
||||||
for (lp = n->npipe.cmdlist ; lp ; lp = lp->next) {
|
|
||||||
shcmd(lp->n, fp);
|
|
||||||
if (lp->next)
|
|
||||||
fputs(" | ", fp);
|
|
||||||
}
|
|
||||||
if (n->npipe.backgnd)
|
|
||||||
fputs(" &", fp);
|
|
||||||
if (ind >= 0)
|
|
||||||
putc('\n', fp);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
fprintf(fp, "<node type %d>", n->type);
|
|
||||||
if (ind >= 0)
|
|
||||||
putc('\n', fp);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static void
|
|
||||||
shcmd(union node *cmd, FILE *fp)
|
|
||||||
{
|
|
||||||
union node *np;
|
|
||||||
int first;
|
|
||||||
const char *s;
|
|
||||||
int dftfd;
|
|
||||||
|
|
||||||
first = 1;
|
|
||||||
for (np = cmd->ncmd.args ; np ; np = np->narg.next) {
|
|
||||||
if (! first)
|
|
||||||
putchar(' ');
|
|
||||||
sharg(np, fp);
|
|
||||||
first = 0;
|
|
||||||
}
|
|
||||||
for (np = cmd->ncmd.redirect ; np ; np = np->nfile.next) {
|
|
||||||
if (! first)
|
|
||||||
putchar(' ');
|
|
||||||
switch (np->nfile.type) {
|
|
||||||
case NTO: s = ">"; dftfd = 1; break;
|
|
||||||
case NCLOBBER: s = ">|"; dftfd = 1; break;
|
|
||||||
case NAPPEND: s = ">>"; dftfd = 1; break;
|
|
||||||
case NTOFD: s = ">&"; dftfd = 1; break;
|
|
||||||
case NFROM: s = "<"; dftfd = 0; break;
|
|
||||||
case NFROMFD: s = "<&"; dftfd = 0; break;
|
|
||||||
case NFROMTO: s = "<>"; dftfd = 0; break;
|
|
||||||
default: s = "*error*"; dftfd = 0; break;
|
|
||||||
}
|
|
||||||
if (np->nfile.fd != dftfd)
|
|
||||||
fprintf(fp, "%d", np->nfile.fd);
|
|
||||||
fputs(s, fp);
|
|
||||||
if (np->nfile.type == NTOFD || np->nfile.type == NFROMFD) {
|
|
||||||
fprintf(fp, "%d", np->ndup.dupfd);
|
|
||||||
} else {
|
|
||||||
sharg(np->nfile.fname, fp);
|
|
||||||
}
|
|
||||||
first = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static void
|
|
||||||
sharg(union node *arg, FILE *fp)
|
|
||||||
{
|
|
||||||
char *p;
|
|
||||||
struct nodelist *bqlist;
|
|
||||||
int subtype;
|
|
||||||
|
|
||||||
if (arg->type != NARG) {
|
|
||||||
printf("<node type %d>\n", arg->type);
|
|
||||||
abort();
|
|
||||||
}
|
|
||||||
bqlist = arg->narg.backquote;
|
|
||||||
for (p = arg->narg.text ; *p ; p++) {
|
|
||||||
switch (*p) {
|
|
||||||
case CTLESC:
|
|
||||||
putc(*++p, fp);
|
|
||||||
break;
|
|
||||||
case CTLVAR:
|
|
||||||
putc('$', fp);
|
|
||||||
putc('{', fp);
|
|
||||||
subtype = *++p;
|
|
||||||
if (subtype == VSLENGTH)
|
|
||||||
putc('#', fp);
|
|
||||||
|
|
||||||
while (*p != '=')
|
|
||||||
putc(*p++, fp);
|
|
||||||
|
|
||||||
if (subtype & VSNUL)
|
|
||||||
putc(':', fp);
|
|
||||||
|
|
||||||
switch (subtype & VSTYPE) {
|
|
||||||
case VSNORMAL:
|
|
||||||
putc('}', fp);
|
|
||||||
break;
|
|
||||||
case VSMINUS:
|
|
||||||
putc('-', fp);
|
|
||||||
break;
|
|
||||||
case VSPLUS:
|
|
||||||
putc('+', fp);
|
|
||||||
break;
|
|
||||||
case VSQUESTION:
|
|
||||||
putc('?', fp);
|
|
||||||
break;
|
|
||||||
case VSASSIGN:
|
|
||||||
putc('=', fp);
|
|
||||||
break;
|
|
||||||
case VSTRIMLEFT:
|
|
||||||
putc('#', fp);
|
|
||||||
break;
|
|
||||||
case VSTRIMLEFTMAX:
|
|
||||||
putc('#', fp);
|
|
||||||
putc('#', fp);
|
|
||||||
break;
|
|
||||||
case VSTRIMRIGHT:
|
|
||||||
putc('%', fp);
|
|
||||||
break;
|
|
||||||
case VSTRIMRIGHTMAX:
|
|
||||||
putc('%', fp);
|
|
||||||
putc('%', fp);
|
|
||||||
break;
|
|
||||||
case VSLENGTH:
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
printf("<subtype %d>", subtype);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case CTLENDVAR:
|
|
||||||
putc('}', fp);
|
|
||||||
break;
|
|
||||||
case CTLBACKQ:
|
|
||||||
case CTLBACKQ|CTLQUOTE:
|
|
||||||
putc('$', fp);
|
|
||||||
putc('(', fp);
|
|
||||||
shtree(bqlist->n, -1, NULL, fp);
|
|
||||||
putc(')', fp);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
putc(*p, fp);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static void
|
|
||||||
indent(int amount, char *pfx, FILE *fp)
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
|
|
||||||
for (i = 0 ; i < amount ; i++) {
|
|
||||||
if (pfx && i == amount - 1)
|
|
||||||
fputs(pfx, fp);
|
|
||||||
putc('\t', fp);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Debugging stuff.
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
FILE *tracefile;
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef DEBUG
|
|
||||||
void
|
|
||||||
trputc(int c)
|
|
||||||
{
|
|
||||||
if (debug != 1)
|
|
||||||
return;
|
|
||||||
putc(c, tracefile);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
void
|
|
||||||
trace(const char *fmt, ...)
|
|
||||||
{
|
|
||||||
#ifdef DEBUG
|
|
||||||
va_list va;
|
|
||||||
|
|
||||||
if (debug != 1)
|
|
||||||
return;
|
|
||||||
va_start(va, fmt);
|
|
||||||
(void) vfprintf(tracefile, fmt, va);
|
|
||||||
va_end(va);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
tracev(const char *fmt, va_list va)
|
|
||||||
{
|
|
||||||
#ifdef DEBUG
|
|
||||||
if (debug != 1)
|
|
||||||
return;
|
|
||||||
(void) vfprintf(tracefile, fmt, va);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef DEBUG
|
|
||||||
void
|
|
||||||
trputs(const char *s)
|
|
||||||
{
|
|
||||||
if (debug != 1)
|
|
||||||
return;
|
|
||||||
fputs(s, tracefile);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static void
|
|
||||||
trstring(char *s)
|
|
||||||
{
|
|
||||||
char *p;
|
|
||||||
char c;
|
|
||||||
|
|
||||||
if (debug != 1)
|
|
||||||
return;
|
|
||||||
putc('"', tracefile);
|
|
||||||
for (p = s ; *p ; p++) {
|
|
||||||
switch (*p) {
|
|
||||||
case '\n': c = 'n'; goto backslash;
|
|
||||||
case '\t': c = 't'; goto backslash;
|
|
||||||
case '\r': c = 'r'; goto backslash;
|
|
||||||
case '"': c = '"'; goto backslash;
|
|
||||||
case '\\': c = '\\'; goto backslash;
|
|
||||||
case CTLESC: c = 'e'; goto backslash;
|
|
||||||
case CTLVAR: c = 'v'; goto backslash;
|
|
||||||
case CTLVAR+CTLQUOTE: c = 'V'; goto backslash;
|
|
||||||
case CTLBACKQ: c = 'q'; goto backslash;
|
|
||||||
case CTLBACKQ+CTLQUOTE: c = 'Q'; goto backslash;
|
|
||||||
backslash: putc('\\', tracefile);
|
|
||||||
putc(c, tracefile);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
if (*p >= ' ' && *p <= '~')
|
|
||||||
putc(*p, tracefile);
|
|
||||||
else {
|
|
||||||
putc('\\', tracefile);
|
|
||||||
putc(*p >> 6 & 03, tracefile);
|
|
||||||
putc(*p >> 3 & 07, tracefile);
|
|
||||||
putc(*p & 07, tracefile);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
putc('"', tracefile);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
trargs(char **ap)
|
|
||||||
{
|
|
||||||
#ifdef DEBUG
|
|
||||||
if (debug != 1)
|
|
||||||
return;
|
|
||||||
while (*ap) {
|
|
||||||
trstring(*ap++);
|
|
||||||
if (*ap)
|
|
||||||
putc(' ', tracefile);
|
|
||||||
else
|
|
||||||
putc('\n', tracefile);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef DEBUG
|
|
||||||
void
|
|
||||||
opentrace(void)
|
|
||||||
{
|
|
||||||
char s[100];
|
|
||||||
#ifdef O_APPEND
|
|
||||||
int flags;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (debug != 1) {
|
|
||||||
if (tracefile)
|
|
||||||
fflush(tracefile);
|
|
||||||
/* leave open because libedit might be using it */
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
#ifdef not_this_way
|
|
||||||
{
|
|
||||||
char *p;
|
|
||||||
if ((p = getenv("HOME")) == NULL) {
|
|
||||||
if (geteuid() == 0)
|
|
||||||
p = "/";
|
|
||||||
else
|
|
||||||
p = "/tmp";
|
|
||||||
}
|
|
||||||
scopy(p, s);
|
|
||||||
strcat(s, "/trace");
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
scopy("./trace", s);
|
|
||||||
#endif /* not_this_way */
|
|
||||||
if (tracefile) {
|
|
||||||
if (!freopen(s, "a", tracefile)) {
|
|
||||||
fprintf(stderr, "Can't re-open %s\n", s);
|
|
||||||
debug = 0;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if ((tracefile = fopen(s, "a")) == NULL) {
|
|
||||||
fprintf(stderr, "Can't open %s\n", s);
|
|
||||||
debug = 0;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#ifdef O_APPEND
|
|
||||||
if ((flags = fcntl(fileno(tracefile), F_GETFL, 0)) >= 0)
|
|
||||||
fcntl(fileno(tracefile), F_SETFL, flags | O_APPEND);
|
|
||||||
#endif
|
|
||||||
setlinebuf(tracefile);
|
|
||||||
fputs("\nTracing started.\n", tracefile);
|
|
||||||
}
|
|
||||||
#endif /* DEBUG */
|
|
||||||
45
sh/show.h
45
sh/show.h
|
|
@ -1,45 +0,0 @@
|
||||||
/* $NetBSD: show.h,v 1.7 2003/08/07 09:05:38 agc Exp $ */
|
|
||||||
|
|
||||||
/*-
|
|
||||||
* Copyright (c) 1995
|
|
||||||
* The Regents of the University of California. All rights reserved.
|
|
||||||
*
|
|
||||||
* Redistribution and use in source and binary forms, with or without
|
|
||||||
* modification, are permitted provided that the following conditions
|
|
||||||
* are met:
|
|
||||||
* 1. Redistributions of source code must retain the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer.
|
|
||||||
* 2. Redistributions in binary form must reproduce the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer in the
|
|
||||||
* documentation and/or other materials provided with the distribution.
|
|
||||||
* 3. Neither the name of the University nor the names of its contributors
|
|
||||||
* may be used to endorse or promote products derived from this software
|
|
||||||
* without specific prior written permission.
|
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
|
||||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
||||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
||||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
|
||||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
||||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
|
||||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
|
||||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
||||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
|
||||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
|
||||||
* SUCH DAMAGE.
|
|
||||||
*
|
|
||||||
* @(#)show.h 1.1 (Berkeley) 5/4/95
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <stdarg.h>
|
|
||||||
|
|
||||||
union node;
|
|
||||||
void showtree(union node *);
|
|
||||||
void trace(const char *, ...);
|
|
||||||
void tracev(const char *, va_list);
|
|
||||||
void trargs(char **);
|
|
||||||
#ifdef DEBUG
|
|
||||||
void trputc(int);
|
|
||||||
void trputs(const char *);
|
|
||||||
void opentrace(void);
|
|
||||||
#endif
|
|
||||||
102
sh/syntax.c
102
sh/syntax.c
|
|
@ -1,102 +0,0 @@
|
||||||
/* $NetBSD: syntax.c,v 1.1 2004/01/17 17:38:12 dsl Exp $ */
|
|
||||||
|
|
||||||
#include "shell.h"
|
|
||||||
#include "syntax.h"
|
|
||||||
#include "parser.h"
|
|
||||||
#include <limits.h>
|
|
||||||
|
|
||||||
#if CWORD != 0
|
|
||||||
#error initialisation assumes 'CWORD' is zero
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define ndx(ch) (ch + 1 - CHAR_MIN)
|
|
||||||
#define set(ch, val) [ndx(ch)] = val,
|
|
||||||
#define set_range(s, e, val) [ndx(s) ... ndx(e)] = val,
|
|
||||||
|
|
||||||
/* syntax table used when not in quotes */
|
|
||||||
const char basesyntax[257] = { CEOF,
|
|
||||||
set_range(CTL_FIRST, CTL_LAST, CCTL)
|
|
||||||
set('\n', CNL)
|
|
||||||
set('\\', CBACK)
|
|
||||||
set('\'', CSQUOTE)
|
|
||||||
set('"', CDQUOTE)
|
|
||||||
set('`', CBQUOTE)
|
|
||||||
set('$', CVAR)
|
|
||||||
set('}', CENDVAR)
|
|
||||||
set('<', CSPCL)
|
|
||||||
set('>', CSPCL)
|
|
||||||
set('(', CSPCL)
|
|
||||||
set(')', CSPCL)
|
|
||||||
set(';', CSPCL)
|
|
||||||
set('&', CSPCL)
|
|
||||||
set('|', CSPCL)
|
|
||||||
set(' ', CSPCL)
|
|
||||||
set('\t', CSPCL)
|
|
||||||
};
|
|
||||||
|
|
||||||
/* syntax table used when in double quotes */
|
|
||||||
const char dqsyntax[257] = { CEOF,
|
|
||||||
set_range(CTL_FIRST, CTL_LAST, CCTL)
|
|
||||||
set('\n', CNL)
|
|
||||||
set('\\', CBACK)
|
|
||||||
set('"', CDQUOTE)
|
|
||||||
set('`', CBQUOTE)
|
|
||||||
set('$', CVAR)
|
|
||||||
set('}', CENDVAR)
|
|
||||||
/* ':/' for tilde expansion, '-' for [a\-x] pattern ranges */
|
|
||||||
set('!', CCTL)
|
|
||||||
set('*', CCTL)
|
|
||||||
set('?', CCTL)
|
|
||||||
set('[', CCTL)
|
|
||||||
set('=', CCTL)
|
|
||||||
set('~', CCTL)
|
|
||||||
set(':', CCTL)
|
|
||||||
set('/', CCTL)
|
|
||||||
set('-', CCTL)
|
|
||||||
};
|
|
||||||
|
|
||||||
/* syntax table used when in single quotes */
|
|
||||||
const char sqsyntax[257] = { CEOF,
|
|
||||||
set_range(CTL_FIRST, CTL_LAST, CCTL)
|
|
||||||
set('\n', CNL)
|
|
||||||
set('\'', CSQUOTE)
|
|
||||||
/* ':/' for tilde expansion, '-' for [a\-x] pattern ranges */
|
|
||||||
set('!', CCTL)
|
|
||||||
set('*', CCTL)
|
|
||||||
set('?', CCTL)
|
|
||||||
set('[', CCTL)
|
|
||||||
set('=', CCTL)
|
|
||||||
set('~', CCTL)
|
|
||||||
set(':', CCTL)
|
|
||||||
set('/', CCTL)
|
|
||||||
set('-', CCTL)
|
|
||||||
};
|
|
||||||
|
|
||||||
/* syntax table used when in arithmetic */
|
|
||||||
const char arisyntax[257] = { CEOF,
|
|
||||||
set_range(CTL_FIRST, CTL_LAST, CCTL)
|
|
||||||
set('\n', CNL)
|
|
||||||
set('\\', CBACK)
|
|
||||||
set('`', CBQUOTE)
|
|
||||||
set('\'', CSQUOTE)
|
|
||||||
set('"', CDQUOTE)
|
|
||||||
set('$', CVAR)
|
|
||||||
set('}', CENDVAR)
|
|
||||||
set('(', CLP)
|
|
||||||
set(')', CRP)
|
|
||||||
};
|
|
||||||
|
|
||||||
/* character classification table */
|
|
||||||
const char is_type[257] = { 0,
|
|
||||||
set_range('0', '9', ISDIGIT)
|
|
||||||
set_range('a', 'z', ISLOWER)
|
|
||||||
set_range('A', 'Z', ISUPPER)
|
|
||||||
set('_', ISUNDER)
|
|
||||||
set('#', ISSPECL)
|
|
||||||
set('?', ISSPECL)
|
|
||||||
set('$', ISSPECL)
|
|
||||||
set('!', ISSPECL)
|
|
||||||
set('-', ISSPECL)
|
|
||||||
set('*', ISSPECL)
|
|
||||||
set('@', ISSPECL)
|
|
||||||
};
|
|
||||||
83
sh/syntax.h
83
sh/syntax.h
|
|
@ -1,83 +0,0 @@
|
||||||
/* $NetBSD: syntax.h,v 1.2 2004/01/17 17:38:12 dsl Exp $ */
|
|
||||||
|
|
||||||
/*-
|
|
||||||
* Copyright (c) 1991, 1993
|
|
||||||
* The Regents of the University of California. All rights reserved.
|
|
||||||
*
|
|
||||||
* This code is derived from software contributed to Berkeley by
|
|
||||||
* Kenneth Almquist.
|
|
||||||
*
|
|
||||||
* Redistribution and use in source and binary forms, with or without
|
|
||||||
* modification, are permitted provided that the following conditions
|
|
||||||
* are met:
|
|
||||||
* 1. Redistributions of source code must retain the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer.
|
|
||||||
* 2. Redistributions in binary form must reproduce the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer in the
|
|
||||||
* documentation and/or other materials provided with the distribution.
|
|
||||||
* 3. Neither the name of the University nor the names of its contributors
|
|
||||||
* may be used to endorse or promote products derived from this software
|
|
||||||
* without specific prior written permission.
|
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
|
||||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
||||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
||||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
|
||||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
||||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
|
||||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
|
||||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
||||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
|
||||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
|
||||||
* SUCH DAMAGE.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <sys/cdefs.h>
|
|
||||||
#include <ctype.h>
|
|
||||||
|
|
||||||
/* Syntax classes */
|
|
||||||
#define CWORD 0 /* character is nothing special */
|
|
||||||
#define CNL 1 /* newline character */
|
|
||||||
#define CBACK 2 /* a backslash character */
|
|
||||||
#define CSQUOTE 3 /* single quote */
|
|
||||||
#define CDQUOTE 4 /* double quote */
|
|
||||||
#define CBQUOTE 5 /* backwards single quote */
|
|
||||||
#define CVAR 6 /* a dollar sign */
|
|
||||||
#define CENDVAR 7 /* a '}' character */
|
|
||||||
#define CLP 8 /* a left paren in arithmetic */
|
|
||||||
#define CRP 9 /* a right paren in arithmetic */
|
|
||||||
#define CEOF 10 /* end of file */
|
|
||||||
#define CCTL 11 /* like CWORD, except it must be escaped */
|
|
||||||
#define CSPCL 12 /* these terminate a word */
|
|
||||||
|
|
||||||
/* Syntax classes for is_ functions */
|
|
||||||
#define ISDIGIT 01 /* a digit */
|
|
||||||
#define ISUPPER 02 /* an upper case letter */
|
|
||||||
#define ISLOWER 04 /* a lower case letter */
|
|
||||||
#define ISUNDER 010 /* an underscore */
|
|
||||||
#define ISSPECL 020 /* the name of a special parameter */
|
|
||||||
|
|
||||||
#define PEOF (CHAR_MIN - 1)
|
|
||||||
#define SYNBASE (-PEOF)
|
|
||||||
/* XXX UPEOF is CHAR_MAX, so is a valid 'char' value... */
|
|
||||||
#define UPEOF ((char)PEOF)
|
|
||||||
|
|
||||||
|
|
||||||
#define BASESYNTAX (basesyntax + SYNBASE)
|
|
||||||
#define DQSYNTAX (dqsyntax + SYNBASE)
|
|
||||||
#define SQSYNTAX (sqsyntax + SYNBASE)
|
|
||||||
#define ARISYNTAX (arisyntax + SYNBASE)
|
|
||||||
|
|
||||||
/* These defines assume that the digits are contiguous */
|
|
||||||
#define is_digit(c) ((unsigned)((c) - '0') <= 9)
|
|
||||||
#define is_alpha(c) (((char)(c)) != UPEOF && ((c) < CTL_FIRST || (c) > CTL_LAST) && isalpha((unsigned char)(c)))
|
|
||||||
#define is_name(c) (((char)(c)) != UPEOF && ((c) < CTL_FIRST || (c) > CTL_LAST) && ((c) == '_' || isalpha((unsigned char)(c))))
|
|
||||||
#define is_in_name(c) (((char)(c)) != UPEOF && ((c) < CTL_FIRST || (c) > CTL_LAST) && ((c) == '_' || isalnum((unsigned char)(c))))
|
|
||||||
#define is_special(c) ((is_type+SYNBASE)[c] & (ISSPECL|ISDIGIT))
|
|
||||||
#define digit_val(c) ((c) - '0')
|
|
||||||
|
|
||||||
extern const char basesyntax[];
|
|
||||||
extern const char dqsyntax[];
|
|
||||||
extern const char sqsyntax[];
|
|
||||||
extern const char arisyntax[];
|
|
||||||
extern const char is_type[];
|
|
||||||
112
sh/token.h
112
sh/token.h
|
|
@ -1,112 +0,0 @@
|
||||||
#define TEOF 0
|
|
||||||
#define TNL 1
|
|
||||||
#define TSEMI 2
|
|
||||||
#define TBACKGND 3
|
|
||||||
#define TAND 4
|
|
||||||
#define TOR 5
|
|
||||||
#define TPIPE 6
|
|
||||||
#define TLP 7
|
|
||||||
#define TRP 8
|
|
||||||
#define TENDCASE 9
|
|
||||||
#define TENDBQUOTE 10
|
|
||||||
#define TREDIR 11
|
|
||||||
#define TWORD 12
|
|
||||||
#define TIF 13
|
|
||||||
#define TTHEN 14
|
|
||||||
#define TELSE 15
|
|
||||||
#define TELIF 16
|
|
||||||
#define TFI 17
|
|
||||||
#define TWHILE 18
|
|
||||||
#define TUNTIL 19
|
|
||||||
#define TFOR 20
|
|
||||||
#define TDO 21
|
|
||||||
#define TDONE 22
|
|
||||||
#define TBEGIN 23
|
|
||||||
#define TEND 24
|
|
||||||
#define TCASE 25
|
|
||||||
#define TESAC 26
|
|
||||||
#define TNOT 27
|
|
||||||
|
|
||||||
/* Array indicating which tokens mark the end of a list */
|
|
||||||
const char tokendlist[] = {
|
|
||||||
1,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
1,
|
|
||||||
1,
|
|
||||||
1,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
1,
|
|
||||||
1,
|
|
||||||
1,
|
|
||||||
1,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
1,
|
|
||||||
1,
|
|
||||||
0,
|
|
||||||
1,
|
|
||||||
0,
|
|
||||||
1,
|
|
||||||
0,
|
|
||||||
};
|
|
||||||
|
|
||||||
const char *const tokname[] = {
|
|
||||||
"end of file",
|
|
||||||
"newline",
|
|
||||||
"\";\"",
|
|
||||||
"\"&\"",
|
|
||||||
"\"&&\"",
|
|
||||||
"\"||\"",
|
|
||||||
"\"|\"",
|
|
||||||
"\"(\"",
|
|
||||||
"\")\"",
|
|
||||||
"\";;\"",
|
|
||||||
"\"`\"",
|
|
||||||
"redirection",
|
|
||||||
"word",
|
|
||||||
"\"if\"",
|
|
||||||
"\"then\"",
|
|
||||||
"\"else\"",
|
|
||||||
"\"elif\"",
|
|
||||||
"\"fi\"",
|
|
||||||
"\"while\"",
|
|
||||||
"\"until\"",
|
|
||||||
"\"for\"",
|
|
||||||
"\"do\"",
|
|
||||||
"\"done\"",
|
|
||||||
"\"{\"",
|
|
||||||
"\"}\"",
|
|
||||||
"\"case\"",
|
|
||||||
"\"esac\"",
|
|
||||||
"\"!\"",
|
|
||||||
};
|
|
||||||
|
|
||||||
#define KWDOFFSET 13
|
|
||||||
|
|
||||||
const char *const parsekwd[] = {
|
|
||||||
"if",
|
|
||||||
"then",
|
|
||||||
"else",
|
|
||||||
"elif",
|
|
||||||
"fi",
|
|
||||||
"while",
|
|
||||||
"until",
|
|
||||||
"for",
|
|
||||||
"do",
|
|
||||||
"done",
|
|
||||||
"{",
|
|
||||||
"}",
|
|
||||||
"case",
|
|
||||||
"esac",
|
|
||||||
"!",
|
|
||||||
0
|
|
||||||
};
|
|
||||||
456
sh/trap.c
456
sh/trap.c
|
|
@ -1,456 +0,0 @@
|
||||||
/* $NetBSD: trap.c,v 1.31 2005/01/11 19:38:57 christos Exp $ */
|
|
||||||
|
|
||||||
/*-
|
|
||||||
* Copyright (c) 1991, 1993
|
|
||||||
* The Regents of the University of California. All rights reserved.
|
|
||||||
*
|
|
||||||
* This code is derived from software contributed to Berkeley by
|
|
||||||
* Kenneth Almquist.
|
|
||||||
*
|
|
||||||
* Redistribution and use in source and binary forms, with or without
|
|
||||||
* modification, are permitted provided that the following conditions
|
|
||||||
* are met:
|
|
||||||
* 1. Redistributions of source code must retain the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer.
|
|
||||||
* 2. Redistributions in binary form must reproduce the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer in the
|
|
||||||
* documentation and/or other materials provided with the distribution.
|
|
||||||
* 3. Neither the name of the University nor the names of its contributors
|
|
||||||
* may be used to endorse or promote products derived from this software
|
|
||||||
* without specific prior written permission.
|
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
|
||||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
||||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
||||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
|
||||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
||||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
|
||||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
|
||||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
||||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
|
||||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
|
||||||
* SUCH DAMAGE.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <sys/cdefs.h>
|
|
||||||
#ifndef lint
|
|
||||||
#if 0
|
|
||||||
static char sccsid[] = "@(#)trap.c 8.5 (Berkeley) 6/5/95";
|
|
||||||
#else
|
|
||||||
__RCSID("$NetBSD: trap.c,v 1.31 2005/01/11 19:38:57 christos Exp $");
|
|
||||||
#endif
|
|
||||||
#endif /* not lint */
|
|
||||||
|
|
||||||
#include <signal.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
|
|
||||||
#include "shell.h"
|
|
||||||
#include "main.h"
|
|
||||||
#include "nodes.h" /* for other headers */
|
|
||||||
#include "eval.h"
|
|
||||||
#include "jobs.h"
|
|
||||||
#include "show.h"
|
|
||||||
#include "options.h"
|
|
||||||
#include "syntax.h"
|
|
||||||
#include "output.h"
|
|
||||||
#include "memalloc.h"
|
|
||||||
#include "error.h"
|
|
||||||
#include "trap.h"
|
|
||||||
#include "mystring.h"
|
|
||||||
#include "var.h"
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Sigmode records the current value of the signal handlers for the various
|
|
||||||
* modes. A value of zero means that the current handler is not known.
|
|
||||||
* S_HARD_IGN indicates that the signal was ignored on entry to the shell,
|
|
||||||
*/
|
|
||||||
|
|
||||||
#define S_DFL 1 /* default signal handling (SIG_DFL) */
|
|
||||||
#define S_CATCH 2 /* signal is caught */
|
|
||||||
#define S_IGN 3 /* signal is ignored (SIG_IGN) */
|
|
||||||
#define S_HARD_IGN 4 /* signal is ignored permenantly */
|
|
||||||
#define S_RESET 5 /* temporary - to reset a hard ignored sig */
|
|
||||||
|
|
||||||
|
|
||||||
char *trap[NSIG+1]; /* trap handler commands */
|
|
||||||
MKINIT char sigmode[NSIG]; /* current value of signal */
|
|
||||||
char gotsig[NSIG]; /* indicates specified signal received */
|
|
||||||
int pendingsigs; /* indicates some signal received */
|
|
||||||
|
|
||||||
static int getsigaction(int, sig_t *);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* return the signal number described by `p' (as a number or a name)
|
|
||||||
* or -1 if it isn't one
|
|
||||||
*/
|
|
||||||
|
|
||||||
static int
|
|
||||||
signame_to_signum(const char *p)
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
|
|
||||||
if (is_number(p))
|
|
||||||
return number(p);
|
|
||||||
|
|
||||||
if (strcasecmp(p, "exit") == 0 )
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
if (strncasecmp(p, "sig", 3) == 0)
|
|
||||||
p += 3;
|
|
||||||
|
|
||||||
for (i = 0; i < NSIG; ++i)
|
|
||||||
if (sys_signame[i] && (strcasecmp (p, sys_signame[i]) == 0))
|
|
||||||
return i;
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Print a list of valid signal names
|
|
||||||
*/
|
|
||||||
static void
|
|
||||||
printsignals(void)
|
|
||||||
{
|
|
||||||
int n;
|
|
||||||
|
|
||||||
out1str("EXIT ");
|
|
||||||
|
|
||||||
for (n = 1; n < NSIG; n++) {
|
|
||||||
out1fmt("%s", sys_signame[n]);
|
|
||||||
if ((n == NSIG/2) || n == (NSIG - 1))
|
|
||||||
out1str("\n");
|
|
||||||
else
|
|
||||||
out1c(' ');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* The trap builtin.
|
|
||||||
*/
|
|
||||||
|
|
||||||
int
|
|
||||||
trapcmd(int argc, char **argv)
|
|
||||||
{
|
|
||||||
char *action;
|
|
||||||
char **ap;
|
|
||||||
int signo;
|
|
||||||
|
|
||||||
if (argc <= 1) {
|
|
||||||
for (signo = 0 ; signo <= NSIG ; signo++)
|
|
||||||
if (trap[signo] != NULL) {
|
|
||||||
out1fmt("trap -- ");
|
|
||||||
print_quoted(trap[signo]);
|
|
||||||
out1fmt(" %s\n",
|
|
||||||
(signo) ? sys_signame[signo] : "EXIT");
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
ap = argv + 1;
|
|
||||||
|
|
||||||
action = NULL;
|
|
||||||
|
|
||||||
if (strcmp(*ap, "--") == 0)
|
|
||||||
if (*++ap == NULL)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
if (signame_to_signum(*ap) == -1) {
|
|
||||||
if ((*ap)[0] == '-') {
|
|
||||||
if ((*ap)[1] == '\0')
|
|
||||||
ap++;
|
|
||||||
else if ((*ap)[1] == 'l' && (*ap)[2] == '\0') {
|
|
||||||
printsignals();
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
error("bad option %s\n", *ap);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
action = *ap++;
|
|
||||||
}
|
|
||||||
|
|
||||||
while (*ap) {
|
|
||||||
if (is_number(*ap))
|
|
||||||
signo = number(*ap);
|
|
||||||
else
|
|
||||||
signo = signame_to_signum(*ap);
|
|
||||||
|
|
||||||
if (signo < 0 || signo > NSIG)
|
|
||||||
error("%s: bad trap", *ap);
|
|
||||||
|
|
||||||
INTOFF;
|
|
||||||
if (action)
|
|
||||||
action = savestr(action);
|
|
||||||
|
|
||||||
if (trap[signo])
|
|
||||||
ckfree(trap[signo]);
|
|
||||||
|
|
||||||
trap[signo] = action;
|
|
||||||
|
|
||||||
if (signo != 0)
|
|
||||||
setsignal(signo, 0);
|
|
||||||
INTON;
|
|
||||||
ap++;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Clear traps on a fork or vfork.
|
|
||||||
* Takes one arg vfork, to tell it to not be destructive of
|
|
||||||
* the parents variables.
|
|
||||||
*/
|
|
||||||
|
|
||||||
void
|
|
||||||
clear_traps(int vforked)
|
|
||||||
{
|
|
||||||
char **tp;
|
|
||||||
|
|
||||||
for (tp = trap ; tp <= &trap[NSIG] ; tp++) {
|
|
||||||
if (*tp && **tp) { /* trap not NULL or SIG_IGN */
|
|
||||||
INTOFF;
|
|
||||||
if (!vforked) {
|
|
||||||
ckfree(*tp);
|
|
||||||
*tp = NULL;
|
|
||||||
}
|
|
||||||
if (tp != &trap[0])
|
|
||||||
setsignal(tp - trap, vforked);
|
|
||||||
INTON;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Set the signal handler for the specified signal. The routine figures
|
|
||||||
* out what it should be set to.
|
|
||||||
*/
|
|
||||||
|
|
||||||
long
|
|
||||||
setsignal(int signo, int vforked)
|
|
||||||
{
|
|
||||||
int action;
|
|
||||||
sig_t sigact = SIG_DFL;
|
|
||||||
struct sigaction act, oact;
|
|
||||||
char *t, tsig;
|
|
||||||
|
|
||||||
if ((t = trap[signo]) == NULL)
|
|
||||||
action = S_DFL;
|
|
||||||
else if (*t != '\0')
|
|
||||||
action = S_CATCH;
|
|
||||||
else
|
|
||||||
action = S_IGN;
|
|
||||||
if (rootshell && !vforked && action == S_DFL) {
|
|
||||||
switch (signo) {
|
|
||||||
case SIGINT:
|
|
||||||
if (iflag || minusc || sflag == 0)
|
|
||||||
action = S_CATCH;
|
|
||||||
break;
|
|
||||||
case SIGQUIT:
|
|
||||||
#ifdef DEBUG
|
|
||||||
if (debug)
|
|
||||||
break;
|
|
||||||
#endif
|
|
||||||
/* FALLTHROUGH */
|
|
||||||
case SIGTERM:
|
|
||||||
if (iflag)
|
|
||||||
action = S_IGN;
|
|
||||||
break;
|
|
||||||
#if JOBS
|
|
||||||
case SIGTSTP:
|
|
||||||
case SIGTTOU:
|
|
||||||
if (mflag)
|
|
||||||
action = S_IGN;
|
|
||||||
break;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
t = &sigmode[signo - 1];
|
|
||||||
tsig = *t;
|
|
||||||
if (tsig == 0) {
|
|
||||||
/*
|
|
||||||
* current setting unknown
|
|
||||||
*/
|
|
||||||
if (!getsigaction(signo, &sigact)) {
|
|
||||||
/*
|
|
||||||
* Pretend it worked; maybe we should give a warning
|
|
||||||
* here, but other shells don't. We don't alter
|
|
||||||
* sigmode, so that we retry every time.
|
|
||||||
*/
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
if (sigact == SIG_IGN) {
|
|
||||||
if (mflag && (signo == SIGTSTP ||
|
|
||||||
signo == SIGTTIN || signo == SIGTTOU)) {
|
|
||||||
tsig = S_IGN; /* don't hard ignore these */
|
|
||||||
} else
|
|
||||||
tsig = S_HARD_IGN;
|
|
||||||
} else {
|
|
||||||
tsig = S_RESET; /* force to be set */
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (tsig == S_HARD_IGN || tsig == action)
|
|
||||||
return 0;
|
|
||||||
switch (action) {
|
|
||||||
case S_DFL: sigact = SIG_DFL; break;
|
|
||||||
case S_CATCH: sigact = onsig; break;
|
|
||||||
case S_IGN: sigact = SIG_IGN; break;
|
|
||||||
}
|
|
||||||
if (!vforked)
|
|
||||||
*t = action;
|
|
||||||
act.sa_handler = sigact;
|
|
||||||
sigemptyset(&act.sa_mask);
|
|
||||||
act.sa_flags = 0;
|
|
||||||
#ifdef SA_INTERRUPT
|
|
||||||
act.sa_flags |= SA_INTERRUPT;
|
|
||||||
#endif
|
|
||||||
if(sigaction(signo, &act, &oact) < 0)
|
|
||||||
return (long) SIG_ERR;
|
|
||||||
return (long) oact.sa_handler;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Return the current setting for sig w/o changing it.
|
|
||||||
*/
|
|
||||||
static int
|
|
||||||
getsigaction(int signo, sig_t *sigact)
|
|
||||||
{
|
|
||||||
struct sigaction sa;
|
|
||||||
|
|
||||||
if (sigaction(signo, (struct sigaction *)0, &sa) == -1)
|
|
||||||
return 0;
|
|
||||||
*sigact = (sig_t) sa.sa_handler;
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Ignore a signal.
|
|
||||||
*/
|
|
||||||
|
|
||||||
void
|
|
||||||
ignoresig(int signo, int vforked)
|
|
||||||
{
|
|
||||||
if (sigmode[signo - 1] != S_IGN && sigmode[signo - 1] != S_HARD_IGN)
|
|
||||||
bsd_signal(signo, SIG_IGN);
|
|
||||||
if (!vforked)
|
|
||||||
sigmode[signo - 1] = S_HARD_IGN;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef mkinit
|
|
||||||
INCLUDE <signal.h>
|
|
||||||
INCLUDE "trap.h"
|
|
||||||
|
|
||||||
SHELLPROC {
|
|
||||||
char *sm;
|
|
||||||
|
|
||||||
clear_traps(0);
|
|
||||||
for (sm = sigmode ; sm < sigmode + NSIG ; sm++) {
|
|
||||||
if (*sm == S_IGN)
|
|
||||||
*sm = S_HARD_IGN;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Signal handler.
|
|
||||||
*/
|
|
||||||
|
|
||||||
void
|
|
||||||
onsig(int signo)
|
|
||||||
{
|
|
||||||
bsd_signal(signo, onsig);
|
|
||||||
if (signo == SIGINT && trap[SIGINT] == NULL) {
|
|
||||||
onint();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
gotsig[signo - 1] = 1;
|
|
||||||
pendingsigs++;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Called to execute a trap. Perhaps we should avoid entering new trap
|
|
||||||
* handlers while we are executing a trap handler.
|
|
||||||
*/
|
|
||||||
|
|
||||||
void
|
|
||||||
dotrap(void)
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
int savestatus;
|
|
||||||
|
|
||||||
for (;;) {
|
|
||||||
for (i = 1 ; ; i++) {
|
|
||||||
if (gotsig[i - 1])
|
|
||||||
break;
|
|
||||||
if (i >= NSIG)
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
gotsig[i - 1] = 0;
|
|
||||||
savestatus=exitstatus;
|
|
||||||
evalstring(trap[i], 0);
|
|
||||||
exitstatus=savestatus;
|
|
||||||
}
|
|
||||||
done:
|
|
||||||
pendingsigs = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Controls whether the shell is interactive or not.
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
setinteractive(int on)
|
|
||||||
{
|
|
||||||
static int is_interactive;
|
|
||||||
|
|
||||||
if (on == is_interactive)
|
|
||||||
return;
|
|
||||||
setsignal(SIGINT, 0);
|
|
||||||
setsignal(SIGQUIT, 0);
|
|
||||||
setsignal(SIGTERM, 0);
|
|
||||||
is_interactive = on;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Called to exit the shell.
|
|
||||||
*/
|
|
||||||
|
|
||||||
void
|
|
||||||
exitshell(int status)
|
|
||||||
{
|
|
||||||
struct jmploc loc1, loc2;
|
|
||||||
char *p;
|
|
||||||
|
|
||||||
TRACE(("pid %d, exitshell(%d)\n", getpid(), status));
|
|
||||||
if (setjmp(loc1.loc)) {
|
|
||||||
goto l1;
|
|
||||||
}
|
|
||||||
if (setjmp(loc2.loc)) {
|
|
||||||
goto l2;
|
|
||||||
}
|
|
||||||
handler = &loc1;
|
|
||||||
if ((p = trap[0]) != NULL && *p != '\0') {
|
|
||||||
trap[0] = NULL;
|
|
||||||
evalstring(p, 0);
|
|
||||||
}
|
|
||||||
l1: handler = &loc2; /* probably unnecessary */
|
|
||||||
flushall();
|
|
||||||
#if JOBS
|
|
||||||
setjobctl(0);
|
|
||||||
#endif
|
|
||||||
l2: _exit(status);
|
|
||||||
/* NOTREACHED */
|
|
||||||
}
|
|
||||||
46
sh/trap.h
46
sh/trap.h
|
|
@ -1,46 +0,0 @@
|
||||||
/* $NetBSD: trap.h,v 1.17 2003/08/07 09:05:39 agc Exp $ */
|
|
||||||
|
|
||||||
/*-
|
|
||||||
* Copyright (c) 1991, 1993
|
|
||||||
* The Regents of the University of California. All rights reserved.
|
|
||||||
*
|
|
||||||
* This code is derived from software contributed to Berkeley by
|
|
||||||
* Kenneth Almquist.
|
|
||||||
*
|
|
||||||
* Redistribution and use in source and binary forms, with or without
|
|
||||||
* modification, are permitted provided that the following conditions
|
|
||||||
* are met:
|
|
||||||
* 1. Redistributions of source code must retain the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer.
|
|
||||||
* 2. Redistributions in binary form must reproduce the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer in the
|
|
||||||
* documentation and/or other materials provided with the distribution.
|
|
||||||
* 3. Neither the name of the University nor the names of its contributors
|
|
||||||
* may be used to endorse or promote products derived from this software
|
|
||||||
* without specific prior written permission.
|
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
|
||||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
||||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
||||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
|
||||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
||||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
|
||||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
|
||||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
||||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
|
||||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
|
||||||
* SUCH DAMAGE.
|
|
||||||
*
|
|
||||||
* @(#)trap.h 8.3 (Berkeley) 6/5/95
|
|
||||||
*/
|
|
||||||
|
|
||||||
extern int pendingsigs;
|
|
||||||
|
|
||||||
int trapcmd(int, char **);
|
|
||||||
void clear_traps(int);
|
|
||||||
long setsignal(int, int);
|
|
||||||
void ignoresig(int, int);
|
|
||||||
void onsig(int);
|
|
||||||
void dotrap(void);
|
|
||||||
void setinteractive(int);
|
|
||||||
void exitshell(int) __attribute__((__noreturn__));
|
|
||||||
825
sh/var.c
825
sh/var.c
|
|
@ -1,825 +0,0 @@
|
||||||
/* $NetBSD: var.c,v 1.36 2004/10/06 10:23:43 enami Exp $ */
|
|
||||||
|
|
||||||
/*-
|
|
||||||
* Copyright (c) 1991, 1993
|
|
||||||
* The Regents of the University of California. All rights reserved.
|
|
||||||
*
|
|
||||||
* This code is derived from software contributed to Berkeley by
|
|
||||||
* Kenneth Almquist.
|
|
||||||
*
|
|
||||||
* Redistribution and use in source and binary forms, with or without
|
|
||||||
* modification, are permitted provided that the following conditions
|
|
||||||
* are met:
|
|
||||||
* 1. Redistributions of source code must retain the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer.
|
|
||||||
* 2. Redistributions in binary form must reproduce the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer in the
|
|
||||||
* documentation and/or other materials provided with the distribution.
|
|
||||||
* 3. Neither the name of the University nor the names of its contributors
|
|
||||||
* may be used to endorse or promote products derived from this software
|
|
||||||
* without specific prior written permission.
|
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
|
||||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
||||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
||||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
|
||||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
||||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
|
||||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
|
||||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
||||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
|
||||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
|
||||||
* SUCH DAMAGE.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <sys/cdefs.h>
|
|
||||||
#ifndef lint
|
|
||||||
#if 0
|
|
||||||
static char sccsid[] = "@(#)var.c 8.3 (Berkeley) 5/4/95";
|
|
||||||
#else
|
|
||||||
__RCSID("$NetBSD: var.c,v 1.36 2004/10/06 10:23:43 enami Exp $");
|
|
||||||
#endif
|
|
||||||
#endif /* not lint */
|
|
||||||
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <paths.h>
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Shell variables.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "shell.h"
|
|
||||||
#include "output.h"
|
|
||||||
#include "expand.h"
|
|
||||||
#include "nodes.h" /* for other headers */
|
|
||||||
#include "eval.h" /* defines cmdenviron */
|
|
||||||
#include "exec.h"
|
|
||||||
#include "syntax.h"
|
|
||||||
#include "options.h"
|
|
||||||
#include "var.h"
|
|
||||||
#include "memalloc.h"
|
|
||||||
#include "error.h"
|
|
||||||
#include "mystring.h"
|
|
||||||
#include "parser.h"
|
|
||||||
#include "show.h"
|
|
||||||
#ifndef SMALL
|
|
||||||
#include "myhistedit.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef SMALL
|
|
||||||
#define VTABSIZE 39
|
|
||||||
#else
|
|
||||||
#define VTABSIZE 517
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
struct varinit {
|
|
||||||
struct var *var;
|
|
||||||
int flags;
|
|
||||||
const char *text;
|
|
||||||
void (*func)(const char *);
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
#if ATTY
|
|
||||||
struct var vatty;
|
|
||||||
#endif
|
|
||||||
#ifdef WITH_HISTORY
|
|
||||||
struct var vhistsize;
|
|
||||||
struct var vterm;
|
|
||||||
#endif
|
|
||||||
struct var vifs;
|
|
||||||
struct var vmpath;
|
|
||||||
struct var vpath;
|
|
||||||
struct var vps1;
|
|
||||||
struct var vps2;
|
|
||||||
struct var vps4;
|
|
||||||
struct var vvers;
|
|
||||||
struct var voptind;
|
|
||||||
|
|
||||||
const struct varinit varinit[] = {
|
|
||||||
#if ATTY
|
|
||||||
{ &vatty, VSTRFIXED|VTEXTFIXED|VUNSET, "ATTY=",
|
|
||||||
NULL },
|
|
||||||
#endif
|
|
||||||
#ifdef WITH_HISTORY
|
|
||||||
{ &vhistsize, VSTRFIXED|VTEXTFIXED|VUNSET, "HISTSIZE=",
|
|
||||||
sethistsize },
|
|
||||||
#endif
|
|
||||||
{ &vifs, VSTRFIXED|VTEXTFIXED, "IFS= \t\n",
|
|
||||||
NULL },
|
|
||||||
{ &vmpath, VSTRFIXED|VTEXTFIXED|VUNSET, "MAILPATH=",
|
|
||||||
NULL },
|
|
||||||
{ &vpath, VSTRFIXED|VTEXTFIXED, "PATH=" _PATH_DEFPATH,
|
|
||||||
changepath },
|
|
||||||
/*
|
|
||||||
* vps1 depends on uid
|
|
||||||
*/
|
|
||||||
{ &vps2, VSTRFIXED|VTEXTFIXED, "PS2=> ",
|
|
||||||
NULL },
|
|
||||||
{ &vps4, VSTRFIXED|VTEXTFIXED, "PS4=+ ",
|
|
||||||
NULL },
|
|
||||||
#ifdef WITH_HISTORY
|
|
||||||
{ &vterm, VSTRFIXED|VTEXTFIXED|VUNSET, "TERM=",
|
|
||||||
setterm },
|
|
||||||
#endif
|
|
||||||
{ &voptind, VSTRFIXED|VTEXTFIXED|VNOFUNC, "OPTIND=1",
|
|
||||||
getoptsreset },
|
|
||||||
{ NULL, 0, NULL,
|
|
||||||
NULL }
|
|
||||||
};
|
|
||||||
|
|
||||||
struct var *vartab[VTABSIZE];
|
|
||||||
|
|
||||||
STATIC int strequal(const char *, const char *);
|
|
||||||
STATIC struct var *find_var(const char *, struct var ***, int *);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Initialize the varable symbol tables and import the environment
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifdef mkinit
|
|
||||||
INCLUDE "var.h"
|
|
||||||
MKINIT char **environ;
|
|
||||||
INIT {
|
|
||||||
char **envp;
|
|
||||||
|
|
||||||
initvar();
|
|
||||||
for (envp = environ ; *envp ; envp++) {
|
|
||||||
if (strchr(*envp, '=')) {
|
|
||||||
setvareq(*envp, VEXPORT|VTEXTFIXED);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* This routine initializes the builtin variables. It is called when the
|
|
||||||
* shell is initialized and again when a shell procedure is spawned.
|
|
||||||
*/
|
|
||||||
|
|
||||||
void
|
|
||||||
initvar(void)
|
|
||||||
{
|
|
||||||
const struct varinit *ip;
|
|
||||||
struct var *vp;
|
|
||||||
struct var **vpp;
|
|
||||||
|
|
||||||
for (ip = varinit ; (vp = ip->var) != NULL ; ip++) {
|
|
||||||
if (find_var(ip->text, &vpp, &vp->name_len) != NULL)
|
|
||||||
continue;
|
|
||||||
vp->next = *vpp;
|
|
||||||
*vpp = vp;
|
|
||||||
vp->text = strdup(ip->text);
|
|
||||||
vp->flags = ip->flags;
|
|
||||||
vp->func = ip->func;
|
|
||||||
}
|
|
||||||
/*
|
|
||||||
* PS1 depends on uid
|
|
||||||
*/
|
|
||||||
if (find_var("PS1", &vpp, &vps1.name_len) == NULL) {
|
|
||||||
vps1.next = *vpp;
|
|
||||||
*vpp = &vps1;
|
|
||||||
vps1.text = strdup(geteuid() ? "PS1=$ " : "PS1=# ");
|
|
||||||
vps1.flags = VSTRFIXED|VTEXTFIXED;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Safe version of setvar, returns 1 on success 0 on failure.
|
|
||||||
*/
|
|
||||||
|
|
||||||
int
|
|
||||||
setvarsafe(const char *name, const char *val, int flags)
|
|
||||||
{
|
|
||||||
struct jmploc jmploc;
|
|
||||||
struct jmploc *volatile savehandler = handler;
|
|
||||||
int err = 0;
|
|
||||||
#ifdef __GNUC__
|
|
||||||
(void) &err;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (setjmp(jmploc.loc))
|
|
||||||
err = 1;
|
|
||||||
else {
|
|
||||||
handler = &jmploc;
|
|
||||||
setvar(name, val, flags);
|
|
||||||
}
|
|
||||||
handler = savehandler;
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Set the value of a variable. The flags argument is ored with the
|
|
||||||
* flags of the variable. If val is NULL, the variable is unset.
|
|
||||||
*/
|
|
||||||
|
|
||||||
void
|
|
||||||
setvar(const char *name, const char *val, int flags)
|
|
||||||
{
|
|
||||||
const char *p;
|
|
||||||
const char *q;
|
|
||||||
char *d;
|
|
||||||
int len;
|
|
||||||
int namelen;
|
|
||||||
char *nameeq;
|
|
||||||
int isbad;
|
|
||||||
|
|
||||||
isbad = 0;
|
|
||||||
p = name;
|
|
||||||
if (! is_name(*p))
|
|
||||||
isbad = 1;
|
|
||||||
p++;
|
|
||||||
for (;;) {
|
|
||||||
if (! is_in_name(*p)) {
|
|
||||||
if (*p == '\0' || *p == '=')
|
|
||||||
break;
|
|
||||||
isbad = 1;
|
|
||||||
}
|
|
||||||
p++;
|
|
||||||
}
|
|
||||||
namelen = p - name;
|
|
||||||
if (isbad)
|
|
||||||
error("%.*s: bad variable name", namelen, name);
|
|
||||||
len = namelen + 2; /* 2 is space for '=' and '\0' */
|
|
||||||
if (val == NULL) {
|
|
||||||
flags |= VUNSET;
|
|
||||||
} else {
|
|
||||||
len += strlen(val);
|
|
||||||
}
|
|
||||||
d = nameeq = ckmalloc(len);
|
|
||||||
q = name;
|
|
||||||
while (--namelen >= 0)
|
|
||||||
*d++ = *q++;
|
|
||||||
*d++ = '=';
|
|
||||||
*d = '\0';
|
|
||||||
if (val)
|
|
||||||
scopy(val, d);
|
|
||||||
setvareq(nameeq, flags);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Same as setvar except that the variable and value are passed in
|
|
||||||
* the first argument as name=value. Since the first argument will
|
|
||||||
* be actually stored in the table, it should not be a string that
|
|
||||||
* will go away.
|
|
||||||
*/
|
|
||||||
|
|
||||||
void
|
|
||||||
setvareq(char *s, int flags)
|
|
||||||
{
|
|
||||||
struct var *vp, **vpp;
|
|
||||||
int nlen;
|
|
||||||
|
|
||||||
if (aflag)
|
|
||||||
flags |= VEXPORT;
|
|
||||||
vp = find_var(s, &vpp, &nlen);
|
|
||||||
if (vp != NULL) {
|
|
||||||
if (vp->flags & VREADONLY)
|
|
||||||
error("%.*s: is read only", vp->name_len, s);
|
|
||||||
if (flags & VNOSET)
|
|
||||||
return;
|
|
||||||
INTOFF;
|
|
||||||
|
|
||||||
if (vp->func && (flags & VNOFUNC) == 0)
|
|
||||||
(*vp->func)(s + vp->name_len + 1);
|
|
||||||
|
|
||||||
if ((vp->flags & (VTEXTFIXED|VSTACK)) == 0)
|
|
||||||
ckfree(vp->text);
|
|
||||||
|
|
||||||
vp->flags &= ~(VTEXTFIXED|VSTACK|VUNSET);
|
|
||||||
vp->flags |= flags & ~VNOFUNC;
|
|
||||||
vp->text = s;
|
|
||||||
|
|
||||||
INTON;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
/* not found */
|
|
||||||
if (flags & VNOSET)
|
|
||||||
return;
|
|
||||||
vp = ckmalloc(sizeof (*vp));
|
|
||||||
vp->flags = flags & ~VNOFUNC;
|
|
||||||
vp->text = s;
|
|
||||||
vp->name_len = nlen;
|
|
||||||
vp->next = *vpp;
|
|
||||||
vp->func = NULL;
|
|
||||||
*vpp = vp;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Process a linked list of variable assignments.
|
|
||||||
*/
|
|
||||||
|
|
||||||
void
|
|
||||||
listsetvar(struct strlist *list, int flags)
|
|
||||||
{
|
|
||||||
struct strlist *lp;
|
|
||||||
|
|
||||||
INTOFF;
|
|
||||||
for (lp = list ; lp ; lp = lp->next) {
|
|
||||||
setvareq(savestr(lp->text), flags);
|
|
||||||
}
|
|
||||||
INTON;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
listmklocal(struct strlist *list, int flags)
|
|
||||||
{
|
|
||||||
struct strlist *lp;
|
|
||||||
|
|
||||||
for (lp = list ; lp ; lp = lp->next)
|
|
||||||
mklocal(lp->text, flags);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Find the value of a variable. Returns NULL if not set.
|
|
||||||
*/
|
|
||||||
|
|
||||||
char *
|
|
||||||
lookupvar(const char *name)
|
|
||||||
{
|
|
||||||
struct var *v;
|
|
||||||
|
|
||||||
v = find_var(name, NULL, NULL);
|
|
||||||
if (v == NULL || v->flags & VUNSET)
|
|
||||||
return NULL;
|
|
||||||
return v->text + v->name_len + 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Search the environment of a builtin command. If the second argument
|
|
||||||
* is nonzero, return the value of a variable even if it hasn't been
|
|
||||||
* exported.
|
|
||||||
*/
|
|
||||||
|
|
||||||
char *
|
|
||||||
bltinlookup(const char *name, int doall)
|
|
||||||
{
|
|
||||||
struct strlist *sp;
|
|
||||||
struct var *v;
|
|
||||||
|
|
||||||
for (sp = cmdenviron ; sp ; sp = sp->next) {
|
|
||||||
if (strequal(sp->text, name))
|
|
||||||
return strchr(sp->text, '=') + 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
v = find_var(name, NULL, NULL);
|
|
||||||
|
|
||||||
if (v == NULL || v->flags & VUNSET || (!doall && !(v->flags & VEXPORT)))
|
|
||||||
return NULL;
|
|
||||||
return v->text + v->name_len + 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Generate a list of exported variables. This routine is used to construct
|
|
||||||
* the third argument to execve when executing a program.
|
|
||||||
*/
|
|
||||||
|
|
||||||
char **
|
|
||||||
environment(void)
|
|
||||||
{
|
|
||||||
int nenv;
|
|
||||||
struct var **vpp;
|
|
||||||
struct var *vp;
|
|
||||||
char **env;
|
|
||||||
char **ep;
|
|
||||||
|
|
||||||
nenv = 0;
|
|
||||||
for (vpp = vartab ; vpp < vartab + VTABSIZE ; vpp++) {
|
|
||||||
for (vp = *vpp ; vp ; vp = vp->next)
|
|
||||||
if (vp->flags & VEXPORT)
|
|
||||||
nenv++;
|
|
||||||
}
|
|
||||||
ep = env = stalloc((nenv + 1) * sizeof *env);
|
|
||||||
for (vpp = vartab ; vpp < vartab + VTABSIZE ; vpp++) {
|
|
||||||
for (vp = *vpp ; vp ; vp = vp->next)
|
|
||||||
if (vp->flags & VEXPORT)
|
|
||||||
*ep++ = vp->text;
|
|
||||||
}
|
|
||||||
*ep = NULL;
|
|
||||||
return env;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Called when a shell procedure is invoked to clear out nonexported
|
|
||||||
* variables. It is also necessary to reallocate variables of with
|
|
||||||
* VSTACK set since these are currently allocated on the stack.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifdef mkinit
|
|
||||||
void shprocvar(void);
|
|
||||||
|
|
||||||
SHELLPROC {
|
|
||||||
shprocvar();
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
void
|
|
||||||
shprocvar(void)
|
|
||||||
{
|
|
||||||
struct var **vpp;
|
|
||||||
struct var *vp, **prev;
|
|
||||||
|
|
||||||
for (vpp = vartab ; vpp < vartab + VTABSIZE ; vpp++) {
|
|
||||||
for (prev = vpp ; (vp = *prev) != NULL ; ) {
|
|
||||||
if ((vp->flags & VEXPORT) == 0) {
|
|
||||||
*prev = vp->next;
|
|
||||||
if ((vp->flags & VTEXTFIXED) == 0)
|
|
||||||
ckfree(vp->text);
|
|
||||||
if ((vp->flags & VSTRFIXED) == 0)
|
|
||||||
ckfree(vp);
|
|
||||||
} else {
|
|
||||||
if (vp->flags & VSTACK) {
|
|
||||||
vp->text = savestr(vp->text);
|
|
||||||
vp->flags &=~ VSTACK;
|
|
||||||
}
|
|
||||||
prev = &vp->next;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
initvar();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Command to list all variables which are set. Currently this command
|
|
||||||
* is invoked from the set command when the set command is called without
|
|
||||||
* any variables.
|
|
||||||
*/
|
|
||||||
|
|
||||||
void
|
|
||||||
print_quoted(const char *p)
|
|
||||||
{
|
|
||||||
const char *q;
|
|
||||||
|
|
||||||
if (strcspn(p, "|&;<>()$`\\\"' \t\n*?[]#~=%") == strlen(p)) {
|
|
||||||
out1fmt("%s", p);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
while (*p) {
|
|
||||||
if (*p == '\'') {
|
|
||||||
out1fmt("\\'");
|
|
||||||
p++;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
q = index(p, '\'');
|
|
||||||
if (!q) {
|
|
||||||
out1fmt("'%s'", p );
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
out1fmt("'%.*s'", (int)(q - p), p );
|
|
||||||
p = q;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
|
||||||
sort_var(const void *v_v1, const void *v_v2)
|
|
||||||
{
|
|
||||||
const struct var * const *v1 = v_v1;
|
|
||||||
const struct var * const *v2 = v_v2;
|
|
||||||
|
|
||||||
/* XXX Will anyone notice we include the '=' of the shorter name? */
|
|
||||||
return strcmp((*v1)->text, (*v2)->text);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* POSIX requires that 'set' (but not export or readonly) output the
|
|
||||||
* variables in lexicographic order - by the locale's collating order (sigh).
|
|
||||||
* Maybe we could keep them in an ordered balanced binary tree
|
|
||||||
* instead of hashed lists.
|
|
||||||
* For now just roll 'em through qsort for printing...
|
|
||||||
*/
|
|
||||||
|
|
||||||
int
|
|
||||||
showvars(const char *name, int flag, int show_value)
|
|
||||||
{
|
|
||||||
struct var **vpp;
|
|
||||||
struct var *vp;
|
|
||||||
const char *p;
|
|
||||||
|
|
||||||
static struct var **list; /* static in case we are interrupted */
|
|
||||||
static int list_len;
|
|
||||||
int count = 0;
|
|
||||||
|
|
||||||
if (!list) {
|
|
||||||
list_len = 32;
|
|
||||||
list = ckmalloc(list_len * sizeof *list);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (vpp = vartab ; vpp < vartab + VTABSIZE ; vpp++) {
|
|
||||||
for (vp = *vpp ; vp ; vp = vp->next) {
|
|
||||||
if (flag && !(vp->flags & flag))
|
|
||||||
continue;
|
|
||||||
if (vp->flags & VUNSET && !(show_value & 2))
|
|
||||||
continue;
|
|
||||||
if (count >= list_len) {
|
|
||||||
list = ckrealloc(list,
|
|
||||||
(list_len << 1) * sizeof *list);
|
|
||||||
list_len <<= 1;
|
|
||||||
}
|
|
||||||
list[count++] = vp;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
qsort(list, count, sizeof *list, sort_var);
|
|
||||||
|
|
||||||
for (vpp = list; count--; vpp++) {
|
|
||||||
vp = *vpp;
|
|
||||||
if (name)
|
|
||||||
out1fmt("%s ", name);
|
|
||||||
for (p = vp->text ; *p != '=' ; p++)
|
|
||||||
out1c(*p);
|
|
||||||
if (!(vp->flags & VUNSET) && show_value) {
|
|
||||||
out1fmt("=");
|
|
||||||
print_quoted(++p);
|
|
||||||
}
|
|
||||||
out1c('\n');
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* The export and readonly commands.
|
|
||||||
*/
|
|
||||||
|
|
||||||
int
|
|
||||||
exportcmd(int argc, char **argv)
|
|
||||||
{
|
|
||||||
struct var *vp;
|
|
||||||
char *name;
|
|
||||||
const char *p;
|
|
||||||
int flag = argv[0][0] == 'r'? VREADONLY : VEXPORT;
|
|
||||||
int pflag;
|
|
||||||
|
|
||||||
pflag = nextopt("p") == 'p' ? 3 : 0;
|
|
||||||
if (argc <= 1 || pflag) {
|
|
||||||
showvars( pflag ? argv[0] : 0, flag, pflag );
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
while ((name = *argptr++) != NULL) {
|
|
||||||
if ((p = strchr(name, '=')) != NULL) {
|
|
||||||
p++;
|
|
||||||
} else {
|
|
||||||
vp = find_var(name, NULL, NULL);
|
|
||||||
if (vp != NULL) {
|
|
||||||
vp->flags |= flag;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
setvar(name, p, flag);
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* The "local" command.
|
|
||||||
*/
|
|
||||||
|
|
||||||
int
|
|
||||||
localcmd(int argc, char **argv)
|
|
||||||
{
|
|
||||||
char *name;
|
|
||||||
|
|
||||||
if (! in_function())
|
|
||||||
error("Not in a function");
|
|
||||||
while ((name = *argptr++) != NULL) {
|
|
||||||
mklocal(name, 0);
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Make a variable a local variable. When a variable is made local, it's
|
|
||||||
* value and flags are saved in a localvar structure. The saved values
|
|
||||||
* will be restored when the shell function returns. We handle the name
|
|
||||||
* "-" as a special case.
|
|
||||||
*/
|
|
||||||
|
|
||||||
void
|
|
||||||
mklocal(const char *name, int flags)
|
|
||||||
{
|
|
||||||
struct localvar *lvp;
|
|
||||||
struct var **vpp;
|
|
||||||
struct var *vp;
|
|
||||||
|
|
||||||
INTOFF;
|
|
||||||
lvp = ckmalloc(sizeof (struct localvar));
|
|
||||||
if (name[0] == '-' && name[1] == '\0') {
|
|
||||||
char *p;
|
|
||||||
p = ckmalloc(sizeof_optlist);
|
|
||||||
lvp->text = memcpy(p, optlist, sizeof_optlist);
|
|
||||||
vp = NULL;
|
|
||||||
} else {
|
|
||||||
vp = find_var(name, &vpp, NULL);
|
|
||||||
if (vp == NULL) {
|
|
||||||
if (strchr(name, '='))
|
|
||||||
setvareq(savestr(name), VSTRFIXED|flags);
|
|
||||||
else
|
|
||||||
setvar(name, NULL, VSTRFIXED|flags);
|
|
||||||
vp = *vpp; /* the new variable */
|
|
||||||
lvp->text = NULL;
|
|
||||||
lvp->flags = VUNSET;
|
|
||||||
} else {
|
|
||||||
lvp->text = vp->text;
|
|
||||||
lvp->flags = vp->flags;
|
|
||||||
vp->flags |= VSTRFIXED|VTEXTFIXED;
|
|
||||||
if (name[vp->name_len] == '=')
|
|
||||||
setvareq(savestr(name), flags);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
lvp->vp = vp;
|
|
||||||
lvp->next = localvars;
|
|
||||||
localvars = lvp;
|
|
||||||
INTON;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Called after a function returns.
|
|
||||||
*/
|
|
||||||
|
|
||||||
void
|
|
||||||
poplocalvars(void)
|
|
||||||
{
|
|
||||||
struct localvar *lvp;
|
|
||||||
struct var *vp;
|
|
||||||
|
|
||||||
while ((lvp = localvars) != NULL) {
|
|
||||||
localvars = lvp->next;
|
|
||||||
vp = lvp->vp;
|
|
||||||
TRACE(("poplocalvar %s", vp ? vp->text : "-"));
|
|
||||||
if (vp == NULL) { /* $- saved */
|
|
||||||
memcpy(optlist, lvp->text, sizeof_optlist);
|
|
||||||
ckfree(lvp->text);
|
|
||||||
} else if ((lvp->flags & (VUNSET|VSTRFIXED)) == VUNSET) {
|
|
||||||
(void)unsetvar(vp->text, 0);
|
|
||||||
} else {
|
|
||||||
if (vp->func && (vp->flags & VNOFUNC) == 0)
|
|
||||||
(*vp->func)(lvp->text + vp->name_len + 1);
|
|
||||||
if ((vp->flags & VTEXTFIXED) == 0)
|
|
||||||
ckfree(vp->text);
|
|
||||||
vp->flags = lvp->flags;
|
|
||||||
vp->text = lvp->text;
|
|
||||||
}
|
|
||||||
ckfree(lvp);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int
|
|
||||||
setvarcmd(int argc, char **argv)
|
|
||||||
{
|
|
||||||
if (argc <= 2)
|
|
||||||
return unsetcmd(argc, argv);
|
|
||||||
else if (argc == 3)
|
|
||||||
setvar(argv[1], argv[2], 0);
|
|
||||||
else
|
|
||||||
error("List assignment not implemented");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* The unset builtin command. We unset the function before we unset the
|
|
||||||
* variable to allow a function to be unset when there is a readonly variable
|
|
||||||
* with the same name.
|
|
||||||
*/
|
|
||||||
|
|
||||||
int
|
|
||||||
unsetcmd(int argc, char **argv)
|
|
||||||
{
|
|
||||||
char **ap;
|
|
||||||
int i;
|
|
||||||
int flg_func = 0;
|
|
||||||
int flg_var = 0;
|
|
||||||
int ret = 0;
|
|
||||||
|
|
||||||
while ((i = nextopt("evf")) != '\0') {
|
|
||||||
if (i == 'f')
|
|
||||||
flg_func = 1;
|
|
||||||
else
|
|
||||||
flg_var = i;
|
|
||||||
}
|
|
||||||
if (flg_func == 0 && flg_var == 0)
|
|
||||||
flg_var = 1;
|
|
||||||
|
|
||||||
for (ap = argptr; *ap ; ap++) {
|
|
||||||
if (flg_func)
|
|
||||||
ret |= unsetfunc(*ap);
|
|
||||||
if (flg_var)
|
|
||||||
ret |= unsetvar(*ap, flg_var == 'e');
|
|
||||||
}
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Unset the specified variable.
|
|
||||||
*/
|
|
||||||
|
|
||||||
int
|
|
||||||
unsetvar(const char *s, int unexport)
|
|
||||||
{
|
|
||||||
struct var **vpp;
|
|
||||||
struct var *vp;
|
|
||||||
|
|
||||||
vp = find_var(s, &vpp, NULL);
|
|
||||||
if (vp == NULL)
|
|
||||||
return 1;
|
|
||||||
|
|
||||||
if (vp->flags & VREADONLY)
|
|
||||||
return (1);
|
|
||||||
|
|
||||||
INTOFF;
|
|
||||||
if (unexport) {
|
|
||||||
vp->flags &= ~VEXPORT;
|
|
||||||
} else {
|
|
||||||
if (vp->text[vp->name_len + 1] != '\0')
|
|
||||||
setvar(s, nullstr, 0);
|
|
||||||
vp->flags &= ~VEXPORT;
|
|
||||||
vp->flags |= VUNSET;
|
|
||||||
if ((vp->flags & VSTRFIXED) == 0) {
|
|
||||||
if ((vp->flags & VTEXTFIXED) == 0)
|
|
||||||
ckfree(vp->text);
|
|
||||||
*vpp = vp->next;
|
|
||||||
ckfree(vp);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
INTON;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Returns true if the two strings specify the same varable. The first
|
|
||||||
* variable name is terminated by '='; the second may be terminated by
|
|
||||||
* either '=' or '\0'.
|
|
||||||
*/
|
|
||||||
|
|
||||||
STATIC int
|
|
||||||
strequal(const char *p, const char *q)
|
|
||||||
{
|
|
||||||
while (*p == *q++) {
|
|
||||||
if (*p++ == '=')
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
if (*p == '=' && *(q - 1) == '\0')
|
|
||||||
return 1;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Search for a variable.
|
|
||||||
* 'name' may be terminated by '=' or a NUL.
|
|
||||||
* vppp is set to the pointer to vp, or the list head if vp isn't found
|
|
||||||
* lenp is set to the number of charactets in 'name'
|
|
||||||
*/
|
|
||||||
|
|
||||||
STATIC struct var *
|
|
||||||
find_var(const char *name, struct var ***vppp, int *lenp)
|
|
||||||
{
|
|
||||||
unsigned int hashval;
|
|
||||||
int len;
|
|
||||||
struct var *vp, **vpp;
|
|
||||||
const char *p = name;
|
|
||||||
|
|
||||||
hashval = 0;
|
|
||||||
while (*p && *p != '=')
|
|
||||||
hashval = 2 * hashval + (unsigned char)*p++;
|
|
||||||
len = p - name;
|
|
||||||
|
|
||||||
if (lenp)
|
|
||||||
*lenp = len;
|
|
||||||
vpp = &vartab[hashval % VTABSIZE];
|
|
||||||
if (vppp)
|
|
||||||
*vppp = vpp;
|
|
||||||
|
|
||||||
for (vp = *vpp ; vp ; vpp = &vp->next, vp = *vpp) {
|
|
||||||
if (vp->name_len != len)
|
|
||||||
continue;
|
|
||||||
if (memcmp(vp->text, name, len) != 0)
|
|
||||||
continue;
|
|
||||||
if (vppp)
|
|
||||||
*vppp = vpp;
|
|
||||||
return vp;
|
|
||||||
}
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
131
sh/var.h
131
sh/var.h
|
|
@ -1,131 +0,0 @@
|
||||||
/* $NetBSD: var.h,v 1.23 2004/10/02 12:16:53 dsl Exp $ */
|
|
||||||
|
|
||||||
/*-
|
|
||||||
* Copyright (c) 1991, 1993
|
|
||||||
* The Regents of the University of California. All rights reserved.
|
|
||||||
*
|
|
||||||
* This code is derived from software contributed to Berkeley by
|
|
||||||
* Kenneth Almquist.
|
|
||||||
*
|
|
||||||
* Redistribution and use in source and binary forms, with or without
|
|
||||||
* modification, are permitted provided that the following conditions
|
|
||||||
* are met:
|
|
||||||
* 1. Redistributions of source code must retain the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer.
|
|
||||||
* 2. Redistributions in binary form must reproduce the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer in the
|
|
||||||
* documentation and/or other materials provided with the distribution.
|
|
||||||
* 3. Neither the name of the University nor the names of its contributors
|
|
||||||
* may be used to endorse or promote products derived from this software
|
|
||||||
* without specific prior written permission.
|
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
|
||||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
||||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
||||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
|
||||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
||||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
|
||||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
|
||||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
||||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
|
||||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
|
||||||
* SUCH DAMAGE.
|
|
||||||
*
|
|
||||||
* @(#)var.h 8.2 (Berkeley) 5/4/95
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Shell variables.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* flags */
|
|
||||||
#define VEXPORT 0x01 /* variable is exported */
|
|
||||||
#define VREADONLY 0x02 /* variable cannot be modified */
|
|
||||||
#define VSTRFIXED 0x04 /* variable struct is statically allocated */
|
|
||||||
#define VTEXTFIXED 0x08 /* text is statically allocated */
|
|
||||||
#define VSTACK 0x10 /* text is allocated on the stack */
|
|
||||||
#define VUNSET 0x20 /* the variable is not set */
|
|
||||||
#define VNOFUNC 0x40 /* don't call the callback function */
|
|
||||||
#define VNOSET 0x80 /* do not set variable - just readonly test */
|
|
||||||
|
|
||||||
|
|
||||||
struct var {
|
|
||||||
struct var *next; /* next entry in hash list */
|
|
||||||
int flags; /* flags are defined above */
|
|
||||||
char *text; /* name=value */
|
|
||||||
int name_len; /* length of name */
|
|
||||||
void (*func)(const char *);
|
|
||||||
/* function to be called when */
|
|
||||||
/* the variable gets set/unset */
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
struct localvar {
|
|
||||||
struct localvar *next; /* next local variable in list */
|
|
||||||
struct var *vp; /* the variable that was made local */
|
|
||||||
int flags; /* saved flags */
|
|
||||||
char *text; /* saved text */
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
struct localvar *localvars;
|
|
||||||
|
|
||||||
#if ATTY
|
|
||||||
extern struct var vatty;
|
|
||||||
#endif
|
|
||||||
extern struct var vifs;
|
|
||||||
extern struct var vmpath;
|
|
||||||
extern struct var vpath;
|
|
||||||
extern struct var vps1;
|
|
||||||
extern struct var vps2;
|
|
||||||
extern struct var vps4;
|
|
||||||
#ifdef WITH_HISTORY
|
|
||||||
extern struct var vterm;
|
|
||||||
extern struct var vtermcap;
|
|
||||||
extern struct var vhistsize;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/*
|
|
||||||
* The following macros access the values of the above variables.
|
|
||||||
* They have to skip over the name. They return the null string
|
|
||||||
* for unset variables.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#define ifsval() (vifs.text + 4)
|
|
||||||
#define ifsset() ((vifs.flags & VUNSET) == 0)
|
|
||||||
#define mpathval() (vmpath.text + 9)
|
|
||||||
#define pathval() (vpath.text + 5)
|
|
||||||
#define ps1val() (vps1.text + 4)
|
|
||||||
#define ps2val() (vps2.text + 4)
|
|
||||||
#define ps4val() (vps4.text + 4)
|
|
||||||
#define optindval() (voptind.text + 7)
|
|
||||||
#ifdef WITH_HISTORY
|
|
||||||
#define histsizeval() (vhistsize.text + 9)
|
|
||||||
#define termval() (vterm.text + 5)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if ATTY
|
|
||||||
#define attyset() ((vatty.flags & VUNSET) == 0)
|
|
||||||
#endif
|
|
||||||
#define mpathset() ((vmpath.flags & VUNSET) == 0)
|
|
||||||
|
|
||||||
void initvar(void);
|
|
||||||
void setvar(const char *, const char *, int);
|
|
||||||
void setvareq(char *, int);
|
|
||||||
struct strlist;
|
|
||||||
void listsetvar(struct strlist *, int);
|
|
||||||
char *lookupvar(const char *);
|
|
||||||
char *bltinlookup(const char *, int);
|
|
||||||
char **environment(void);
|
|
||||||
void shprocvar(void);
|
|
||||||
int showvars(const char *, int, int);
|
|
||||||
int exportcmd(int, char **);
|
|
||||||
int localcmd(int, char **);
|
|
||||||
void mklocal(const char *, int);
|
|
||||||
void listmklocal(struct strlist *, int);
|
|
||||||
void poplocalvars(void);
|
|
||||||
int setvarcmd(int, char **);
|
|
||||||
int unsetcmd(int, char **);
|
|
||||||
int unsetvar(const char *, int);
|
|
||||||
int setvarsafe(const char *, const char *, int);
|
|
||||||
void print_quoted(const char *);
|
|
||||||
Loading…
Add table
Reference in a new issue