Compare commits
386 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
72542ac0a7 | ||
|
|
818b1a2741 | ||
|
|
2862654b07 | ||
|
|
26cf8b90ea | ||
|
|
1560fc9b94 | ||
|
|
af78f809ee | ||
|
|
0e44ca2b61 | ||
|
|
2db64a7fa5 | ||
|
|
3a3f4496d9 | ||
|
|
f73affcfc3 | ||
|
|
dc4916c77a | ||
|
|
0a9128303d | ||
|
|
ccd02a6028 | ||
|
|
b015dae3e7 | ||
|
|
dc67b37a10 | ||
|
|
4e0316611a | ||
|
|
6b2ad6fdfd | ||
|
|
a2b1a5134b | ||
|
|
7dd225ffb2 | ||
|
|
2958815463 | ||
|
|
9200a8a253 | ||
|
|
691b09f232 | ||
|
|
d61a481169 | ||
|
|
ef8ec86b78 | ||
|
|
18e7b315a1 | ||
|
|
01c0669075 | ||
|
|
57a5797045 | ||
|
|
7b4cfd585a | ||
|
|
3354ba1b6c | ||
|
|
21e61a600d | ||
|
|
4928e42efb | ||
|
|
70b95c31bc | ||
|
|
9581f1596f | ||
|
|
85198a280c | ||
|
|
647d1496f3 | ||
|
|
321622a318 | ||
|
|
c0ed0de7d1 | ||
|
|
c808aeb74e | ||
|
|
735d605330 | ||
|
|
056ac0a0d3 | ||
|
|
6ccd37a982 | ||
|
|
0be7f44224 | ||
|
|
a2d3b518d8 | ||
|
|
7507ebfeca | ||
|
|
f3f2e92191 | ||
|
|
288ee57135 | ||
|
|
fedb5c0368 | ||
|
|
3b2c65e323 | ||
|
|
5596ab1ec7 | ||
|
|
75f8ceb70e | ||
|
|
31c62a7347 | ||
|
|
70ab580d6b | ||
|
|
bd2ddd5fd4 | ||
|
|
4e63801916 | ||
|
|
1588a9ba77 | ||
|
|
98410fd5fe | ||
|
|
5c4a1e5c95 | ||
|
|
9843d7a625 | ||
|
|
f4b7a16f7b | ||
|
|
3fcf9fde61 | ||
|
|
6d50591226 | ||
|
|
4148c24393 | ||
|
|
454bb40129 | ||
|
|
f8eb059bb9 | ||
|
|
5f46b37a3d | ||
|
|
97fa05d773 | ||
|
|
52b71b2396 | ||
|
|
84b77d5bfd | ||
|
|
8c9e1cf4c5 | ||
|
|
92e57afdf3 | ||
|
|
3b08825d85 | ||
|
|
bf08c90e74 | ||
|
|
238ae978ba | ||
|
|
a9f2f36f46 | ||
|
|
be30a639cd | ||
|
|
1bf8a2e8bf | ||
|
|
d75a1c3f38 | ||
|
|
3bb73b431b | ||
|
|
2d95b37f12 | ||
|
|
77474b28e8 | ||
|
|
f7992c94ec | ||
|
|
168d766f32 | ||
|
|
825f29fd89 | ||
|
|
cbb67705d5 | ||
|
|
f150b11a7b | ||
|
|
654f6faf05 | ||
|
|
49d2195722 | ||
|
|
448376ee7e | ||
|
|
3275602598 | ||
|
|
a47531cc97 | ||
|
|
0d5c50f3fc | ||
|
|
3f58857ce9 | ||
|
|
b267d42531 | ||
|
|
1ff8616378 | ||
|
|
cb2f124830 | ||
|
|
bd27c5240b | ||
|
|
b857dec78d | ||
|
|
1d300550cf | ||
|
|
c6f8154df0 | ||
|
|
304471a107 | ||
|
|
20a13246a8 | ||
|
|
9f2f3dd488 | ||
|
|
df9326a340 | ||
|
|
624f17ee04 | ||
|
|
ebde52a9bc | ||
|
|
a12c7ad963 | ||
|
|
63a271200e | ||
|
|
3c907e6ef1 | ||
|
|
8ea438ae93 | ||
|
|
41e9fedf87 | ||
|
|
fa59af2bc0 | ||
|
|
047847e628 | ||
|
|
5358dc42bf | ||
|
|
ce5add84e8 | ||
|
|
e8edfe876d | ||
|
|
73e4e31376 | ||
|
|
f9e4768eb4 | ||
|
|
82ae9b9c5c | ||
|
|
980b58d8d2 | ||
|
|
2194bc0310 | ||
|
|
d954a122f7 | ||
|
|
78fe72e198 | ||
|
|
7d6b1dcf1e | ||
|
|
a6ab1cbd34 | ||
|
|
722f1b2b9f | ||
|
|
94b936d7c1 | ||
|
|
8412423248 | ||
|
|
bcbac65a07 | ||
|
|
80e2b3ade6 | ||
|
|
f47aa04a30 | ||
|
|
f65b3b8fbf | ||
|
|
b01aff70d2 | ||
|
|
8b3ddfc19f | ||
|
|
f307d84cda | ||
|
|
61b9193ced | ||
|
|
7d46116e47 | ||
|
|
9092146be7 | ||
|
|
753f7bebde | ||
|
|
324c6f583d | ||
|
|
dfaf30e54d | ||
|
|
53a6054b66 | ||
|
|
6f77685609 | ||
|
|
f7984144d5 | ||
|
|
dac2e8fcc9 | ||
|
|
da42185e1c | ||
|
|
4daf936bd2 | ||
|
|
7d012272a1 | ||
|
|
d4e6fe3546 | ||
|
|
170a72fd61 | ||
|
|
8a2a957d49 | ||
|
|
bafc45a309 | ||
|
|
828e87862f | ||
|
|
d84dd06b3f | ||
|
|
2032e23e8c | ||
|
|
0438bca7aa | ||
|
|
1030187965 | ||
|
|
03be184bd6 | ||
|
|
f8a5db5ab0 | ||
|
|
d83e4d3b2e | ||
|
|
ca448f0b0f | ||
|
|
12eb228aae | ||
|
|
07c4c00181 | ||
|
|
1250e94d56 | ||
|
|
f6436dc1a0 | ||
|
|
aa8206941c | ||
|
|
64dbdd855d | ||
|
|
954ad990e5 | ||
|
|
86303b3024 | ||
|
|
0c1d433f60 | ||
|
|
9ac537eb7c | ||
|
|
7195fe3325 | ||
|
|
fa0ba56bc9 | ||
|
|
21ed846479 | ||
|
|
65a1d21963 | ||
|
|
f84653d908 | ||
|
|
7c0fda0932 | ||
|
|
1e656b349d | ||
|
|
4933f34715 | ||
|
|
f9ccfca2a1 | ||
|
|
fd448c332b | ||
|
|
dd3ee082b2 | ||
|
|
1ce2f75627 | ||
|
|
be928f01a5 | ||
|
|
0b2c167c48 | ||
|
|
8082aad9b2 | ||
|
|
61bbef2f4e | ||
|
|
140afcfb7d | ||
|
|
1f3560229d | ||
|
|
84c93dd20e | ||
|
|
b5a6e7bbb0 | ||
|
|
810de3b474 | ||
|
|
3b295eb002 | ||
|
|
cbfa0f4fb8 | ||
|
|
1d4be8052f | ||
|
|
b5b76d5691 | ||
|
|
c2bbcfe560 | ||
|
|
d9bfb27282 | ||
|
|
d24a880003 | ||
|
|
c39a693274 | ||
|
|
4cc6be8532 | ||
|
|
3e35db1514 | ||
|
|
f6c4002b35 | ||
|
|
c5efbf71c0 | ||
|
|
62cb625f1b | ||
|
|
d68627f3a8 | ||
|
|
66f9a5f508 | ||
|
|
0ac9521c94 | ||
|
|
2f58281a20 | ||
|
|
8ecf9cb9b8 | ||
|
|
32f8abc362 | ||
|
|
150a68c940 | ||
|
|
b90b5898e4 | ||
|
|
cdfe90a6ca | ||
|
|
bf195531b3 | ||
|
|
5a6052119f | ||
|
|
8f7876b1d1 | ||
|
|
87f95d7c02 | ||
|
|
a178a15950 | ||
|
|
030d4a7e2c | ||
|
|
1d7257b613 | ||
|
|
b888922d62 | ||
|
|
82a5bffa7d | ||
|
|
6076eddf9c | ||
|
|
4539e54d8b | ||
|
|
4ba5826ba6 | ||
|
|
c3c08d252c | ||
|
|
4c7c64cd66 | ||
|
|
e3ffd4c2b1 | ||
|
|
9d9e14941e | ||
|
|
23e1bffd7a | ||
|
|
6dbca44030 | ||
|
|
5d8c07b3f2 | ||
|
|
bc8b79da53 | ||
|
|
636b368dd0 | ||
|
|
153e2c406c | ||
|
|
99644bed66 | ||
|
|
18327f02a8 | ||
|
|
4d7f2af576 | ||
|
|
a284f55473 | ||
|
|
36e9a43109 | ||
|
|
4a6cd8f878 | ||
|
|
baa3ac5853 | ||
|
|
13d1de5122 | ||
|
|
82173212ee | ||
|
|
7573c41657 | ||
|
|
ec4223d96a | ||
|
|
e6076e2c95 | ||
|
|
61337d5f7b | ||
|
|
0020ad8ac7 | ||
|
|
75267305f1 | ||
|
|
deca72b814 | ||
|
|
cbfcdcc4c2 | ||
|
|
f7c36e31e5 | ||
|
|
53cbd9acbf | ||
|
|
6c7004423d | ||
|
|
f6d1f6fdf6 | ||
|
|
0d9976ae9f | ||
|
|
2bb759206f | ||
|
|
4033ccc08d | ||
|
|
59830eda3f | ||
|
|
371ac29c9f | ||
|
|
ee46e92dd2 | ||
|
|
b0fc01eb82 | ||
|
|
8f19ca2039 | ||
|
|
3512a86b44 | ||
|
|
d40007667c | ||
|
|
c06bc3ead8 | ||
|
|
04b478f177 | ||
|
|
2d79ae7831 | ||
|
|
b52a516521 | ||
|
|
9939089dea | ||
|
|
7ce17fe655 | ||
|
|
2cf649db2e | ||
|
|
9392742cc4 | ||
|
|
fd62815e73 | ||
|
|
ee09d50403 | ||
|
|
a3fce7ce8d | ||
|
|
dcb7cae67c | ||
|
|
6f4091eb8c | ||
|
|
73e5de6354 | ||
|
|
d7174ec0ab | ||
|
|
cac387bc1e | ||
|
|
5c55d94007 | ||
|
|
1561067ee4 | ||
|
|
b654c02f55 | ||
|
|
b5179d7025 | ||
|
|
0323892f71 | ||
|
|
407eefe63a | ||
|
|
f1222a09a6 | ||
|
|
bfca7d68ba | ||
|
|
46646a49a8 | ||
|
|
f9fb0ff546 | ||
|
|
6b1f8de38a | ||
|
|
bd535a120b | ||
|
|
a0f8161fe7 | ||
|
|
59bedc2074 | ||
|
|
607fb6bf7f | ||
|
|
a587273c56 | ||
|
|
2f50f92eb3 | ||
|
|
961a173573 | ||
|
|
de07a562d1 | ||
|
|
14c9743ecf | ||
|
|
48a6203ae7 | ||
|
|
3b814d36d1 | ||
|
|
add4be444f | ||
|
|
002922fa4c | ||
|
|
8dfac43a75 | ||
|
|
777dbbe3f7 | ||
|
|
0e9c6932c4 | ||
|
|
3ffa1684ae | ||
|
|
31318a8ce5 | ||
|
|
d402047222 | ||
|
|
82855e9cf5 | ||
|
|
08bb0f7708 | ||
|
|
529ca8a4df | ||
|
|
bd783b901f | ||
|
|
20a9ca246d | ||
|
|
ed9be75384 | ||
|
|
7b6a1e5f59 | ||
|
|
0d39b17655 | ||
|
|
705f1039d9 | ||
|
|
cef426ee54 | ||
|
|
848b96a9a4 | ||
|
|
223a0e7b60 | ||
|
|
150c964b49 | ||
|
|
2384a85296 | ||
|
|
54f1e6d3d4 | ||
|
|
7a76a7a495 | ||
|
|
3061d7b17a | ||
|
|
ada6592af9 | ||
|
|
bf6fa2acd0 | ||
|
|
b89c6634f5 | ||
|
|
2e89eb5270 | ||
|
|
eecb40cf21 | ||
|
|
28950e6104 | ||
|
|
831bc7ecd1 | ||
|
|
281e76364a | ||
|
|
d61715a69e | ||
|
|
6d8fa97233 | ||
|
|
b80626c878 | ||
|
|
1c8b206a5d | ||
|
|
9fa06d5e3f | ||
|
|
5350645c86 | ||
|
|
60bbcab13f | ||
|
|
3ca26c812d | ||
|
|
ad6d8a53c8 | ||
|
|
4fa6691106 | ||
|
|
3bd3c2cee1 | ||
|
|
e929676268 | ||
|
|
9be69be836 | ||
|
|
296a0fb33d | ||
|
|
9df1183b94 | ||
|
|
cfb984e9bd | ||
|
|
aaca17c36d | ||
|
|
6ef5aa4fb2 | ||
|
|
aa5efff203 | ||
|
|
ede3e5ab83 | ||
|
|
3edf4c2854 | ||
|
|
a617a46e35 | ||
|
|
221e731e45 | ||
|
|
474d137c39 | ||
|
|
cb02a90b77 | ||
|
|
373ea53510 | ||
|
|
acebf7b52f | ||
|
|
3f297ffd9f | ||
|
|
eaf9e4cff8 | ||
|
|
43d9263589 | ||
|
|
5f19e53afb | ||
|
|
7aa4c9ec2f | ||
|
|
3ea083b8d4 | ||
|
|
e9aabcf2f8 | ||
|
|
c3cf4ef460 | ||
|
|
c9ff3994f1 | ||
|
|
f0186f4179 | ||
|
|
ae92cc208d | ||
|
|
14b7a72ba3 | ||
|
|
e4967b06bb | ||
|
|
773844a816 | ||
|
|
94717cb74c | ||
|
|
aeb6630868 | ||
|
|
15b8fe54a8 | ||
|
|
71917d6383 | ||
|
|
5a8315cf5b | ||
|
|
5a3d6ac67f | ||
|
|
244786ae34 | ||
|
|
461a4fafb1 |
@@ -1369,6 +1369,9 @@ void boot_device(char *devname)
|
||||
|
||||
void ctty(char *line)
|
||||
{
|
||||
if (line == nil) {
|
||||
serial_init(-1);
|
||||
} else
|
||||
if (between('0', line[0], '3') && line[1] == 0) {
|
||||
serial_init(line[0] - '0');
|
||||
} else {
|
||||
@@ -1793,6 +1796,7 @@ void execute(void)
|
||||
case R_HELP: help(); ok= 1; break;
|
||||
case R_EXIT: exit(0);
|
||||
case R_OFF: off(); ok= 1; break;
|
||||
case R_CTTY: ctty(nil); ok= 1; break;
|
||||
}
|
||||
|
||||
/* Command to check bootparams: */
|
||||
|
||||
@@ -854,6 +854,9 @@ restore_video: ! To restore the video mode on exit
|
||||
_serial_init:
|
||||
mov bx, sp
|
||||
mov dx, 2(bx) ! Line number
|
||||
mov line, #0
|
||||
test dx, dx ! Off if line number < 0
|
||||
js 0f
|
||||
push ds
|
||||
xor ax, ax
|
||||
mov ds, ax ! Vector and BIOS data segment
|
||||
|
||||
@@ -45,7 +45,7 @@ static int block_size = 0;
|
||||
/* Data about the different processes. */
|
||||
|
||||
#define PROCESS_MAX 16 /* Must match the space in kernel/mpx.x */
|
||||
#define KERNEL 0 /* The first process is the kernel. */
|
||||
#define KERNEL_IDX 0 /* The first process is the kernel. */
|
||||
#define FS 2 /* The third must be fs. */
|
||||
|
||||
struct process { /* Per-process memory adresses. */
|
||||
@@ -194,7 +194,7 @@ void patch_sizes(void)
|
||||
|
||||
/* Patch text and data sizes of the processes into kernel data space.
|
||||
*/
|
||||
doff= process[KERNEL].data + P_SIZ_OFF;
|
||||
doff= process[KERNEL_IDX].data + P_SIZ_OFF;
|
||||
|
||||
for (i= 0; i < n_procs; i++) {
|
||||
procp= &process[i];
|
||||
@@ -445,7 +445,7 @@ void exec_image(char *image)
|
||||
}
|
||||
|
||||
/* Get the click shift from the kernel text segment. */
|
||||
if (i == KERNEL) {
|
||||
if (i == KERNEL_IDX) {
|
||||
if (!get_clickshift(vsec, &hdr)) return;
|
||||
addr= align(addr, click_size);
|
||||
}
|
||||
@@ -504,7 +504,7 @@ void exec_image(char *image)
|
||||
if (!get_segment(&vsec, &a_data, &addr, limit)) return;
|
||||
|
||||
/* Make space for bss and stack unless... */
|
||||
if (i != KERNEL && (k_flags & K_CLAIM)) a_bss= a_stack= 0;
|
||||
if (i != KERNEL_IDX && (k_flags & K_CLAIM)) a_bss= a_stack= 0;
|
||||
|
||||
printf("%07lx %07lx %8ld %8ld %8ld",
|
||||
procp->cs, procp->ds,
|
||||
@@ -554,7 +554,7 @@ void exec_image(char *image)
|
||||
}
|
||||
|
||||
/* Check the kernel magic number. */
|
||||
if (get_word(process[KERNEL].data + MAGIC_OFF) != KERNEL_D_MAGIC) {
|
||||
if (get_word(process[KERNEL_IDX].data + MAGIC_OFF) != KERNEL_D_MAGIC) {
|
||||
printf("Kernel magic number is incorrect\n");
|
||||
errno= 0;
|
||||
return;
|
||||
@@ -592,8 +592,8 @@ void exec_image(char *image)
|
||||
(void) dev_close();
|
||||
|
||||
/* Minix. */
|
||||
minix(process[KERNEL].entry, process[KERNEL].cs,
|
||||
process[KERNEL].ds, params, sizeof(params), aout);
|
||||
minix(process[KERNEL_IDX].entry, process[KERNEL_IDX].cs,
|
||||
process[KERNEL_IDX].ds, params, sizeof(params), aout);
|
||||
|
||||
if (!(k_flags & K_BRET)) {
|
||||
extern u32_t reboot_code;
|
||||
|
||||
10
boot/rawfs.c
10
boot/rawfs.c
@@ -14,11 +14,11 @@
|
||||
#include <minix/config.h>
|
||||
#include <minix/const.h>
|
||||
#include <minix/type.h>
|
||||
#include <servers/fs/const.h>
|
||||
#include <servers/fs/type.h>
|
||||
#include <servers/fs/buf.h>
|
||||
#include <servers/fs/super.h>
|
||||
#include <servers/fs/inode.h>
|
||||
#include <servers/mfs/const.h>
|
||||
#include <servers/mfs/type.h>
|
||||
#include <servers/mfs/buf.h>
|
||||
#include <servers/mfs/super.h>
|
||||
#include <servers/mfs/inode.h>
|
||||
#include "rawfs.h"
|
||||
|
||||
void readblock(off_t blockno, char *buf, int);
|
||||
|
||||
@@ -2,8 +2,9 @@
|
||||
|
||||
MAKE = exec make -$(MAKEFLAGS)
|
||||
BZIP2=bzip2-1.0.3
|
||||
FLEX=flex-2.5.4
|
||||
|
||||
SMALLPROGRAMS=`arch` aal advent ash autil awk bc byacc cawf cron de dhcpd dis88 elle elvis ftp ftpd200 httpd ibm indent m4 make mdb mined patch pax ps reboot rlogind scripts sh simple syslogd talk talkd telnet telnetd urlget yap zmodem
|
||||
SMALLPROGRAMS=`arch` aal advent ash autil awk bc byacc cawf cron de dhcpd dis88 elle elvis ftp101 ftpd200 ibm indent m4 make mdb mined patch pax profile ps reboot rlogind scripts sh simple syslogd talk talkd telnet telnetd urlget yap zoneinfo
|
||||
|
||||
usage:
|
||||
@echo "Usage: make all # Compile all commands" >&2
|
||||
@@ -16,20 +17,28 @@ usage:
|
||||
@echo " "
|
||||
@echo "big compiles the commands the require large compiler sizes."
|
||||
@echo "small compiles the rest. all compiles all."
|
||||
@false
|
||||
|
||||
all: small big
|
||||
all: big small
|
||||
|
||||
install: biginstall smallinstall
|
||||
install: big biginstall small smallinstall
|
||||
|
||||
big:
|
||||
binsizes big
|
||||
cd zmodem && make
|
||||
cd $(BZIP2) && /bin/sh build build
|
||||
binsizes normal
|
||||
|
||||
biginstall: big
|
||||
binsizes big
|
||||
cd zmodem && make install
|
||||
cd $(BZIP2) && make install
|
||||
cd $(FLEX) && sh build
|
||||
binsizes normal
|
||||
|
||||
clean::
|
||||
cd $(BZIP2) && make clean
|
||||
cd zmodem && make clean
|
||||
if [ -f $(FLEX)/Makefile ]; then cd $(FLEX) && make distclean ; fi
|
||||
for p in $(SMALLPROGRAMS); do ( cd $$p && make clean ); done
|
||||
|
||||
small::
|
||||
|
||||
@@ -1,36 +1,56 @@
|
||||
# Makefile for ash.
|
||||
|
||||
SRCS= builtins.c cd.c dirent.c error.c eval.c exec.c expand.c input.c \
|
||||
SRCS= alias.c builtins.c cd.c error.c eval.c exec.c expand.c histedit.c \
|
||||
input.c \
|
||||
jobs.c mail.c main.c memalloc.c miscbltin.c mystring.c nodes.c \
|
||||
options.c parser.c redir.c show.c signames.c syntax.c trap.c \
|
||||
options.c parser.c redir.c setmode.c show.c signames.c syntax.c \
|
||||
trap.c \
|
||||
output.c var.c
|
||||
|
||||
OBJS= builtins.o cd.o dirent.o error.o eval.o exec.o expand.o input.o \
|
||||
OBJS= alias.o builtins.o cd.o error.o eval.o exec.o expand.o histedit.o \
|
||||
input.o \
|
||||
jobs.o mail.o main.o memalloc.o miscbltin.o mystring.o nodes.o \
|
||||
options.o parser.o redir.o show.o signames.o syntax.o trap.o \
|
||||
options.o parser.o redir.o setmode.o show.o signames.o syntax.o \
|
||||
trap.o \
|
||||
output.o var.o init.o \
|
||||
bltin/echo.o bltin/expr.o bltin/operators.o bltin/regexp.o
|
||||
bltin/echo.o bltin/expr.o bltin/operators.o bltin/regexp.o \
|
||||
arith.o arith_lex.o
|
||||
|
||||
#
|
||||
# Set READLINE in shell.h and add -ledit to LIBS if you want to use the
|
||||
# editline package by Simmule Turner and Rich Salz. (The big, bloated
|
||||
# and GPL contaminated FSF readline should work too.)
|
||||
#
|
||||
CPPFLAGS= -DSHELL -I. -D_MINIX -D_POSIX_SOURCE
|
||||
CFLAGS= -wo -i $(CPPFLAGS)
|
||||
LIBS= -ledit
|
||||
CC = exec cc
|
||||
LEX=flex
|
||||
YACC=/usr/bin/yacc
|
||||
.c.o:
|
||||
$(CC) $(CFLAGS) -c $< -o $@
|
||||
|
||||
# Enable this line to disable command line editing
|
||||
#EDIT=-DNO_HISTORY
|
||||
# Enable this line to use the editline library instead of libedit
|
||||
EDIT=-DEDITLINE
|
||||
EDITLIB=-ledit
|
||||
|
||||
FLEXLIB=-lfl
|
||||
|
||||
# Enable this line if your system does not have a <paths.h>
|
||||
NO_PATHS_H=-DNO_PATHS_H
|
||||
|
||||
# Enable this if you don't want job control
|
||||
NO_JOBS=-DJOBS=0
|
||||
MKB_NO_JOBS=-j
|
||||
|
||||
CPPFLAGS= -DSHELL -I. -D_MINIX $(EDIT) $(NO_PATHS_H) $(NO_JOBS)
|
||||
CFLAGS= $(OPT) $(CPPFLAGS)
|
||||
LIBS= $(EDITLIB) $(FLEXLIB)
|
||||
|
||||
CLEANFILES= $(OBJS) \
|
||||
builtins.c builtins.h init.c mkinit mknodes mksignames mksyntax \
|
||||
nodes.c nodes.h signames.c signames.h syntax.c syntax.h token.def \
|
||||
arith.c arith_y.h arith_lex.c builtins.c builtins.h init.c \
|
||||
mkinit mknodes mksignames mksyntax \
|
||||
nodes.c nodes.h signames.c signames.h syntax.c syntax.h token.h \
|
||||
bltin/operators.h bltin/operators.c
|
||||
|
||||
all: sh
|
||||
|
||||
sh: $(OBJS)
|
||||
$(CC) $(CFLAGS) -o sh $(OBJS) $(LIBS)
|
||||
install -S 100k sh
|
||||
$(CC) $(CFLAGS) -fnone -o sh $(OBJS) $(LIBS)
|
||||
install -S 136k sh
|
||||
|
||||
install: /usr/bin/ash /usr/bin/sh /bin/sh /bin/bigsh
|
||||
|
||||
@@ -44,7 +64,7 @@ install: /usr/bin/ash /usr/bin/sh /bin/sh /bin/bigsh
|
||||
install -lcs $? $@
|
||||
|
||||
/bin/bigsh: /usr/bin/ash
|
||||
install -S 1500000 -lcs $? $@
|
||||
install -S 6600k -lcs $? $@
|
||||
|
||||
clean:
|
||||
rm -f $(CLEANFILES) sh core
|
||||
@@ -54,11 +74,18 @@ parser.o: token.def
|
||||
token.def: mktokens
|
||||
sh mktokens
|
||||
|
||||
builtins.c builtins.h: builtins.table shell.h
|
||||
sh mkbuiltins shell.h builtins.table
|
||||
arith.c: arith.y
|
||||
$(YACC) -d $?
|
||||
mv y.tab.c $@
|
||||
mv y.tab.h arith_y.h
|
||||
|
||||
init.o: mkinit $(SRCS)
|
||||
./mkinit '$(CC) -c $(CFLAGS) init.c' $(SRCS)
|
||||
arith_lex.c: arith_lex.l
|
||||
|
||||
builtins.c builtins.h: builtins.def shell.h
|
||||
sh mkbuiltins $(MKB_NO_JOBS) . shell.h builtins.def
|
||||
|
||||
init.c: mkinit $(SRCS)
|
||||
./mkinit $(SRCS)
|
||||
|
||||
mkinit: mkinit.c
|
||||
$(CC) $(CFLAGS) mkinit.c -o $@
|
||||
@@ -81,20 +108,8 @@ syntax.c syntax.h: mksyntax
|
||||
mksyntax: mksyntax.c parser.h
|
||||
$(CC) $(CFLAGS) mksyntax.c -o $@
|
||||
|
||||
bltin/operators.h: bltin/mkexpr bltin/binary_op bltin/unary_op
|
||||
cd bltin && sh mkexpr
|
||||
|
||||
bltin/echo.o: bltin/echo.c
|
||||
cd bltin && $(CC) -I.. $(CFLAGS) -c echo.c
|
||||
|
||||
bltin/expr.o: bltin/expr.c
|
||||
cd bltin && $(CC) -I.. $(CFLAGS) -c expr.c
|
||||
|
||||
bltin/operators.o: bltin/operators.c
|
||||
cd bltin && $(CC) -I.. $(CFLAGS) -c operators.c
|
||||
|
||||
bltin/regexp.o: bltin/regexp.c
|
||||
cd bltin && $(CC) -I.. $(CFLAGS) -c regexp.c
|
||||
bltin/operators.h: bltin/mkexpr bltin/unary_op bltin/binary_op
|
||||
cd bltin && sh mkexpr unary_op binary_op
|
||||
|
||||
# Dependencies you say? This will have to do.
|
||||
$(OBJS): error.h eval.h exec.h expand.h init.h input.h \
|
||||
@@ -103,3 +118,6 @@ $(OBJS): error.h eval.h exec.h expand.h init.h input.h \
|
||||
builtins.h nodes.h signames.h syntax.h
|
||||
|
||||
bltin/expr.o bltin/operators.o: bltin/operators.h
|
||||
|
||||
#
|
||||
# $PchId: Makefile,v 1.4 2006/05/22 12:40:46 philip Exp $
|
||||
|
||||
@@ -1,4 +1,13 @@
|
||||
# @(#)TOUR 5.1 (Berkeley) 3/7/91
|
||||
# @(#)TOUR 8.1 (Berkeley) 5/31/93
|
||||
# $FreeBSD: src/bin/sh/TOUR,v 1.6 1999/08/27 23:15:07 peter Exp $
|
||||
|
||||
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
|
||||
|
||||
@@ -20,7 +29,7 @@ programs is:
|
||||
mknodes nodetypes nodes.h nodes.c
|
||||
mksignames - signames.h signames.c
|
||||
mksyntax - syntax.h syntax.c
|
||||
mktokens - token.def
|
||||
mktokens - token.h
|
||||
bltin/mkexpr unary_op binary_op operators.h operators.c
|
||||
|
||||
There are undoubtedly too many of these. Mkinit searches all the
|
||||
@@ -346,3 +355,6 @@ 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.
|
||||
|
||||
#
|
||||
# $PchId: TOUR,v 1.3 2006/03/31 11:33:46 philip Exp $
|
||||
|
||||
265
commands/ash/alias.c
Normal file
265
commands/ash/alias.c
Normal file
@@ -0,0 +1,265 @@
|
||||
/*-
|
||||
* 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.
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef lint
|
||||
#if 0
|
||||
static char sccsid[] = "@(#)alias.c 8.3 (Berkeley) 5/4/95";
|
||||
#endif
|
||||
#endif /* not lint */
|
||||
/*
|
||||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD: src/bin/sh/alias.c,v 1.18 2004/04/06 20:06:51 markm Exp $");
|
||||
*/
|
||||
|
||||
#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 "builtins.h"
|
||||
|
||||
#define ATABSIZE 39
|
||||
|
||||
STATIC 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 marks 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->flag = 0;
|
||||
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
|
||||
INCLUDE "alias.h"
|
||||
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);
|
||||
}
|
||||
|
||||
/*
|
||||
* 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);
|
||||
out1qstr(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);
|
||||
out1qstr(ap->val);
|
||||
out1c('\n');
|
||||
}
|
||||
else {
|
||||
*v++ = '\0';
|
||||
setalias(n, v);
|
||||
}
|
||||
}
|
||||
|
||||
return (ret);
|
||||
}
|
||||
|
||||
int
|
||||
unaliascmd(int argc __unused, char **argv __unused)
|
||||
{
|
||||
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];
|
||||
}
|
||||
|
||||
/*
|
||||
* $PchId: alias.c,v 1.5 2006/05/22 12:41:12 philip Exp $
|
||||
*/
|
||||
52
commands/ash/alias.h
Normal file
52
commands/ash/alias.h
Normal file
@@ -0,0 +1,52 @@
|
||||
/*-
|
||||
* 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.
|
||||
* 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.
|
||||
*
|
||||
* @(#)alias.h 8.2 (Berkeley) 5/4/95
|
||||
* $FreeBSD: src/bin/sh/alias.h,v 1.8 2004/04/06 20:06:51 markm Exp $
|
||||
*/
|
||||
|
||||
#define ALIASINUSE 1
|
||||
|
||||
struct alias {
|
||||
struct alias *next;
|
||||
char *name;
|
||||
char *val;
|
||||
int flag;
|
||||
};
|
||||
|
||||
struct alias *lookupalias(char *, int);
|
||||
int aliascmd(int, char **);
|
||||
int unaliascmd(int, char **);
|
||||
void rmaliases(void);
|
||||
|
||||
/*
|
||||
* $PchId: alias.h,v 1.4 2006/03/31 11:30:54 philip Exp $
|
||||
*/
|
||||
39
commands/ash/arith.h
Normal file
39
commands/ash/arith.h
Normal file
@@ -0,0 +1,39 @@
|
||||
/*-
|
||||
* 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.
|
||||
* 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.
|
||||
*
|
||||
* @(#)arith.h 1.1 (Berkeley) 5/4/95
|
||||
* $FreeBSD: src/bin/sh/arith.h,v 1.9 2004/04/06 20:06:51 markm Exp $
|
||||
*/
|
||||
|
||||
int arith(char *);
|
||||
int arith_assign(char *, arith_t);
|
||||
int expcmd(int, char **);
|
||||
|
||||
/*
|
||||
* $PchId: arith.h,v 1.3 2006/03/31 11:25:25 philip Exp $
|
||||
*/
|
||||
366
commands/ash/arith.y
Normal file
366
commands/ash/arith.y
Normal file
@@ -0,0 +1,366 @@
|
||||
%{
|
||||
/*-
|
||||
* 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.
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#if 0
|
||||
#ifndef lint
|
||||
static char sccsid[] = "@(#)arith.y 8.3 (Berkeley) 5/4/95";
|
||||
#endif
|
||||
#endif /* not lint */
|
||||
/*
|
||||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD: src/bin/sh/arith.y,v 1.19 2004/05/24 10:11:31 stefanf Exp $");
|
||||
*/
|
||||
|
||||
#include <limits.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "shell.h"
|
||||
#include "arith.h"
|
||||
#include "arith_lex.h"
|
||||
#include "var.h"
|
||||
%}
|
||||
%union {
|
||||
arith_t l_value;
|
||||
char* s_value;
|
||||
}
|
||||
%token <l_value> ARITH_NUM ARITH_LPAREN ARITH_RPAREN
|
||||
%token <s_value> ARITH_VAR
|
||||
|
||||
%type <l_value> expr
|
||||
%right ARITH_ASSIGN
|
||||
%right ARITH_ADDASSIGN ARITH_SUBASSIGN
|
||||
%right ARITH_MULASSIGN ARITH_DIVASSIGN ARITH_REMASSIGN
|
||||
%right ARITH_RSHASSIGN ARITH_LSHASSIGN
|
||||
%right ARITH_BANDASSIGN ARITH_BXORASSIGN ARITH_BORASSIGN
|
||||
%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 |
|
||||
ARITH_VAR
|
||||
{
|
||||
char *p;
|
||||
arith_t arith_val;
|
||||
char *str_val;
|
||||
|
||||
if (lookupvar($1) == NULL)
|
||||
setvarsafe($1, "0", 0);
|
||||
str_val = lookupvar($1);
|
||||
arith_val = strtoarith_t(str_val, &p, 0);
|
||||
/*
|
||||
* Conversion is successful only in case
|
||||
* we've converted _all_ characters.
|
||||
*/
|
||||
if (*p != '\0')
|
||||
yyerror("variable conversion error");
|
||||
$$ = arith_val;
|
||||
} |
|
||||
ARITH_VAR ARITH_ASSIGN expr
|
||||
{
|
||||
if (arith_assign($1, $3) != 0)
|
||||
yyerror("variable assignment error");
|
||||
$$ = $3;
|
||||
} |
|
||||
ARITH_VAR ARITH_ADDASSIGN expr
|
||||
{
|
||||
arith_t value;
|
||||
|
||||
value = atoarith_t(lookupvar($1)) + $3;
|
||||
if (arith_assign($1, value) != 0)
|
||||
yyerror("variable assignment error");
|
||||
$$ = value;
|
||||
} |
|
||||
ARITH_VAR ARITH_SUBASSIGN expr
|
||||
{
|
||||
arith_t value;
|
||||
|
||||
value = atoarith_t(lookupvar($1)) - $3;
|
||||
if (arith_assign($1, value) != 0)
|
||||
yyerror("variable assignment error");
|
||||
$$ = value;
|
||||
} |
|
||||
ARITH_VAR ARITH_MULASSIGN expr
|
||||
{
|
||||
arith_t value;
|
||||
|
||||
value = atoarith_t(lookupvar($1)) * $3;
|
||||
if (arith_assign($1, value) != 0)
|
||||
yyerror("variable assignment error");
|
||||
$$ = value;
|
||||
} |
|
||||
ARITH_VAR ARITH_DIVASSIGN expr
|
||||
{
|
||||
arith_t value;
|
||||
|
||||
if ($3 == 0)
|
||||
yyerror("division by zero");
|
||||
|
||||
value = atoarith_t(lookupvar($1)) / $3;
|
||||
if (arith_assign($1, value) != 0)
|
||||
yyerror("variable assignment error");
|
||||
$$ = value;
|
||||
} |
|
||||
ARITH_VAR ARITH_REMASSIGN expr
|
||||
{
|
||||
arith_t value;
|
||||
|
||||
if ($3 == 0)
|
||||
yyerror("division by zero");
|
||||
|
||||
value = atoarith_t(lookupvar($1)) % $3;
|
||||
if (arith_assign($1, value) != 0)
|
||||
yyerror("variable assignment error");
|
||||
$$ = value;
|
||||
} |
|
||||
ARITH_VAR ARITH_RSHASSIGN expr
|
||||
{
|
||||
arith_t value;
|
||||
|
||||
value = atoarith_t(lookupvar($1)) >> $3;
|
||||
if (arith_assign($1, value) != 0)
|
||||
yyerror("variable assignment error");
|
||||
$$ = value;
|
||||
} |
|
||||
ARITH_VAR ARITH_LSHASSIGN expr
|
||||
{
|
||||
arith_t value;
|
||||
|
||||
value = atoarith_t(lookupvar($1)) << $3;
|
||||
if (arith_assign($1, value) != 0)
|
||||
yyerror("variable assignment error");
|
||||
$$ = value;
|
||||
} |
|
||||
ARITH_VAR ARITH_BANDASSIGN expr
|
||||
{
|
||||
arith_t value;
|
||||
|
||||
value = atoarith_t(lookupvar($1)) & $3;
|
||||
if (arith_assign($1, value) != 0)
|
||||
yyerror("variable assignment error");
|
||||
$$ = value;
|
||||
} |
|
||||
ARITH_VAR ARITH_BXORASSIGN expr
|
||||
{
|
||||
arith_t value;
|
||||
|
||||
value = atoarith_t(lookupvar($1)) ^ $3;
|
||||
if (arith_assign($1, value) != 0)
|
||||
yyerror("variable assignment error");
|
||||
$$ = value;
|
||||
} |
|
||||
ARITH_VAR ARITH_BORASSIGN expr
|
||||
{
|
||||
arith_t value;
|
||||
|
||||
value = atoarith_t(lookupvar($1)) | $3;
|
||||
if (arith_assign($1, value) != 0)
|
||||
yyerror("variable assignment error");
|
||||
$$ = value;
|
||||
} ;
|
||||
%%
|
||||
#include "error.h"
|
||||
#include "output.h"
|
||||
#include "memalloc.h"
|
||||
#include "builtins.h"
|
||||
|
||||
#define lstrlen(var) (3 + (2 + CHAR_BIT * sizeof((var))) / 3)
|
||||
|
||||
char *arith_buf, *arith_startbuf;
|
||||
|
||||
int yylex(void);
|
||||
int yyparse(void);
|
||||
|
||||
int
|
||||
arith_assign(char *name, arith_t value)
|
||||
{
|
||||
char *str;
|
||||
int ret;
|
||||
|
||||
str = (char *)ckmalloc(lstrlen(value));
|
||||
sprintf(str, ARITH_FORMAT_STR, value);
|
||||
ret = setvarsafe(name, str, 0);
|
||||
free(str);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int
|
||||
arith(char *s)
|
||||
{
|
||||
long result;
|
||||
|
||||
arith_buf = arith_startbuf = s;
|
||||
|
||||
INTOFF;
|
||||
result = yyparse();
|
||||
arith_lex_reset(); /* Reprime lex. */
|
||||
INTON;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void
|
||||
yyerror(char *s)
|
||||
{
|
||||
|
||||
yyerrok;
|
||||
yyclearin;
|
||||
arith_lex_reset(); /* Reprime lex. */
|
||||
error("arithmetic expression: %s: \"%s\"", s, arith_startbuf);
|
||||
}
|
||||
|
||||
/*
|
||||
* The exp(1) builtin.
|
||||
*/
|
||||
int
|
||||
expcmd(int argc, char **argv)
|
||||
{
|
||||
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(int argc, char *argv[])
|
||||
{
|
||||
printf("%d\n", exp(argv[1]));
|
||||
}
|
||||
|
||||
error(char *s)
|
||||
{
|
||||
fprintf(stderr, "exp: %s\n", s);
|
||||
exit(1);
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* $PchId: arith.y,v 1.6 2006/05/22 12:41:47 philip Exp $
|
||||
*/
|
||||
12
commands/ash/arith_lex.h
Normal file
12
commands/ash/arith_lex.h
Normal file
@@ -0,0 +1,12 @@
|
||||
/*
|
||||
arith_lex.h
|
||||
|
||||
Created: July 1995 by Philip Homburg <philip@cs.vu.nl>
|
||||
*/
|
||||
|
||||
int yylex(void);
|
||||
void arith_lex_reset(void);
|
||||
|
||||
/*
|
||||
* $PchId: arith_lex.h,v 1.1 2001/05/18 19:57:55 philip Exp $
|
||||
*/
|
||||
138
commands/ash/arith_lex.l
Normal file
138
commands/ash/arith_lex.l
Normal file
@@ -0,0 +1,138 @@
|
||||
%{
|
||||
/*-
|
||||
* 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.
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#if 0
|
||||
#ifndef lint
|
||||
static char sccsid[] = "@(#)arith_lex.l 8.3 (Berkeley) 5/4/95";
|
||||
#endif
|
||||
#endif /* not lint */
|
||||
/*
|
||||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD: src/bin/sh/arith_lex.l,v 1.22 2004/04/06 20:06:51 markm Exp $");
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "shell.h"
|
||||
#include "arith_lex.h"
|
||||
#include "arith_y.h"
|
||||
#include "error.h"
|
||||
#include "memalloc.h"
|
||||
#include "var.h"
|
||||
|
||||
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
|
||||
%}
|
||||
|
||||
%%
|
||||
[ \t\n] { ; }
|
||||
|
||||
0x[a-fA-F0-9]+ {
|
||||
yylval.l_value = strtoarith_t(yytext, NULL, 16);
|
||||
return ARITH_NUM;
|
||||
}
|
||||
|
||||
0[0-7]+ {
|
||||
yylval.l_value = strtoarith_t(yytext, NULL, 8);
|
||||
return ARITH_NUM;
|
||||
}
|
||||
|
||||
[0-9]+ {
|
||||
yylval.l_value = strtoarith_t(yytext, NULL, 10);
|
||||
return ARITH_NUM;
|
||||
}
|
||||
|
||||
[A-Za-z][A-Za-z0-9_]* {
|
||||
/*
|
||||
* If variable doesn't exist, we should initialize
|
||||
* it to zero.
|
||||
*/
|
||||
char *temp;
|
||||
if (lookupvar(yytext) == NULL)
|
||||
setvarsafe(yytext, "0", 0);
|
||||
temp = (char *)ckmalloc(strlen(yytext) + 1);
|
||||
yylval.s_value = strcpy(temp, yytext);
|
||||
|
||||
return ARITH_VAR;
|
||||
}
|
||||
|
||||
"(" { 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; }
|
||||
"=" { return ARITH_ASSIGN; }
|
||||
"+=" { return ARITH_ADDASSIGN; }
|
||||
"-=" { return ARITH_SUBASSIGN; }
|
||||
"*=" { return ARITH_MULASSIGN; }
|
||||
"/=" { return ARITH_DIVASSIGN; }
|
||||
"%=" { return ARITH_REMASSIGN; }
|
||||
">>=" { return ARITH_RSHASSIGN; }
|
||||
"<<=" { return ARITH_LSHASSIGN; }
|
||||
"&=" { return ARITH_BANDASSIGN; }
|
||||
"^=" { return ARITH_BXORASSIGN; }
|
||||
"|=" { return ARITH_BORASSIGN; }
|
||||
. {
|
||||
error("arith: syntax error: \"%s\"\n", arith_startbuf);
|
||||
}
|
||||
%%
|
||||
|
||||
void
|
||||
arith_lex_reset(void)
|
||||
{
|
||||
YY_NEW_FILE;
|
||||
}
|
||||
|
||||
/*
|
||||
* $PchId: arith_lex.l,v 1.5 2006/04/10 14:35:29 philip Exp $
|
||||
*/
|
||||
@@ -1,26 +1,78 @@
|
||||
/*-
|
||||
* 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.
|
||||
* 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.
|
||||
*
|
||||
* @(#)bltin.h 8.2 (Berkeley) 5/4/95
|
||||
* $FreeBSD: src/bin/sh/bltin/bltin.h,v 1.13 2004/04/06 20:06:53 markm Exp $
|
||||
*/
|
||||
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
* Copyright (C) 1989 by Kenneth Almquist. All rights reserved.
|
||||
* This file is part of ash, which is distributed under the terms specified
|
||||
* by the Ash General Public License. See the file named LICENSE.
|
||||
*/
|
||||
|
||||
#include "../shell.h"
|
||||
#include "../mystring.h"
|
||||
#ifdef SHELL
|
||||
#include "builtins.h"
|
||||
#include "../output.h"
|
||||
#undef stdout
|
||||
#define stdout out1
|
||||
#undef stderr
|
||||
#define stderr out2
|
||||
#define printf out1fmt
|
||||
#undef putc
|
||||
#define putc(c, file) outc(c, file)
|
||||
#undef putchar
|
||||
#define putchar(c) out1c(c)
|
||||
#define fprintf outfmt
|
||||
#define fputs outstr
|
||||
#define fflush flushout
|
||||
#define INITARGS(argv)
|
||||
#define warnx1(a, b, c) { \
|
||||
char buf[64]; \
|
||||
(void)snprintf(buf, sizeof(buf), a); \
|
||||
error("%s", buf); \
|
||||
}
|
||||
#define warnx2(a, b, c) { \
|
||||
char buf[64]; \
|
||||
(void)snprintf(buf, sizeof(buf), a, b); \
|
||||
error("%s", buf); \
|
||||
}
|
||||
#define warnx3(a, b, c) { \
|
||||
char buf[64]; \
|
||||
(void)snprintf(buf, sizeof(buf), a, b, c); \
|
||||
error("%s", buf); \
|
||||
}
|
||||
|
||||
#else
|
||||
#undef NULL
|
||||
#include <stdio.h>
|
||||
@@ -28,13 +80,12 @@
|
||||
#define INITARGS(argv) if ((commandname = argv[0]) == NULL) {fputs("Argc is zero\n", stderr); exit(2);} else
|
||||
#endif
|
||||
|
||||
#ifdef __STDC__
|
||||
pointer stalloc(int);
|
||||
void error(char *, ...);
|
||||
#else
|
||||
pointer stalloc();
|
||||
void error();
|
||||
#endif
|
||||
void error(const char *, ...);
|
||||
|
||||
|
||||
extern char *commandname;
|
||||
|
||||
/*
|
||||
* $PchId: bltin.h,v 1.4 2006/03/29 11:39:00 philip Exp $
|
||||
*/
|
||||
|
||||
@@ -1,74 +1,126 @@
|
||||
/*
|
||||
* Echo command.
|
||||
/*-
|
||||
* Copyright (c) 1991, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* Copyright (C) 1989 by Kenneth Almquist. All rights reserved.
|
||||
* This file is part of ash, which is distributed under the terms specified
|
||||
* by the Ash General Public License. See the file named LICENSE.
|
||||
* 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.
|
||||
* 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.
|
||||
*
|
||||
* @(#)echo.c 8.2 (Berkeley) 5/4/95
|
||||
*/
|
||||
|
||||
#define main echocmd
|
||||
/*
|
||||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD: src/bin/sh/bltin/echo.c,v 1.14 2004/04/06 20:06:53 markm Exp $");
|
||||
*/
|
||||
|
||||
/*
|
||||
* Echo command.
|
||||
*/
|
||||
|
||||
#ifdef __minix
|
||||
#define MINIX
|
||||
#endif
|
||||
|
||||
#include "bltin.h"
|
||||
|
||||
#ifndef MINIX
|
||||
/* #define eflag 1 */
|
||||
#else
|
||||
#undef eflag
|
||||
|
||||
|
||||
main(argc, argv) char **argv; {
|
||||
register char **ap;
|
||||
register char *p;
|
||||
register char c;
|
||||
int count;
|
||||
int nflag = 0;
|
||||
#ifndef eflag
|
||||
int eflag = 0;
|
||||
#endif
|
||||
|
||||
ap = argv;
|
||||
if (argc)
|
||||
ap++;
|
||||
if ((p = *ap) != NULL) {
|
||||
if (equal(p, "--")) {
|
||||
ap++;
|
||||
}
|
||||
if (equal(p, "-n")) {
|
||||
nflag++;
|
||||
ap++;
|
||||
} else if (equal(p, "-e")) {
|
||||
int
|
||||
echocmd(argc, argv)
|
||||
int argc;
|
||||
char **argv;
|
||||
{
|
||||
char **ap;
|
||||
char *p;
|
||||
char c;
|
||||
int count;
|
||||
int nflag = 0;
|
||||
#ifndef eflag
|
||||
eflag++;
|
||||
int eflag = 0;
|
||||
#endif
|
||||
ap++;
|
||||
}
|
||||
}
|
||||
while ((p = *ap++) != NULL) {
|
||||
while ((c = *p++) != '\0') {
|
||||
if (c == '\\' && eflag) {
|
||||
switch (*p++) {
|
||||
case 'b': c = '\b'; break;
|
||||
case 'c': return 0; /* exit */
|
||||
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:
|
||||
p--;
|
||||
break;
|
||||
|
||||
ap = argv;
|
||||
if (argc)
|
||||
ap++;
|
||||
if ((p = *ap) != NULL) {
|
||||
#ifdef MINIX
|
||||
if (equal(p, "--")) {
|
||||
ap++;
|
||||
}
|
||||
#endif
|
||||
if (equal(p, "-n")) {
|
||||
nflag++;
|
||||
ap++;
|
||||
} else if (equal(p, "-e")) {
|
||||
#ifndef eflag
|
||||
eflag++;
|
||||
#endif
|
||||
ap++;
|
||||
}
|
||||
}
|
||||
while ((p = *ap++) != NULL) {
|
||||
while ((c = *p++) != '\0') {
|
||||
if (c == '\\' && eflag) {
|
||||
switch (*p++) {
|
||||
case 'a': c = '\a'; break;
|
||||
case 'b': c = '\b'; break;
|
||||
case 'c': return 0; /* exit */
|
||||
case 'e': c = '\033'; break;
|
||||
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:
|
||||
p--;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
putchar(c);
|
||||
}
|
||||
if (*ap)
|
||||
putchar(' ');
|
||||
}
|
||||
if (! nflag)
|
||||
putchar('\n');
|
||||
return 0;
|
||||
putchar(c);
|
||||
}
|
||||
if (*ap)
|
||||
putchar(' ');
|
||||
}
|
||||
if (! nflag)
|
||||
putchar('\n');
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* $PchId: echo.c,v 1.5 2006/05/23 12:05:56 philip Exp $
|
||||
*/
|
||||
|
||||
@@ -7,17 +7,14 @@
|
||||
*/
|
||||
|
||||
|
||||
#define main exprcmd
|
||||
|
||||
#include "bltin.h"
|
||||
#include "operators.h"
|
||||
#include <regex.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#ifndef S_ISLNK
|
||||
#define lstat stat
|
||||
#define S_ISLNK(mode) (0)
|
||||
#endif
|
||||
|
||||
#define STACKSIZE 12
|
||||
#define NESTINCR 16
|
||||
@@ -50,7 +47,6 @@ struct operator {
|
||||
|
||||
|
||||
struct filestat {
|
||||
int op; /* OP_FILE or OP_LFILE */
|
||||
char *name; /* name of file */
|
||||
int rcode; /* return code from stat */
|
||||
struct stat stat; /* status info on file */
|
||||
@@ -63,24 +59,18 @@ extern short number_parens; /* number of \( \) pairs */
|
||||
|
||||
|
||||
#ifdef __STDC__
|
||||
int expr_is_false(struct value *);
|
||||
void expr_operator(int, struct value *, struct filestat *);
|
||||
int lookup_op(char *, char *const*);
|
||||
char *re_compile(char *); /* defined in regexp.c */
|
||||
int re_match(char *, char *); /* defined in regexp.c */
|
||||
long atol(const char *);
|
||||
static int expr_is_false(struct value *);
|
||||
static void expr_operator(int, struct value *, struct filestat *);
|
||||
static int lookup_op(char *, char *const*);
|
||||
#else
|
||||
int expr_is_false();
|
||||
void expr_operator();
|
||||
int lookup_op();
|
||||
char *re_compile(); /* defined in regexp.c */
|
||||
int re_match(); /* defined in regexp.c */
|
||||
long atol();
|
||||
static int expr_is_false();
|
||||
static void expr_operator();
|
||||
static int lookup_op();
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
main(argc, argv) char **argv; {
|
||||
exprcmd(argc, argv) char **argv; {
|
||||
char **ap;
|
||||
char *opname;
|
||||
char c;
|
||||
@@ -146,6 +136,13 @@ overflow: error("Expression too complex");
|
||||
continue;
|
||||
|
||||
} else {
|
||||
if (opname[0] == '\'') {
|
||||
for (p = opname ; *++p != '\0' ; );
|
||||
if (--p > opname && *p == '\'') {
|
||||
*p = '\0';
|
||||
opname++;
|
||||
}
|
||||
}
|
||||
valsp->type = STRING;
|
||||
valsp->u.string = opname;
|
||||
valsp++;
|
||||
@@ -193,19 +190,11 @@ overflow: error("Expression too complex");
|
||||
valsp->u.string = "";
|
||||
}
|
||||
valsp->type = STRING;
|
||||
if (c >= OP_FILE
|
||||
&& (fs.op != c
|
||||
|| fs.name == NULL
|
||||
if (c == OP_FILE
|
||||
&& (fs.name == NULL
|
||||
|| ! equal(fs.name, valsp->u.string))) {
|
||||
fs.op = c;
|
||||
fs.name = valsp->u.string;
|
||||
if (c == OP_FILE) {
|
||||
fs.rcode = stat(valsp->u.string,
|
||||
&fs.stat);
|
||||
} else {
|
||||
fs.rcode = lstat(valsp->u.string,
|
||||
&fs.stat);
|
||||
}
|
||||
fs.rcode = stat(valsp->u.string, &fs.stat);
|
||||
}
|
||||
}
|
||||
if (binary < FIRST_BINARY_OP)
|
||||
@@ -250,7 +239,7 @@ done:
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
static int
|
||||
expr_is_false(val)
|
||||
struct value *val;
|
||||
{
|
||||
@@ -274,14 +263,16 @@ expr_is_false(val)
|
||||
* to stat, to avoid repeated stat calls on the same file.
|
||||
*/
|
||||
|
||||
void
|
||||
static void
|
||||
expr_operator(op, sp, fs)
|
||||
int op;
|
||||
struct value *sp;
|
||||
struct filestat *fs;
|
||||
{
|
||||
int i;
|
||||
int i, r;
|
||||
struct stat st1, st2;
|
||||
regex_t pat;
|
||||
regmatch_t rm[2];
|
||||
|
||||
switch (op) {
|
||||
case NOT:
|
||||
@@ -343,16 +334,16 @@ filebit:
|
||||
if (fs->stat.st_mode & i && fs->rcode >= 0)
|
||||
goto true;
|
||||
goto false;
|
||||
case ISSLINK:
|
||||
if (lstat(fs->name, &st1) == -1)
|
||||
goto false;
|
||||
if (S_ISLNK(st1.st_mode))
|
||||
goto true;
|
||||
goto false;
|
||||
case ISSIZE:
|
||||
sp->u.num = fs->rcode >= 0? fs->stat.st_size : 0L;
|
||||
sp->type = INTEGER;
|
||||
break;
|
||||
case ISLINK1:
|
||||
case ISLINK2:
|
||||
if (S_ISLNK(fs->stat.st_mode) && fs->rcode >= 0)
|
||||
goto true;
|
||||
fs->op = OP_FILE; /* not a symlink, so expect a -d or so next */
|
||||
goto false;
|
||||
case NEWER:
|
||||
if (stat(sp->u.string, &st1) != 0) {
|
||||
sp->u.num = 0;
|
||||
@@ -439,19 +430,21 @@ filebit:
|
||||
break;
|
||||
case MATCHPAT:
|
||||
{
|
||||
char *pat;
|
||||
|
||||
pat = re_compile((sp + 1)->u.string);
|
||||
if (re_match(pat, sp->u.string)) {
|
||||
if (number_parens > 0) {
|
||||
sp->u.string = match_begin[1];
|
||||
sp->u.string[match_length[1]] = '\0';
|
||||
r = regcomp(&pat, (sp + 1)->u.string, 0);
|
||||
if (r)
|
||||
error("Bad regular expression");
|
||||
if (regexec(&pat, sp->u.string, 2, rm, 0) == 0 &&
|
||||
rm[0].rm_so == 0)
|
||||
{
|
||||
if (pat.re_nsub > 0) {
|
||||
sp->u.string[rm[1].rm_eo] = '\0';
|
||||
sp->u.string = sp->u.string+rm[1].rm_so;
|
||||
} else {
|
||||
sp->u.num = match_length[0];
|
||||
sp->u.num = rm[0].rm_eo;
|
||||
sp->type = INTEGER;
|
||||
}
|
||||
} else {
|
||||
if (number_parens > 0) {
|
||||
if (pat.re_nsub > 0) {
|
||||
sp->u.string[0] = '\0';
|
||||
} else {
|
||||
sp->u.num = 0;
|
||||
@@ -464,7 +457,7 @@ filebit:
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
static int
|
||||
lookup_op(name, table)
|
||||
char *name;
|
||||
char *const*table;
|
||||
|
||||
@@ -5,21 +5,28 @@
|
||||
|
||||
# All calls to awk removed, because Minix bawk is deficient. (kjb)
|
||||
|
||||
if [ $# -ne 2 ]
|
||||
then
|
||||
echo "Usage: $0 <unary_op> <binary_op>" >&2
|
||||
exit 1
|
||||
fi
|
||||
unary_op="$1"
|
||||
binary_op="$2"
|
||||
|
||||
exec > operators.h
|
||||
i=0
|
||||
sed -e '/^[^#]/!d' unary_op binary_op | while read line
|
||||
sed -e '/^[^#]/!d' "$unary_op" "$binary_op" | while read line
|
||||
do
|
||||
set -$- $line
|
||||
echo "#define $1 $i"
|
||||
i=`expr $i + 1`
|
||||
done
|
||||
echo
|
||||
echo "#define FIRST_BINARY_OP" `sed -e '/^[^#]/!d' unary_op | wc -l`
|
||||
echo "#define FIRST_BINARY_OP" `sed -e '/^[^#]/!d' "$unary_op" | wc -l`
|
||||
echo '
|
||||
#define OP_INT 1 /* arguments to operator are integer */
|
||||
#define OP_STRING 2 /* arguments to operator are string */
|
||||
#define OP_FILE 3 /* argument is a file name */
|
||||
#define OP_LFILE 4 /* argument is a file name of a symlink? */
|
||||
|
||||
extern char *const unary_op[];
|
||||
extern char *const binary_op[];
|
||||
@@ -31,14 +38,15 @@ echo '/*
|
||||
* Operators used in the expr/test command.
|
||||
*/
|
||||
|
||||
#include "../shell.h"
|
||||
#include <stddef.h>
|
||||
#include "shell.h"
|
||||
#include "operators.h"
|
||||
|
||||
char *const unary_op[] = {'
|
||||
sed -e '/^[^#]/!d
|
||||
s/[ ][ ]*/ /g
|
||||
s/^[^ ][^ ]* \([^ ][^ ]*\).*/ "\1",/
|
||||
' unary_op
|
||||
' "$unary_op"
|
||||
echo ' NULL
|
||||
};
|
||||
|
||||
@@ -46,7 +54,7 @@ char *const binary_op[] = {'
|
||||
sed -e '/^[^#]/!d
|
||||
s/[ ][ ]*/ /g
|
||||
s/^[^ ][^ ]* \([^ ][^ ]*\).*/ "\1",/
|
||||
' binary_op
|
||||
' "$binary_op"
|
||||
echo ' NULL
|
||||
};
|
||||
|
||||
@@ -54,7 +62,7 @@ const char op_priority[] = {'
|
||||
sed -e '/^[^#]/!d
|
||||
s/[ ][ ]*/ /g
|
||||
s/^[^ ][^ ]* [^ ][^ ]* \([^ ][^ ]*\).*/ \1,/
|
||||
' unary_op binary_op
|
||||
' "$unary_op" "$binary_op"
|
||||
echo '};
|
||||
|
||||
const char op_argflag[] = {'
|
||||
@@ -62,5 +70,5 @@ sed -e '/^[^#]/!d
|
||||
s/[ ][ ]*/ /g
|
||||
s/^[^ ][^ ]* [^ ][^ ]* [^ ][^ ]*$/& 0/
|
||||
s/^[^ ][^ ]* [^ ][^ ]* [^ ][^ ]* \([^ ][^ ]*\)/ \1,/
|
||||
' unary_op binary_op
|
||||
' "$unary_op" "$binary_op"
|
||||
echo '};'
|
||||
|
||||
8
commands/ash/bltin/myregexp.h
Normal file
8
commands/ash/bltin/myregexp.h
Normal file
@@ -0,0 +1,8 @@
|
||||
/*
|
||||
myregexp.h
|
||||
|
||||
Created: July 1995 by Philip Homburg <philip@cs.vu.nl>
|
||||
*/
|
||||
|
||||
char *re_compile(char *pattern);
|
||||
int re_match(char *pattern, char *string);
|
||||
@@ -8,7 +8,9 @@
|
||||
*/
|
||||
|
||||
#include "bltin.h"
|
||||
#include "myregexp.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#define RE_END 0 /* end of regular expression */
|
||||
#define RE_LITERAL 1 /* normal character follows */
|
||||
@@ -27,7 +29,7 @@
|
||||
char *match_begin[10];
|
||||
short match_length[10];
|
||||
short number_parens;
|
||||
static int match();
|
||||
static int match(char *pattern, char *string);
|
||||
|
||||
|
||||
|
||||
@@ -48,7 +50,6 @@ re_compile(pattern)
|
||||
char stack[10];
|
||||
int paren_num;
|
||||
int i;
|
||||
char *malloc();
|
||||
|
||||
p = pattern;
|
||||
if (*p == '^')
|
||||
@@ -176,6 +177,7 @@ out:
|
||||
|
||||
|
||||
|
||||
int
|
||||
re_match(pattern, string)
|
||||
char *pattern;
|
||||
char *string;
|
||||
@@ -246,7 +248,7 @@ ccl:
|
||||
p++;
|
||||
}
|
||||
p++;
|
||||
if (found == negate || c == 0)
|
||||
if (found == negate)
|
||||
goto bad;
|
||||
break;
|
||||
case RE_LP:
|
||||
|
||||
@@ -16,9 +16,8 @@ ISFIFO -p 12 OP_FILE
|
||||
ISSETUID -u 12 OP_FILE
|
||||
ISSETGID -g 12 OP_FILE
|
||||
ISSTICKY -k 12 OP_FILE
|
||||
ISSLINK -h 12 OP_FILE
|
||||
ISSIZE -s 12 OP_FILE
|
||||
ISLINK1 -h 12 OP_LFILE
|
||||
ISLINK2 -L 12 OP_LFILE
|
||||
ISTTY -t 12 OP_INT
|
||||
NULSTR -z 12 OP_STRING
|
||||
STRLEN -n 12 OP_STRING
|
||||
|
||||
@@ -1,3 +0,0 @@
|
||||
#!/bin/sh
|
||||
make clean
|
||||
make && make install
|
||||
21
commands/ash/builtins.table → commands/ash/builtins
Executable file → Normal file
21
commands/ash/builtins.table → commands/ash/builtins
Executable file → Normal file
@@ -1,7 +1,7 @@
|
||||
#!/bin/sh -
|
||||
#
|
||||
# Copyright (c) 1991 The Regents of the University of California.
|
||||
# All rights reserved.
|
||||
# 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.
|
||||
@@ -34,19 +34,21 @@
|
||||
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
# SUCH DAMAGE.
|
||||
#
|
||||
# @(#)builtins 5.1 (Berkeley) 3/7/91
|
||||
# @(#)builtins 8.1 (Berkeley) 5/31/93
|
||||
|
||||
#
|
||||
# This file lists all the builtin commands. The first column is the name
|
||||
# of a C routine. The -j flag, if present, specifies that this command
|
||||
# is to be excluded from systems without job control. The rest of the line
|
||||
# specifies the command name or names used to run the command. The entry
|
||||
# for nullcmd, which is run when the user does not specify a command, must
|
||||
# for bltincmd, which is run when the user does not specify a command, must
|
||||
# come first.
|
||||
#
|
||||
# Copyright (C) 1989 by Kenneth Almquist. All rights reserved.
|
||||
# This file is part of ash, which is distributed under the terms specified
|
||||
# by the Ash General Public License. See the file named LICENSE.
|
||||
#
|
||||
# NOTE: bltincmd must come first!
|
||||
|
||||
bltincmd command
|
||||
#alloccmd alloc
|
||||
@@ -59,17 +61,19 @@ echocmd echo
|
||||
evalcmd eval
|
||||
execcmd exec
|
||||
exitcmd exit
|
||||
expcmd exp let
|
||||
exportcmd export readonly
|
||||
exprcmd expr test [
|
||||
#exprcmd expr test [
|
||||
histcmd fc
|
||||
fgcmd -j fg
|
||||
getoptscmd getopts
|
||||
hashcmd hash
|
||||
jobidcmd jobid
|
||||
jobscmd jobs
|
||||
#lccmd lc
|
||||
#linecmd line
|
||||
localcmd local
|
||||
#nlechocmd nlecho
|
||||
printfcmd printf
|
||||
pwdcmd pwd
|
||||
readcmd read
|
||||
returncmd return
|
||||
@@ -77,7 +81,10 @@ setcmd set
|
||||
setvarcmd setvar
|
||||
shiftcmd shift
|
||||
trapcmd trap
|
||||
truecmd : true false
|
||||
truecmd : true
|
||||
umaskcmd umask
|
||||
unaliascmd unalias
|
||||
unsetcmd unset
|
||||
waitcmd wait
|
||||
#foocmd foo
|
||||
aliascmd alias
|
||||
94
commands/ash/builtins.def
Normal file
94
commands/ash/builtins.def
Normal file
@@ -0,0 +1,94 @@
|
||||
#!/bin/sh -
|
||||
#
|
||||
# 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.
|
||||
# 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.
|
||||
#
|
||||
# @(#)builtins.def 8.4 (Berkeley) 5/4/95
|
||||
# $FreeBSD: src/bin/sh/builtins.def,v 1.14 2004/04/06 20:06:51 markm Exp $
|
||||
|
||||
#
|
||||
# This file lists all the builtin commands. The first column is the name
|
||||
# of a C routine. The -j flag, if present, specifies that this command
|
||||
# is to be excluded from systems without job control, and the -h flag,
|
||||
# if present specifies that this command is to be excluded from systems
|
||||
# based on the NO_HISTORY compile-time symbol. The rest of the line
|
||||
# specifies the command name or names used to run the command. The entry
|
||||
# for bltincmd, which is run when the user does not specify a command, must
|
||||
# come first.
|
||||
#
|
||||
# NOTE: bltincmd must come first!
|
||||
|
||||
bltincmd builtin
|
||||
commandcmd command
|
||||
#alloccmd alloc
|
||||
bgcmd -j bg
|
||||
breakcmd break continue
|
||||
#catfcmd catf
|
||||
cdcmd cd chdir
|
||||
dotcmd .
|
||||
echocmd echo
|
||||
evalcmd eval
|
||||
execcmd exec
|
||||
exitcmd exit
|
||||
expcmd exp let
|
||||
exportcmd export readonly
|
||||
exprcmd expr test [
|
||||
falsecmd false
|
||||
histcmd -h fc
|
||||
fgcmd -j fg
|
||||
getoptscmd getopts
|
||||
hashcmd hash
|
||||
jobidcmd jobid
|
||||
jobscmd jobs
|
||||
#linecmd line
|
||||
localcmd local
|
||||
#nlechocmd nlecho
|
||||
#printfcmd printf
|
||||
pwdcmd pwd
|
||||
readcmd read
|
||||
returncmd return
|
||||
setcmd set
|
||||
setvarcmd setvar
|
||||
shiftcmd shift
|
||||
trapcmd trap
|
||||
truecmd : true
|
||||
typecmd type
|
||||
umaskcmd umask
|
||||
unaliascmd unalias
|
||||
unsetcmd unset
|
||||
waitcmd wait
|
||||
#foocmd foo
|
||||
aliascmd alias
|
||||
ulimitcmd ulimit
|
||||
bindcmd bind
|
||||
wordexpcmd wordexp
|
||||
|
||||
#
|
||||
# $PchId: builtins.def,v 1.5 2006/03/31 10:50:57 philip Exp $
|
||||
@@ -1,6 +1,6 @@
|
||||
/*-
|
||||
* Copyright (c) 1991 The Regents of the University of California.
|
||||
* All rights reserved.
|
||||
* 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.
|
||||
@@ -13,10 +13,6 @@
|
||||
* 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.
|
||||
@@ -35,8 +31,22 @@
|
||||
*/
|
||||
|
||||
#ifndef lint
|
||||
static char sccsid[] = "@(#)cd.c 5.2 (Berkeley) 3/13/91";
|
||||
#if 0
|
||||
static char sccsid[] = "@(#)cd.c 8.2 (Berkeley) 5/4/95";
|
||||
#endif
|
||||
#endif /* not lint */
|
||||
/*
|
||||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD: src/bin/sh/cd.c,v 1.34 2004/04/06 20:06:51 markm Exp $");
|
||||
*/
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
#include <limits.h>
|
||||
|
||||
/*
|
||||
* The cd and pwd commands.
|
||||
@@ -50,115 +60,124 @@ static char sccsid[] = "@(#)cd.c 5.2 (Berkeley) 3/13/91";
|
||||
#include "output.h"
|
||||
#include "memalloc.h"
|
||||
#include "error.h"
|
||||
#include "exec.h"
|
||||
#include "redir.h"
|
||||
#include "mystring.h"
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <errno.h>
|
||||
#include "builtins.h"
|
||||
#include "show.h"
|
||||
#include "cd.h"
|
||||
|
||||
|
||||
#ifdef __STDC__
|
||||
STATIC int cdlogical(char *);
|
||||
STATIC int cdphysical(char *);
|
||||
STATIC int docd(char *, int, int);
|
||||
STATIC void updatepwd(char *);
|
||||
STATIC void getpwd(void);
|
||||
STATIC char *getcomponent(void);
|
||||
#else
|
||||
STATIC int docd();
|
||||
STATIC void updatepwd();
|
||||
STATIC void getpwd();
|
||||
STATIC char *getcomponent();
|
||||
#endif
|
||||
STATIC int updatepwd(char *);
|
||||
|
||||
|
||||
char *curdir; /* current working directory */
|
||||
STATIC char *curdir = NULL; /* current working directory */
|
||||
STATIC char *prevdir; /* previous working directory */
|
||||
STATIC char *cdcomppath;
|
||||
|
||||
#if UDIR || TILDE
|
||||
extern int didudir; /* set if /u/logname or ~logname expanded */
|
||||
#endif
|
||||
|
||||
|
||||
int
|
||||
cdcmd(argc, argv) char **argv; {
|
||||
cdcmd(int argc, char **argv)
|
||||
{
|
||||
char *dest;
|
||||
char *path;
|
||||
char *p;
|
||||
struct stat statb;
|
||||
char *padvance();
|
||||
int tohome= 0;
|
||||
int ch, phys, print = 0;
|
||||
|
||||
nextopt(nullstr);
|
||||
if ((dest = *argptr) == NULL) {
|
||||
if ((dest = bltinlookup("HOME", 1)) == NULL)
|
||||
error("HOME not set");
|
||||
tohome = 1;
|
||||
optreset = 1; optind = 1; opterr = 0; /* initialize getopt */
|
||||
phys = Pflag;
|
||||
while ((ch = getopt(argc, argv, "LP")) != -1) {
|
||||
switch (ch) {
|
||||
case 'L':
|
||||
phys = 0;
|
||||
break;
|
||||
case 'P':
|
||||
phys = 1;
|
||||
break;
|
||||
default:
|
||||
error("unknown option: -%c", optopt);
|
||||
break;
|
||||
}
|
||||
}
|
||||
argc -= optind;
|
||||
argv += optind;
|
||||
|
||||
if (argc > 1)
|
||||
error("too many arguments");
|
||||
|
||||
if ((dest = *argv) == NULL && (dest = bltinlookup("HOME", 1)) == NULL)
|
||||
error("HOME not set");
|
||||
if (*dest == '\0')
|
||||
dest = ".";
|
||||
if (dest[0] == '-' && dest[1] == '\0') {
|
||||
dest = prevdir ? prevdir : curdir;
|
||||
if (dest)
|
||||
print = 1;
|
||||
else
|
||||
dest = ".";
|
||||
}
|
||||
if (*dest == '/' || (path = bltinlookup("CDPATH", 1)) == NULL)
|
||||
path = nullstr;
|
||||
while ((p = padvance(&path, dest)) != NULL) {
|
||||
if (stat(p, &statb) >= 0
|
||||
&& (statb.st_mode & S_IFMT) == S_IFDIR
|
||||
&& docd(p, strcmp(p, dest), tohome) >= 0)
|
||||
return 0;
|
||||
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, phys) >= 0)
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
error("can't cd to %s", dest);
|
||||
/*NOTREACHED*/
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Actually do the chdir. If the name refers to symbolic links, we
|
||||
* compute the actual directory name before doing the cd. In an
|
||||
* interactive shell, print the directory name if "print" is nonzero
|
||||
* or if the name refers to a symbolic link. We also print the name
|
||||
* if "/u/logname" was expanded in it, since this is similar to a
|
||||
* symbolic link. (The check for this breaks if the user gives the
|
||||
* cd command some additional, unused arguments.)
|
||||
* Actually change the directory. In an interactive shell, print the
|
||||
* directory name if "print" is nonzero.
|
||||
*/
|
||||
|
||||
#if SYMLINKS == 0
|
||||
STATIC int
|
||||
docd(dest, print, tohome)
|
||||
char *dest;
|
||||
{
|
||||
#if UDIR || TILDE
|
||||
if (didudir)
|
||||
print = 1;
|
||||
#endif
|
||||
INTOFF;
|
||||
if (chdir(dest) < 0) {
|
||||
INTON;
|
||||
return -1;
|
||||
}
|
||||
updatepwd(dest);
|
||||
INTON;
|
||||
if (print && iflag)
|
||||
out1fmt("%s\n", stackblock());
|
||||
docd(char *dest, int print, int phys)
|
||||
{
|
||||
|
||||
TRACE(("docd(\"%s\", %d, %d) called\n", dest, print, phys));
|
||||
|
||||
/* If logical cd fails, fall back to physical. */
|
||||
if ((phys || cdlogical(dest) < 0) && cdphysical(dest) < 0)
|
||||
return (-1);
|
||||
|
||||
if (print && iflag && curdir)
|
||||
out1fmt("%s\n", curdir);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
|
||||
|
||||
STATIC int
|
||||
docd(dest, print, tohome)
|
||||
char *dest;
|
||||
{
|
||||
register char *p;
|
||||
register char *q;
|
||||
char *symlink;
|
||||
cdlogical(char *dest)
|
||||
{
|
||||
char *p;
|
||||
char *q;
|
||||
char *component;
|
||||
struct stat statb;
|
||||
int first;
|
||||
int i;
|
||||
int badstat;
|
||||
|
||||
TRACE(("docd(\"%s\", %d, %d) called\n", dest, print, tohome));
|
||||
#if UDIR || TILDE
|
||||
if (didudir)
|
||||
print = 1;
|
||||
#endif
|
||||
|
||||
top:
|
||||
cdcomppath = dest;
|
||||
/*
|
||||
* 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);
|
||||
@@ -166,7 +185,7 @@ top:
|
||||
}
|
||||
first = 1;
|
||||
while ((q = getcomponent()) != NULL) {
|
||||
if (q[0] == '\0' || q[0] == '.' && q[1] == '\0')
|
||||
if (q[0] == '\0' || (q[0] == '.' && q[1] == '\0'))
|
||||
continue;
|
||||
if (! first)
|
||||
STPUTC('/', p);
|
||||
@@ -177,71 +196,42 @@ top:
|
||||
if (equal(component, ".."))
|
||||
continue;
|
||||
STACKSTRNUL(p);
|
||||
if (lstat(stackblock(), &statb) < 0)
|
||||
error("lstat %s failed", stackblock());
|
||||
if ((statb.st_mode & S_IFMT) != S_IFLNK)
|
||||
continue;
|
||||
|
||||
/* Hit a symbolic link. We have to start all over again. */
|
||||
print = 1;
|
||||
STPUTC('\0', p);
|
||||
symlink = grabstackstr(p);
|
||||
i = (int)statb.st_size + 2; /* 2 for '/' and '\0' */
|
||||
if (cdcomppath != NULL)
|
||||
i += strlen(cdcomppath);
|
||||
p = stalloc(i);
|
||||
if (readlink(symlink, p, (int)statb.st_size) < 0) {
|
||||
error("readlink %s failed", stackblock());
|
||||
if (lstat(stackblock(), &statb) < 0) {
|
||||
badstat = 1;
|
||||
break;
|
||||
}
|
||||
if (cdcomppath != NULL) {
|
||||
p[(int)statb.st_size] = '/';
|
||||
scopy(cdcomppath, p + (int)statb.st_size + 1);
|
||||
} else {
|
||||
p[(int)statb.st_size] = '\0';
|
||||
}
|
||||
if (p[0] != '/') { /* relative path name */
|
||||
char *r;
|
||||
q = r = symlink;
|
||||
while (*q) {
|
||||
if (*q++ == '/')
|
||||
r = q;
|
||||
}
|
||||
*r = '\0';
|
||||
dest = stalloc(strlen(symlink) + strlen(p) + 1);
|
||||
scopy(symlink, dest);
|
||||
strcat(dest, p);
|
||||
} else {
|
||||
dest = p;
|
||||
}
|
||||
goto top;
|
||||
}
|
||||
STPUTC('\0', p);
|
||||
p = grabstackstr(p);
|
||||
|
||||
INTOFF;
|
||||
/* The empty string is not a legal argument to chdir on a POSIX 1003.1
|
||||
* system. */
|
||||
if (p[0] != '\0' && chdir(p) < 0) {
|
||||
if (updatepwd(badstat ? NULL : dest) < 0 || chdir(curdir) < 0) {
|
||||
INTON;
|
||||
return -1;
|
||||
return (-1);
|
||||
}
|
||||
updatepwd(p);
|
||||
INTON;
|
||||
if (print && !tohome && iflag)
|
||||
out1fmt("%s\n", p);
|
||||
return 0;
|
||||
return (0);
|
||||
}
|
||||
#endif /* SYMLINKS */
|
||||
|
||||
STATIC int
|
||||
cdphysical(char *dest)
|
||||
{
|
||||
|
||||
INTOFF;
|
||||
if (chdir(dest) < 0 || updatepwd(NULL) < 0) {
|
||||
INTON;
|
||||
return (-1);
|
||||
}
|
||||
INTON;
|
||||
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() {
|
||||
register char *p;
|
||||
getcomponent(void)
|
||||
{
|
||||
char *p;
|
||||
char *start;
|
||||
|
||||
if ((p = cdcomppath) == NULL)
|
||||
@@ -259,29 +249,43 @@ getcomponent() {
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
void hashcd();
|
||||
|
||||
STATIC void
|
||||
updatepwd(dir)
|
||||
char *dir;
|
||||
{
|
||||
STATIC int
|
||||
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;
|
||||
if (getpwd() == NULL) {
|
||||
INTON;
|
||||
return (-1);
|
||||
}
|
||||
setvar("PWD", curdir, VEXPORT);
|
||||
setvar("OLDPWD", prevdir, VEXPORT);
|
||||
INTON;
|
||||
return (0);
|
||||
}
|
||||
cdcomppath = stalloc(strlen(dir) + 1);
|
||||
scopy(dir, cdcomppath);
|
||||
STARTSTACKSTR(new);
|
||||
if (*dir != '/') {
|
||||
if (curdir == NULL)
|
||||
return;
|
||||
p = curdir;
|
||||
while (*p)
|
||||
STPUTC(*p++, new);
|
||||
@@ -300,73 +304,87 @@ updatepwd(dir)
|
||||
if (new == stackblock())
|
||||
STPUTC('/', new);
|
||||
STACKSTRNUL(new);
|
||||
if (curdir)
|
||||
ckfree(curdir);
|
||||
INTOFF;
|
||||
if (prevdir)
|
||||
ckfree(prevdir);
|
||||
prevdir = curdir;
|
||||
curdir = savestr(stackblock());
|
||||
setvar("PWD", curdir, VEXPORT);
|
||||
setvar("OLDPWD", prevdir, VEXPORT);
|
||||
INTON;
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
|
||||
|
||||
int
|
||||
pwdcmd(argc, argv) char **argv; {
|
||||
getpwd();
|
||||
out1str(curdir);
|
||||
out1c('\n');
|
||||
pwdcmd(int argc, char **argv)
|
||||
{
|
||||
char buf[PATH_MAX];
|
||||
int ch, phys;
|
||||
|
||||
optreset = 1; optind = 1; opterr = 0; /* initialize getopt */
|
||||
phys = Pflag;
|
||||
while ((ch = getopt(argc, argv, "LP")) != -1) {
|
||||
switch (ch) {
|
||||
case 'L':
|
||||
phys = 0;
|
||||
break;
|
||||
case 'P':
|
||||
phys = 1;
|
||||
break;
|
||||
default:
|
||||
error("unknown option: -%c", optopt);
|
||||
break;
|
||||
}
|
||||
}
|
||||
argc -= optind;
|
||||
argv += optind;
|
||||
|
||||
if (argc != 0)
|
||||
error("too many arguments");
|
||||
|
||||
if (!phys && getpwd()) {
|
||||
out1str(curdir);
|
||||
out1c('\n');
|
||||
} else {
|
||||
if (getcwd(buf, sizeof(buf)) == NULL)
|
||||
error(".: %s", strerror(errno));
|
||||
out1str(buf);
|
||||
out1c('\n');
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Run /bin/pwd to find out what the current directory is. We suppress
|
||||
* interrupts throughout most of this, but the user can still break out
|
||||
* of it by killing the pwd program. If we already know the current
|
||||
* Find out what the current directory is. If we already know the current
|
||||
* directory, this routine returns immediately.
|
||||
*/
|
||||
|
||||
#define MAXPWD 256
|
||||
|
||||
STATIC void
|
||||
getpwd() {
|
||||
char buf[MAXPWD];
|
||||
char *p;
|
||||
int i;
|
||||
int status;
|
||||
struct job *jp;
|
||||
int pip[2];
|
||||
char *
|
||||
getpwd(void)
|
||||
{
|
||||
char buf[PATH_MAX];
|
||||
|
||||
if (curdir)
|
||||
return;
|
||||
INTOFF;
|
||||
if (pipe(pip) < 0)
|
||||
error("Pipe call failed");
|
||||
jp = makejob((union node *)NULL, 1);
|
||||
if (forkshell(jp, (union node *)NULL, FORK_NOJOB) == 0) {
|
||||
close(pip[0]);
|
||||
if (pip[1] != 1) {
|
||||
close(1);
|
||||
copyfd(pip[1], 1);
|
||||
close(pip[1]);
|
||||
return curdir;
|
||||
if (getcwd(buf, sizeof(buf)) == NULL) {
|
||||
char *pwd = getenv("PWD");
|
||||
struct stat stdot, stpwd;
|
||||
|
||||
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 curdir;
|
||||
}
|
||||
execl("/bin/pwd", "pwd", (char *)0);
|
||||
error("Cannot exec /bin/pwd");
|
||||
return NULL;
|
||||
}
|
||||
close(pip[1]);
|
||||
pip[1] = -1;
|
||||
p = buf;
|
||||
while ((i = read(pip[0], p, buf + MAXPWD - p)) > 0
|
||||
|| i == -1 && errno == EINTR) {
|
||||
if (i > 0)
|
||||
p += i;
|
||||
}
|
||||
close(pip[0]);
|
||||
pip[0] = -1;
|
||||
status = waitforjob(jp);
|
||||
if (status != 0)
|
||||
error((char *)0);
|
||||
if (i < 0 || p == buf || p[-1] != '\n')
|
||||
error("pwd command failed");
|
||||
p[-1] = '\0';
|
||||
curdir = savestr(buf);
|
||||
INTON;
|
||||
|
||||
return curdir;
|
||||
}
|
||||
|
||||
/*
|
||||
* $PchId: cd.c,v 1.6 2006/05/22 12:42:03 philip Exp $
|
||||
*/
|
||||
|
||||
38
commands/ash/cd.h
Normal file
38
commands/ash/cd.h
Normal file
@@ -0,0 +1,38 @@
|
||||
/*-
|
||||
* 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.
|
||||
* 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.
|
||||
*
|
||||
* $FreeBSD: src/bin/sh/cd.h,v 1.7 2004/04/06 20:06:51 markm Exp $
|
||||
*/
|
||||
|
||||
char *getpwd(void);
|
||||
int cdcmd (int, char **);
|
||||
int pwdcmd(int, char **);
|
||||
|
||||
/*
|
||||
* $PchId: cd.h,v 1.3 2006/03/31 09:59:04 philip Exp $
|
||||
*/
|
||||
354
commands/ash/complete.c
Normal file
354
commands/ash/complete.c
Normal file
@@ -0,0 +1,354 @@
|
||||
/*
|
||||
complete.c
|
||||
|
||||
Created: July 1995 by Philip Homburg <philip@cs.vu.nl>
|
||||
*/
|
||||
|
||||
#include <ctype.h>
|
||||
#include <dirent.h>
|
||||
#include <errno.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/stat.h>
|
||||
#include "myhistedit.h"
|
||||
#include "shell.h"
|
||||
|
||||
#include "complete.h"
|
||||
#include "error.h"
|
||||
#include "expand.h"
|
||||
#include "nodes.h"
|
||||
#include "memalloc.h"
|
||||
|
||||
static char **getlist(EditLine *el, int *baselen, int *isdir);
|
||||
static char **getlist_tilde(char *prefix);
|
||||
static int vstrcmp(const void *v1, const void *v2);
|
||||
static void print_list(char **list);
|
||||
static int install_extra(EditLine *el, char **list, int baselen, int isdir);
|
||||
|
||||
unsigned char complete(EditLine *el, int ch)
|
||||
{
|
||||
struct stackmark mark;
|
||||
const LineInfo *lf;
|
||||
char **list;
|
||||
int baselen, prefix, isdir;
|
||||
|
||||
/* Direct the cursor the the end of the word. */
|
||||
for(;;)
|
||||
{
|
||||
lf = el_line(el);
|
||||
if (lf->cursor < lf->lastchar &&
|
||||
!isspace((unsigned char)*lf->cursor))
|
||||
{
|
||||
(*(char **)&lf->cursor)++; /* XXX */
|
||||
}
|
||||
else
|
||||
break;
|
||||
}
|
||||
|
||||
setstackmark(&mark);
|
||||
list= getlist(el, &baselen, &isdir);
|
||||
if (list)
|
||||
{
|
||||
prefix= install_extra(el, list, baselen, isdir);
|
||||
el_push(el, "i");
|
||||
}
|
||||
popstackmark(&mark);
|
||||
if (list)
|
||||
return CC_REFRESH;
|
||||
else
|
||||
return CC_ERROR;
|
||||
}
|
||||
|
||||
unsigned char complete_list(EditLine *el, int ch)
|
||||
{
|
||||
struct stackmark mark;
|
||||
char **list;
|
||||
|
||||
setstackmark(&mark);
|
||||
list= getlist(el, NULL, NULL);
|
||||
if (list)
|
||||
{
|
||||
print_list(list);
|
||||
re_goto_bottom(el);
|
||||
}
|
||||
popstackmark(&mark);
|
||||
if (list)
|
||||
{
|
||||
return CC_REFRESH;
|
||||
}
|
||||
else
|
||||
return CC_ERROR;
|
||||
}
|
||||
|
||||
unsigned char complete_or_list(EditLine *el, int ch)
|
||||
{
|
||||
struct stackmark mark;
|
||||
const LineInfo *lf;
|
||||
char **list;
|
||||
int baselen, prefix, isdir;
|
||||
|
||||
setstackmark(&mark);
|
||||
list= getlist(el, &baselen, &isdir);
|
||||
if (list)
|
||||
{
|
||||
prefix= install_extra(el, list, baselen, isdir);
|
||||
if (prefix == baselen)
|
||||
{
|
||||
print_list(list);
|
||||
re_goto_bottom(el);
|
||||
}
|
||||
}
|
||||
popstackmark(&mark);
|
||||
if (list)
|
||||
return CC_REFRESH;
|
||||
else
|
||||
return CC_ERROR;
|
||||
}
|
||||
|
||||
unsigned char complete_expand(EditLine *el, int ch)
|
||||
{
|
||||
printf("complete_expand\n");
|
||||
return CC_ERROR;
|
||||
}
|
||||
|
||||
static char **getlist(EditLine *el, int *baselen, int *isdir)
|
||||
{
|
||||
const LineInfo *lf;
|
||||
const char *begin, *end;
|
||||
char *dirnam, *basenam;
|
||||
union node arg;
|
||||
struct arglist arglist;
|
||||
DIR *dir;
|
||||
struct dirent *dirent;
|
||||
int i, l, n;
|
||||
char *p, **list;
|
||||
struct strlist *slp, *nslp;
|
||||
struct stat sb;
|
||||
|
||||
lf = el_line(el);
|
||||
|
||||
/* Try to find to begin and end of the word that we have to comple. */
|
||||
begin= lf->cursor;
|
||||
while (begin > lf->buffer && !isspace((unsigned char)begin[-1]))
|
||||
begin--;
|
||||
end= lf->cursor;
|
||||
while (end < lf->lastchar && !isspace((unsigned char)end[0]))
|
||||
end++;
|
||||
|
||||
*(const char **)&lf->cursor= end; /* XXX */
|
||||
|
||||
/* Copy the word to a string */
|
||||
dirnam= stalloc(end-begin+1);
|
||||
strncpy(dirnam, begin, end-begin);
|
||||
dirnam[end-begin]= '\0';
|
||||
|
||||
/* Cut the word in two pieces: a path and a (partial) component. */
|
||||
basenam= strrchr(dirnam, '/');
|
||||
if (basenam)
|
||||
{
|
||||
basenam++;
|
||||
p= stalloc(strlen(basenam) + 1);
|
||||
strcpy(p, basenam);
|
||||
*basenam= '\0';
|
||||
basenam= p;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (dirnam[0] == '~')
|
||||
return getlist_tilde(dirnam);
|
||||
basenam= dirnam;
|
||||
dirnam= "./";
|
||||
}
|
||||
if (baselen)
|
||||
*baselen= strlen(basenam);
|
||||
|
||||
arg.type= NARG;
|
||||
arg.narg.next= NULL;
|
||||
arg.narg.text= dirnam;
|
||||
arg.narg.backquote= NULL;
|
||||
arglist.list= NULL;
|
||||
arglist.lastp= &arglist.list;
|
||||
expandarg(&arg, &arglist, EXP_TILDE);
|
||||
|
||||
INTOFF;
|
||||
list= NULL;
|
||||
dir= opendir(arglist.list->text);
|
||||
if (dir)
|
||||
{
|
||||
slp= NULL;
|
||||
n= 0;
|
||||
l= strlen(basenam);
|
||||
while(dirent= readdir(dir))
|
||||
{
|
||||
if (strncmp(dirent->d_name, basenam, l) != 0)
|
||||
continue;
|
||||
if (l == 0 && dirent->d_name[0] == '.')
|
||||
continue;
|
||||
nslp= stalloc(sizeof(*nslp));
|
||||
nslp->next= slp;
|
||||
slp= nslp;
|
||||
slp->text= stalloc(strlen(dirent->d_name)+1);
|
||||
strcpy(slp->text, dirent->d_name);
|
||||
n++;
|
||||
if (n == 1 && isdir != NULL)
|
||||
{
|
||||
/* Try to findout whether this entry is a
|
||||
* file or a directory.
|
||||
*/
|
||||
p= stalloc(strlen(arglist.list->text) +
|
||||
strlen(dirent->d_name) + 1);
|
||||
strcpy(p, arglist.list->text);
|
||||
strcat(p, dirent->d_name);
|
||||
if (stat(p, &sb) == -1)
|
||||
printf("stat '%s' failed: %s\n",
|
||||
p, strerror(errno));
|
||||
if (stat(p, &sb) == 0 && S_ISDIR(sb.st_mode))
|
||||
*isdir= 1;
|
||||
else
|
||||
*isdir= 0;
|
||||
}
|
||||
}
|
||||
closedir(dir);
|
||||
if (n != 0)
|
||||
{
|
||||
list= stalloc((n+1)*sizeof(*list));
|
||||
for(i= 0; slp; i++, slp= slp->next)
|
||||
list[i]= slp->text;
|
||||
if (i != n)
|
||||
error("complete'make_list: i != n");
|
||||
list[i]= NULL;
|
||||
qsort(list, n, sizeof(*list), vstrcmp);
|
||||
}
|
||||
}
|
||||
INTON;
|
||||
return list;
|
||||
}
|
||||
|
||||
static char **getlist_tilde(char *prefix)
|
||||
{
|
||||
printf("should ~-complete '%s'\n", prefix);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int vstrcmp(const void *v1, const void *v2)
|
||||
{
|
||||
return strcmp(*(char **)v1, *(char **)v2);
|
||||
}
|
||||
|
||||
#define MAXCOLS 40
|
||||
#define SEPWIDTH 4
|
||||
|
||||
static void print_list(char **list)
|
||||
{
|
||||
struct
|
||||
{
|
||||
int cols;
|
||||
int start[MAXCOLS+1];
|
||||
int width[MAXCOLS];
|
||||
} best, next;
|
||||
int e, i, j, l, n, o, cols, maxw, width;
|
||||
int linewidth= 80;
|
||||
|
||||
/* Count the number of entries. */
|
||||
for (n= 0; list[n]; n++)
|
||||
; /* do nothing */
|
||||
if (n == 0)
|
||||
error("complete'print_list: n= 0");
|
||||
|
||||
/* Try to maximize the number of columns */
|
||||
for (cols= 1; cols<= MAXCOLS; cols++)
|
||||
{
|
||||
next.cols= cols;
|
||||
|
||||
o= 0;
|
||||
width= 0;
|
||||
for(j= 0; j<cols; j++)
|
||||
{
|
||||
next.start[j]= o;
|
||||
|
||||
/* Number of entries in this column. */
|
||||
e= (n-o)/(cols-j);
|
||||
if ((n-o)%(cols-j))
|
||||
e++;
|
||||
|
||||
maxw= 0;
|
||||
for (i= 0; i<e; i++)
|
||||
{
|
||||
l= strlen(list[o+i]);
|
||||
if (l < 6)
|
||||
l= 6;
|
||||
l += SEPWIDTH;
|
||||
if (l > maxw)
|
||||
maxw= l;
|
||||
}
|
||||
next.width[j]= maxw;
|
||||
width += maxw;
|
||||
o += e;
|
||||
}
|
||||
next.start[j]= o;
|
||||
if (cols > 1 && width-SEPWIDTH>linewidth)
|
||||
break;
|
||||
best= next;
|
||||
}
|
||||
cols= best.cols;
|
||||
e= best.start[1];
|
||||
printf("\n");
|
||||
for(i= 0; i<e; i++)
|
||||
{
|
||||
for (j= 0; j<cols; j++)
|
||||
{
|
||||
if (best.start[j]+i == best.start[j+1])
|
||||
continue;
|
||||
if (j < cols-1)
|
||||
{
|
||||
printf("%-*s", best.width[j],
|
||||
list[best.start[j]+i]);
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("%s", list[best.start[j]+i]);
|
||||
}
|
||||
}
|
||||
if (i < e-1)
|
||||
printf("\n");
|
||||
}
|
||||
fflush(stdout);
|
||||
}
|
||||
|
||||
static int install_extra(EditLine *el, char **list, int baselen, int isdir)
|
||||
{
|
||||
int l;
|
||||
char *p, **lp;
|
||||
|
||||
l= strlen(list[0]);
|
||||
for (lp= &list[1]; *lp; lp++)
|
||||
{
|
||||
while(l>0)
|
||||
{
|
||||
if (strncmp(list[0], *lp, l) != 0)
|
||||
l--;
|
||||
else
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (l > baselen || list[1] == NULL)
|
||||
{
|
||||
p= stalloc(l-baselen+2);
|
||||
strncpy(p, list[0]+baselen, l-baselen);
|
||||
if (list[1] == NULL)
|
||||
{
|
||||
p[l-baselen]= isdir ? '/' : ' ';
|
||||
p[l-baselen+1]= '\0';
|
||||
l++;
|
||||
}
|
||||
else
|
||||
p[l-baselen]= '\0';
|
||||
if (el_insertstr(el, p) == -1)
|
||||
return -1;
|
||||
}
|
||||
return l;
|
||||
}
|
||||
|
||||
/*
|
||||
* $PchId: complete.c,v 1.2 2006/04/10 14:35:53 philip Exp $
|
||||
*/
|
||||
14
commands/ash/complete.h
Normal file
14
commands/ash/complete.h
Normal file
@@ -0,0 +1,14 @@
|
||||
/*
|
||||
complete.h
|
||||
|
||||
Created: July 1995 by Philip Homburg <philip@cs.vu.nl>
|
||||
*/
|
||||
|
||||
unsigned char complete(EditLine *el, int ch);
|
||||
unsigned char complete_list(EditLine *el, int ch);
|
||||
unsigned char complete_or_list(EditLine *el, int ch);
|
||||
unsigned char complete_expand(EditLine *el, int ch);
|
||||
|
||||
/*
|
||||
* $PchId: complete.h,v 1.1 2001/05/17 07:12:05 philip Exp $
|
||||
*/
|
||||
@@ -1,194 +0,0 @@
|
||||
/*-
|
||||
* Copyright (c) 1991 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.
|
||||
*/
|
||||
|
||||
#ifndef lint
|
||||
static char sccsid[] = "@(#)dirent.c 5.1 (Berkeley) 3/7/91";
|
||||
#endif /* not lint */
|
||||
|
||||
#include "shell.h" /* definitions for pointer, NULL, DIRENT, and BSD */
|
||||
|
||||
#if ! DIRENT
|
||||
|
||||
#include <errno.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#include <dirent.h>
|
||||
|
||||
#ifndef S_ISDIR /* macro to test for directory file */
|
||||
#define S_ISDIR(mode) (((mode) & S_IFMT) == S_IFDIR)
|
||||
#endif
|
||||
|
||||
#ifdef BSD
|
||||
|
||||
#ifdef __STDC__
|
||||
int stat(char *, struct stat *);
|
||||
#else
|
||||
int stat();
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
* The BSD opendir routine doesn't check that what is being opened is a
|
||||
* directory, so we have to include the check in a wrapper routine.
|
||||
*/
|
||||
|
||||
#undef opendir
|
||||
|
||||
DIR *
|
||||
myopendir(dirname)
|
||||
char *dirname; /* name of directory */
|
||||
{
|
||||
struct stat statb;
|
||||
|
||||
if (stat(dirname, &statb) != 0 || ! S_ISDIR(statb.st_mode)) {
|
||||
errno = ENOTDIR;
|
||||
return NULL; /* not a directory */
|
||||
}
|
||||
return opendir(dirname);
|
||||
}
|
||||
|
||||
#else /* not BSD */
|
||||
|
||||
/*
|
||||
* Dirent routines for old style file systems.
|
||||
*/
|
||||
|
||||
#ifdef __STDC__
|
||||
pointer malloc(unsigned);
|
||||
void free(pointer);
|
||||
int open(char *, int, ...);
|
||||
int close(int);
|
||||
int fstat(int, struct stat *);
|
||||
#else
|
||||
pointer malloc();
|
||||
void free();
|
||||
int open();
|
||||
int close();
|
||||
int fstat();
|
||||
#endif
|
||||
|
||||
|
||||
DIR *
|
||||
opendir(dirname)
|
||||
char *dirname; /* name of directory */
|
||||
{
|
||||
register DIR *dirp; /* -> malloc'ed storage */
|
||||
register int fd; /* file descriptor for read */
|
||||
struct stat statb; /* result of fstat() */
|
||||
|
||||
#ifdef O_NDELAY
|
||||
fd = open(dirname, O_RDONLY|O_NDELAY);
|
||||
#else
|
||||
fd = open(dirname, O_RDONLY);
|
||||
#endif
|
||||
if (fd < 0)
|
||||
return NULL; /* errno set by open() */
|
||||
|
||||
if (fstat(fd, &statb) != 0 || !S_ISDIR(statb.st_mode)) {
|
||||
(void)close(fd);
|
||||
errno = ENOTDIR;
|
||||
return NULL; /* not a directory */
|
||||
}
|
||||
|
||||
if ((dirp = (DIR *)malloc(sizeof(DIR))) == NULL) {
|
||||
(void)close(fd);
|
||||
errno = ENOMEM;
|
||||
return NULL; /* not enough memory */
|
||||
}
|
||||
|
||||
dirp->dd_fd = fd;
|
||||
dirp->dd_nleft = 0; /* refill needed */
|
||||
|
||||
return dirp;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int
|
||||
closedir(dirp)
|
||||
register DIR *dirp; /* stream from opendir() */
|
||||
{
|
||||
register int fd;
|
||||
|
||||
if (dirp == NULL) {
|
||||
errno = EFAULT;
|
||||
return -1; /* invalid pointer */
|
||||
}
|
||||
|
||||
fd = dirp->dd_fd;
|
||||
free((pointer)dirp);
|
||||
return close(fd);
|
||||
}
|
||||
|
||||
|
||||
|
||||
struct dirent *
|
||||
readdir(dirp)
|
||||
register DIR *dirp; /* stream from opendir() */
|
||||
{
|
||||
register struct direct *dp;
|
||||
register char *p, *q;
|
||||
register int i;
|
||||
|
||||
do {
|
||||
if ((dirp->dd_nleft -= sizeof (struct direct)) < 0) {
|
||||
if ((i = read(dirp->dd_fd,
|
||||
(char *)dirp->dd_buf,
|
||||
DIRBUFENT*sizeof(struct direct))) <= 0) {
|
||||
if (i == 0)
|
||||
errno = 0; /* unnecessary */
|
||||
return NULL; /* EOF or error */
|
||||
}
|
||||
dirp->dd_loc = dirp->dd_buf;
|
||||
dirp->dd_nleft = i - sizeof (struct direct);
|
||||
}
|
||||
dp = dirp->dd_loc++;
|
||||
} while (dp->d_ino == 0);
|
||||
dirp->dd_entry.d_ino = dp->d_ino;
|
||||
|
||||
/* now copy the name, nul terminating it */
|
||||
p = dp->d_name;
|
||||
q = dirp->dd_entry.d_name;
|
||||
i = DIRSIZ;
|
||||
while (--i >= 0 && *p != '\0')
|
||||
*q++ = *p++;
|
||||
*q = '\0';
|
||||
return &dirp->dd_entry;
|
||||
}
|
||||
|
||||
#endif /* BSD */
|
||||
#endif /* DIRENT */
|
||||
127
commands/ash/errmsg.c
Normal file
127
commands/ash/errmsg.c
Normal file
@@ -0,0 +1,127 @@
|
||||
/*-
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef lint
|
||||
static char sccsid[] = "@(#)errmsg.c 8.1 (Berkeley) 5/31/93";
|
||||
#endif /* not lint */
|
||||
|
||||
#include "shell.h"
|
||||
#include "output.h"
|
||||
#include "errmsg.h"
|
||||
#include <errno.h>
|
||||
|
||||
|
||||
#define ALL (E_OPEN|E_CREAT|E_EXEC)
|
||||
|
||||
|
||||
struct errname {
|
||||
short errcode; /* error number */
|
||||
short action; /* operation which encountered the error */
|
||||
char *msg; /* text describing the error */
|
||||
};
|
||||
|
||||
|
||||
STATIC const struct errname errormsg[] = {
|
||||
EINTR, ALL, "interrupted",
|
||||
EACCES, ALL, "permission denied",
|
||||
EIO, ALL, "I/O error",
|
||||
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",
|
||||
/* EMFILE, ALL, "too many open files", */
|
||||
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 SYSV
|
||||
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.
|
||||
*/
|
||||
|
||||
char *
|
||||
errmsg(e, 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;
|
||||
}
|
||||
47
commands/ash/errmsg.h
Normal file
47
commands/ash/errmsg.h
Normal file
@@ -0,0 +1,47 @@
|
||||
/*-
|
||||
* 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.
|
||||
*
|
||||
* @(#)errmsg.h 8.1 (Berkeley) 5/31/93
|
||||
*/
|
||||
|
||||
#define E_OPEN 01
|
||||
#define E_CREAT 02
|
||||
#define E_EXEC 04
|
||||
|
||||
#ifdef __STDC__
|
||||
char *errmsg(int, int);
|
||||
#else
|
||||
char *errmsg();
|
||||
#endif
|
||||
@@ -1,6 +1,6 @@
|
||||
/*-
|
||||
* Copyright (c) 1991 The Regents of the University of California.
|
||||
* All rights reserved.
|
||||
* 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.
|
||||
@@ -13,10 +13,6 @@
|
||||
* 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.
|
||||
@@ -35,8 +31,14 @@
|
||||
*/
|
||||
|
||||
#ifndef lint
|
||||
static char sccsid[] = "@(#)error.c 5.1 (Berkeley) 3/7/91";
|
||||
#if 0
|
||||
static char sccsid[] = "@(#)error.c 8.2 (Berkeley) 5/4/95";
|
||||
#endif
|
||||
#endif /* not lint */
|
||||
/*
|
||||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD: src/bin/sh/error.c,v 1.25 2004/04/06 20:06:51 markm Exp $");
|
||||
*/
|
||||
|
||||
/*
|
||||
* Errors and exceptions.
|
||||
@@ -47,14 +49,14 @@ static char sccsid[] = "@(#)error.c 5.1 (Berkeley) 3/7/91";
|
||||
#include "options.h"
|
||||
#include "output.h"
|
||||
#include "error.h"
|
||||
#include <sys/types.h>
|
||||
#include "nodes.h" /* show.h needs nodes.h */
|
||||
#include "show.h"
|
||||
#include "trap.h"
|
||||
#include <signal.h>
|
||||
#ifdef __STDC__
|
||||
#include "stdarg.h"
|
||||
#else
|
||||
#include <varargs.h>
|
||||
#endif
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
|
||||
/*
|
||||
@@ -62,12 +64,14 @@ static char sccsid[] = "@(#)error.c 5.1 (Berkeley) 3/7/91";
|
||||
*/
|
||||
|
||||
struct jmploc *handler;
|
||||
int exception;
|
||||
volatile int suppressint;
|
||||
volatile int intpending;
|
||||
volatile sig_atomic_t exception;
|
||||
volatile sig_atomic_t suppressint;
|
||||
volatile sig_atomic_t intpending;
|
||||
char *commandname;
|
||||
|
||||
|
||||
static void exverror(int, const char *, va_list) __printf0like(2, 0);
|
||||
|
||||
/*
|
||||
* 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
|
||||
@@ -75,7 +79,8 @@ char *commandname;
|
||||
*/
|
||||
|
||||
void
|
||||
exraise(e) {
|
||||
exraise(int e)
|
||||
{
|
||||
if (handler == NULL)
|
||||
abort();
|
||||
exception = e;
|
||||
@@ -87,69 +92,63 @@ exraise(e) {
|
||||
* 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.)
|
||||
* are held using the INTOFF macro. If SIGINTs are not suppressed and
|
||||
* the shell is not a root shell, then we want to be terminated if we
|
||||
* get here, as if we were terminated directly by a SIGINT. Arrange for
|
||||
* this here.
|
||||
*/
|
||||
|
||||
void
|
||||
onint() {
|
||||
if (suppressint) {
|
||||
onint(void)
|
||||
{
|
||||
sigset_t sigset;
|
||||
|
||||
/*
|
||||
* The !in_dotrap here is safe. The only way we can arrive here
|
||||
* with in_dotrap set is that a trap handler set SIGINT to SIG_DFL
|
||||
* and killed itself.
|
||||
*/
|
||||
|
||||
if (suppressint && !in_dotrap) {
|
||||
intpending++;
|
||||
return;
|
||||
}
|
||||
intpending = 0;
|
||||
#ifdef BSD
|
||||
sigsetmask(0);
|
||||
sigemptyset(&sigset);
|
||||
sigprocmask(SIG_SETMASK, &sigset, NULL);
|
||||
|
||||
/*
|
||||
* This doesn't seem to be needed, since main() emits a newline.
|
||||
*/
|
||||
#if 0
|
||||
if (tcgetpgrp(0) == getpid())
|
||||
write(STDERR_FILENO, "\n", 1);
|
||||
#endif
|
||||
if (rootshell && iflag)
|
||||
exraise(EXINT);
|
||||
else
|
||||
_exit(128 + SIGINT);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
error2(a, b)
|
||||
char *a, *b;
|
||||
{
|
||||
error("%s: %s", a, b);
|
||||
else {
|
||||
signal(SIGINT, SIG_DFL);
|
||||
kill(getpid(), SIGINT);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Error is called to raise the error exception. If the first argument
|
||||
* Exverror is called to raise the error exception. If the first argument
|
||||
* is not NULL then error prints an error message using printf style
|
||||
* formatting. It then raises the error exception.
|
||||
*/
|
||||
|
||||
#ifdef __STDC__
|
||||
void
|
||||
error(char *msg, ...) {
|
||||
#else
|
||||
void
|
||||
error(va_alist)
|
||||
va_dcl
|
||||
{
|
||||
char *msg;
|
||||
#endif
|
||||
va_list ap;
|
||||
|
||||
static void
|
||||
exverror(int cond, const char *msg, va_list ap)
|
||||
{
|
||||
CLEAR_PENDING_INT;
|
||||
INTOFF;
|
||||
#ifdef __STDC__
|
||||
va_start(ap, msg);
|
||||
#else
|
||||
va_start(ap);
|
||||
msg = va_arg(ap, char *);
|
||||
#endif
|
||||
|
||||
#if DEBUG
|
||||
if (msg)
|
||||
TRACE(("error(\"%s\") pid=%d\n", msg, getpid()));
|
||||
TRACE(("exverror(%d, \"%s\") pid=%d\n", cond, msg, getpid()));
|
||||
else
|
||||
TRACE(("error(NULL) pid=%d\n", getpid()));
|
||||
TRACE(("exverror(%d, NULL) pid=%d\n", cond, getpid()));
|
||||
#endif
|
||||
if (msg) {
|
||||
if (commandname)
|
||||
@@ -157,96 +156,30 @@ error(va_alist)
|
||||
doformat(&errout, msg, ap);
|
||||
out2c('\n');
|
||||
}
|
||||
va_end(ap);
|
||||
flushall();
|
||||
exraise(EXERROR);
|
||||
exraise(cond);
|
||||
}
|
||||
|
||||
|
||||
#ifdef notdef /* These strange error messages only confuse. -- kjb */
|
||||
/*
|
||||
* Table of error messages.
|
||||
*/
|
||||
|
||||
struct errname {
|
||||
short errcode; /* error number */
|
||||
short action; /* operation which encountered the error */
|
||||
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",
|
||||
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",
|
||||
ENOEXEC, ALL, "not an executable",
|
||||
EISDIR, ALL, "is a directory",
|
||||
/* EMFILE, ALL, "too many open files", */
|
||||
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 SYSV
|
||||
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.
|
||||
*/
|
||||
|
||||
char *
|
||||
errmsg(e, action) {
|
||||
const struct errname *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;
|
||||
void
|
||||
error(const char *msg, ...)
|
||||
{
|
||||
va_list ap;
|
||||
va_start(ap, msg);
|
||||
exverror(EXERROR, msg, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
void
|
||||
exerror(int cond, const char *msg, ...)
|
||||
{
|
||||
va_list ap;
|
||||
va_start(ap, msg);
|
||||
exverror(cond, msg, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
/*
|
||||
* $PchId: error.c,v 1.5 2006/04/10 14:36:23 philip Exp $
|
||||
*/
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*-
|
||||
* Copyright (c) 1991 The Regents of the University of California.
|
||||
* All rights reserved.
|
||||
* 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.
|
||||
@@ -13,10 +13,6 @@
|
||||
* 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.
|
||||
@@ -33,41 +29,35 @@
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)error.h 5.1 (Berkeley) 3/7/91
|
||||
* @(#)error.h 8.2 (Berkeley) 5/4/95
|
||||
* $FreeBSD: src/bin/sh/error.h,v 1.17 2004/04/06 20:06:51 markm Exp $
|
||||
*/
|
||||
|
||||
/*
|
||||
* 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
|
||||
* contains a code identifying the exception. 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>
|
||||
#include <signal.h>
|
||||
|
||||
struct jmploc {
|
||||
jmp_buf loc;
|
||||
};
|
||||
|
||||
extern struct jmploc *handler;
|
||||
extern int exception;
|
||||
extern volatile sig_atomic_t exception;
|
||||
|
||||
/* 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 */
|
||||
|
||||
|
||||
/*
|
||||
@@ -77,32 +67,21 @@ extern int exception;
|
||||
* more fun than worrying about efficiency and portability. :-))
|
||||
*/
|
||||
|
||||
extern volatile int suppressint;
|
||||
extern volatile int intpending;
|
||||
extern char *commandname; /* name of command--printed on error */
|
||||
extern volatile sig_atomic_t suppressint;
|
||||
extern volatile sig_atomic_t intpending;
|
||||
|
||||
#define INTOFF suppressint++
|
||||
#define INTON if (--suppressint == 0 && intpending) onint(); else
|
||||
#define INTON { if (--suppressint == 0 && intpending) onint(); }
|
||||
#define FORCEINTON {suppressint = 0; if (intpending) onint();}
|
||||
#define CLEAR_PENDING_INT intpending = 0
|
||||
#define int_pending() intpending
|
||||
|
||||
#ifdef __STDC__
|
||||
#define __printf0like(a,b)
|
||||
|
||||
void exraise(int);
|
||||
void onint(void);
|
||||
void error2(char *, char *);
|
||||
void error(char *, ...);
|
||||
char *errmsg(int, int);
|
||||
#else
|
||||
void exraise();
|
||||
void onint();
|
||||
void error2();
|
||||
void error();
|
||||
char *errmsg();
|
||||
#endif
|
||||
|
||||
/* Errmsg uses confusingly different messages. Prefer strerror(). -- kjb */
|
||||
#define errmsg(errno, action) strerror(errno)
|
||||
void error(const char *, ...) __printf0like(1, 2);
|
||||
void exerror(int, const char *, ...) __printf0like(2, 3);
|
||||
|
||||
|
||||
/*
|
||||
@@ -111,6 +90,12 @@ char *errmsg();
|
||||
*/
|
||||
|
||||
#ifdef BSD
|
||||
#ifndef __minix
|
||||
#define setjmp(jmploc) _setjmp(jmploc)
|
||||
#define longjmp(jmploc, val) _longjmp(jmploc, val)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/*
|
||||
* $PchId: error.h,v 1.5 2006/04/10 14:36:43 philip Exp $
|
||||
*/
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*-
|
||||
* Copyright (c) 1991 The Regents of the University of California.
|
||||
* All rights reserved.
|
||||
* 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.
|
||||
@@ -13,10 +13,6 @@
|
||||
* 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.
|
||||
@@ -35,8 +31,23 @@
|
||||
*/
|
||||
|
||||
#ifndef lint
|
||||
static char sccsid[] = "@(#)eval.c 5.3 (Berkeley) 4/12/91";
|
||||
#if 0
|
||||
static char sccsid[] = "@(#)eval.c 8.9 (Berkeley) 6/8/95";
|
||||
#endif
|
||||
#endif /* not lint */
|
||||
/*
|
||||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD: src/bin/sh/eval.c,v 1.42 2004/04/06 20:06:51 markm Exp $");
|
||||
*/
|
||||
|
||||
#ifndef NO_PATHS_H
|
||||
#include <paths.h>
|
||||
#endif
|
||||
#include <signal.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/wait.h> /* For WIFSIGNALED(status) */
|
||||
#include <errno.h>
|
||||
|
||||
/*
|
||||
* Evaluate a command.
|
||||
@@ -59,22 +70,21 @@ static char sccsid[] = "@(#)eval.c 5.3 (Berkeley) 4/12/91";
|
||||
#include "var.h"
|
||||
#include "memalloc.h"
|
||||
#include "error.h"
|
||||
#include "show.h"
|
||||
#include "mystring.h"
|
||||
#include <sys/types.h>
|
||||
#include <signal.h>
|
||||
#if !defined(NO_HISTORY) && !defined(EDITLINE)
|
||||
#include "myhistedit.h"
|
||||
#endif
|
||||
|
||||
#ifndef _PATH_STDPATH
|
||||
#define _PATH_STDPATH "/usr/bin:/bin:/usr/sbin:/sbin:"
|
||||
#endif
|
||||
|
||||
/* flags in argument to evaltree */
|
||||
#define EV_EXIT 01 /* exit after evaluating tree */
|
||||
#define EV_TESTED 02 /* exit status is checked; ignore -e flag */
|
||||
#define EV_BACKCMD 04 /* command executing within back quotes */
|
||||
|
||||
|
||||
/* reasons for skipping commands (see comment on breakcmd routine) */
|
||||
#define SKIPBREAK 1
|
||||
#define SKIPCONT 2
|
||||
#define SKIPFUNC 3
|
||||
|
||||
MKINIT int evalskip; /* set if we are skipping commands */
|
||||
STATIC int skipcount; /* number of levels to skip */
|
||||
MKINIT int loopnest; /* current loop nesting level */
|
||||
@@ -87,7 +97,6 @@ int exitstatus; /* exit status of last command */
|
||||
int oexitstatus; /* saved exit status */
|
||||
|
||||
|
||||
#ifdef __STDC__
|
||||
STATIC void evalloop(union node *);
|
||||
STATIC void evalfor(union node *);
|
||||
STATIC void evalcase(union node *, int);
|
||||
@@ -96,17 +105,6 @@ STATIC void expredir(union node *);
|
||||
STATIC void evalpipe(union node *);
|
||||
STATIC void evalcommand(union node *, int, struct backcmd *);
|
||||
STATIC void prehash(union node *);
|
||||
#else
|
||||
STATIC void evalloop();
|
||||
STATIC void evalfor();
|
||||
STATIC void evalcase();
|
||||
STATIC void evalsubshell();
|
||||
STATIC void expredir();
|
||||
STATIC void evalpipe();
|
||||
STATIC void evalcommand();
|
||||
STATIC void prehash();
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
/*
|
||||
@@ -130,11 +128,11 @@ SHELLPROC {
|
||||
|
||||
|
||||
/*
|
||||
* The eval commmand.
|
||||
* The eval command.
|
||||
*/
|
||||
|
||||
evalcmd(argc, argv)
|
||||
char **argv;
|
||||
int
|
||||
evalcmd(int argc, char **argv)
|
||||
{
|
||||
char *p;
|
||||
char *concat;
|
||||
@@ -166,9 +164,8 @@ evalcmd(argc, argv)
|
||||
*/
|
||||
|
||||
void
|
||||
evalstring(s)
|
||||
char *s;
|
||||
{
|
||||
evalstring(char *s)
|
||||
{
|
||||
union node *n;
|
||||
struct stackmark smark;
|
||||
|
||||
@@ -190,14 +187,17 @@ evalstring(s)
|
||||
*/
|
||||
|
||||
void
|
||||
evaltree(n, flags)
|
||||
union node *n;
|
||||
{
|
||||
evaltree(union node *n, int flags)
|
||||
{
|
||||
if (n == NULL) {
|
||||
TRACE(("evaltree(NULL) called\n"));
|
||||
return;
|
||||
exitstatus = 0;
|
||||
goto out;
|
||||
}
|
||||
TRACE(("evaltree(0x%x: %d) called\n", (int)n, n->type));
|
||||
#if !defined(NO_HISTORY) && !defined(EDITLINE)
|
||||
displayhist = 1; /* show history substitutions done with fc */
|
||||
#endif
|
||||
TRACE(("evaltree(0x%lx: %d) called\n", (long)n, n->type));
|
||||
switch (n->type) {
|
||||
case NSEMI:
|
||||
evaltree(n->nbinary.ch1, 0);
|
||||
@@ -207,8 +207,9 @@ evaltree(n, flags)
|
||||
break;
|
||||
case NAND:
|
||||
evaltree(n->nbinary.ch1, EV_TESTED);
|
||||
if (evalskip || exitstatus != 0)
|
||||
if (evalskip || exitstatus != 0) {
|
||||
goto out;
|
||||
}
|
||||
evaltree(n->nbinary.ch2, flags);
|
||||
break;
|
||||
case NOR:
|
||||
@@ -230,19 +231,15 @@ evaltree(n, flags)
|
||||
evalsubshell(n, flags);
|
||||
break;
|
||||
case NIF: {
|
||||
int status = 0;
|
||||
|
||||
evaltree(n->nif.test, EV_TESTED);
|
||||
if (evalskip)
|
||||
goto out;
|
||||
if (exitstatus == 0) {
|
||||
if (exitstatus == 0)
|
||||
evaltree(n->nif.ifpart, flags);
|
||||
status = exitstatus;
|
||||
} else if (n->nif.elsepart) {
|
||||
else if (n->nif.elsepart)
|
||||
evaltree(n->nif.elsepart, flags);
|
||||
status = exitstatus;
|
||||
}
|
||||
exitstatus = status;
|
||||
else
|
||||
exitstatus = 0;
|
||||
break;
|
||||
}
|
||||
case NWHILE:
|
||||
@@ -259,6 +256,11 @@ evaltree(n, flags)
|
||||
defun(n->narg.text, n->narg.next);
|
||||
exitstatus = 0;
|
||||
break;
|
||||
case NNOT:
|
||||
evaltree(n->nnot.com, EV_TESTED);
|
||||
exitstatus = !exitstatus;
|
||||
break;
|
||||
|
||||
case NPIPE:
|
||||
evalpipe(n);
|
||||
break;
|
||||
@@ -273,18 +275,16 @@ evaltree(n, flags)
|
||||
out:
|
||||
if (pendingsigs)
|
||||
dotrap();
|
||||
if ((flags & EV_EXIT) || (eflag && exitstatus
|
||||
&& !(flags & EV_TESTED) && (n->type == NCMD ||
|
||||
n->type == NSUBSHELL))) {
|
||||
if ((flags & EV_EXIT) || (eflag && exitstatus
|
||||
&& !(flags & EV_TESTED) && (n->type == NCMD ||
|
||||
n->type == NSUBSHELL)))
|
||||
exitshell(exitstatus);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
STATIC void
|
||||
evalloop(n)
|
||||
union node *n;
|
||||
{
|
||||
evalloop(union node *n)
|
||||
{
|
||||
int status;
|
||||
|
||||
loopnest++;
|
||||
@@ -319,9 +319,8 @@ skipping: if (evalskip == SKIPCONT && --skipcount <= 0) {
|
||||
|
||||
|
||||
STATIC void
|
||||
evalfor(n)
|
||||
union node *n;
|
||||
{
|
||||
evalfor(union node *n)
|
||||
{
|
||||
struct arglist arglist;
|
||||
union node *argp;
|
||||
struct strlist *sp;
|
||||
@@ -331,7 +330,7 @@ evalfor(n)
|
||||
arglist.lastp = &arglist.list;
|
||||
for (argp = n->nfor.args ; argp ; argp = argp->narg.next) {
|
||||
oexitstatus = exitstatus;
|
||||
expandarg(argp, &arglist, 1);
|
||||
expandarg(argp, &arglist, EXP_FULL | EXP_TILDE);
|
||||
if (evalskip)
|
||||
goto out;
|
||||
}
|
||||
@@ -360,9 +359,8 @@ out:
|
||||
|
||||
|
||||
STATIC void
|
||||
evalcase(n, flags)
|
||||
union node *n;
|
||||
{
|
||||
evalcase(union node *n, int flags)
|
||||
{
|
||||
union node *cp;
|
||||
union node *patp;
|
||||
struct arglist arglist;
|
||||
@@ -370,8 +368,8 @@ evalcase(n, flags)
|
||||
|
||||
setstackmark(&smark);
|
||||
arglist.lastp = &arglist.list;
|
||||
oexitstatus = exitstatus;
|
||||
expandarg(n->ncase.expr, &arglist, 0);
|
||||
oexitstatus = exitstatus;
|
||||
expandarg(n->ncase.expr, &arglist, EXP_TILDE);
|
||||
for (cp = n->ncase.cases ; cp && evalskip == 0 ; cp = cp->nclist.next) {
|
||||
for (patp = cp->nclist.pattern ; patp ; patp = patp->narg.next) {
|
||||
if (casematch(patp, arglist.list->text)) {
|
||||
@@ -393,9 +391,8 @@ out:
|
||||
*/
|
||||
|
||||
STATIC void
|
||||
evalsubshell(n, flags)
|
||||
union node *n;
|
||||
{
|
||||
evalsubshell(union node *n, int flags)
|
||||
{
|
||||
struct job *jp;
|
||||
int backgnd = (n->type == NBACKGND);
|
||||
|
||||
@@ -409,7 +406,7 @@ evalsubshell(n, flags)
|
||||
}
|
||||
if (! backgnd) {
|
||||
INTOFF;
|
||||
exitstatus = waitforjob(jp);
|
||||
exitstatus = waitforjob(jp, (int *)NULL);
|
||||
INTON;
|
||||
}
|
||||
}
|
||||
@@ -421,20 +418,30 @@ evalsubshell(n, flags)
|
||||
*/
|
||||
|
||||
STATIC void
|
||||
expredir(n)
|
||||
union node *n;
|
||||
{
|
||||
register union node *redir;
|
||||
expredir(union node *n)
|
||||
{
|
||||
union node *redir;
|
||||
|
||||
for (redir = n ; redir ; redir = redir->nfile.next) {
|
||||
struct arglist fn;
|
||||
fn.lastp = &fn.list;
|
||||
oexitstatus = exitstatus;
|
||||
if (redir->type == NFROM
|
||||
|| redir->type == NTO
|
||||
|| redir->type == NAPPEND) {
|
||||
struct arglist fn;
|
||||
fn.lastp = &fn.list;
|
||||
expandarg(redir->nfile.fname, &fn, 0);
|
||||
switch (redir->type) {
|
||||
case NFROM:
|
||||
case NTO:
|
||||
case NFROMTO:
|
||||
case NAPPEND:
|
||||
case NCLOBBER:
|
||||
expandarg(redir->nfile.fname, &fn, EXP_TILDE | EXP_REDIR);
|
||||
redir->nfile.expfname = fn.list->text;
|
||||
break;
|
||||
case NFROMFD:
|
||||
case NTOFD:
|
||||
if (redir->ndup.vname) {
|
||||
expandarg(redir->ndup.vname, &fn, EXP_FULL | EXP_TILDE);
|
||||
fixredir(redir, fn.list->text, 1);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -449,16 +456,15 @@ expredir(n)
|
||||
*/
|
||||
|
||||
STATIC void
|
||||
evalpipe(n)
|
||||
union node *n;
|
||||
{
|
||||
evalpipe(union node *n)
|
||||
{
|
||||
struct job *jp;
|
||||
struct nodelist *lp;
|
||||
int pipelen;
|
||||
int prevfd;
|
||||
int pip[2];
|
||||
|
||||
TRACE(("evalpipe(0x%x) called\n", (int)n));
|
||||
TRACE(("evalpipe(0x%lx) called\n", (long)n));
|
||||
pipelen = 0;
|
||||
for (lp = n->npipe.cmdlist ; lp ; lp = lp->next)
|
||||
pipelen++;
|
||||
@@ -471,21 +477,20 @@ evalpipe(n)
|
||||
if (lp->next) {
|
||||
if (pipe(pip) < 0) {
|
||||
close(prevfd);
|
||||
error("Pipe call failed");
|
||||
error("Pipe call failed: %s", strerror(errno));
|
||||
}
|
||||
}
|
||||
if (forkshell(jp, lp->n, n->npipe.backgnd) == 0) {
|
||||
INTON;
|
||||
if (prevfd > 0) {
|
||||
close(0);
|
||||
copyfd(prevfd, 0);
|
||||
dup2(prevfd, 0);
|
||||
close(prevfd);
|
||||
}
|
||||
if (pip[1] >= 0) {
|
||||
close(pip[0]);
|
||||
if (!(prevfd >= 0 && pip[0] == 0))
|
||||
close(pip[0]);
|
||||
if (pip[1] != 1) {
|
||||
close(1);
|
||||
copyfd(pip[1], 1);
|
||||
dup2(pip[1], 1);
|
||||
close(pip[1]);
|
||||
}
|
||||
}
|
||||
@@ -499,7 +504,7 @@ evalpipe(n)
|
||||
INTON;
|
||||
if (n->npipe.backgnd == 0) {
|
||||
INTOFF;
|
||||
exitstatus = waitforjob(jp);
|
||||
exitstatus = waitforjob(jp, (int *)NULL);
|
||||
TRACE(("evalpipe: job done exit status %d\n", exitstatus));
|
||||
INTON;
|
||||
}
|
||||
@@ -515,10 +520,8 @@ evalpipe(n)
|
||||
*/
|
||||
|
||||
void
|
||||
evalbackcmd(n, result)
|
||||
union node *n;
|
||||
struct backcmd *result;
|
||||
{
|
||||
evalbackcmd(union node *n, struct backcmd *result)
|
||||
{
|
||||
int pip[2];
|
||||
struct job *jp;
|
||||
struct stackmark smark; /* unnecessary */
|
||||
@@ -529,21 +532,22 @@ evalbackcmd(n, result)
|
||||
result->nleft = 0;
|
||||
result->jp = NULL;
|
||||
if (n == NULL) {
|
||||
/* `` */
|
||||
} else
|
||||
exitstatus = 0;
|
||||
goto out;
|
||||
}
|
||||
if (n->type == NCMD) {
|
||||
exitstatus = oexitstatus;
|
||||
exitstatus = oexitstatus;
|
||||
evalcommand(n, EV_BACKCMD, result);
|
||||
} else {
|
||||
exitstatus = 0;
|
||||
if (pipe(pip) < 0)
|
||||
error("Pipe call failed");
|
||||
error("Pipe call failed: %s", strerror(errno));
|
||||
jp = makejob(n, 1);
|
||||
if (forkshell(jp, n, FORK_NOJOB) == 0) {
|
||||
FORCEINTON;
|
||||
close(pip[0]);
|
||||
if (pip[1] != 1) {
|
||||
close(1);
|
||||
copyfd(pip[1], 1);
|
||||
dup2(pip[1], 1);
|
||||
close(pip[1]);
|
||||
}
|
||||
evaltree(n, EV_EXIT);
|
||||
@@ -552,8 +556,9 @@ evalbackcmd(n, result)
|
||||
result->fd = pip[0];
|
||||
result->jp = jp;
|
||||
}
|
||||
out:
|
||||
popstackmark(&smark);
|
||||
TRACE(("evalbackcmd done: fd=%d buf=0x%x nleft=%d jp=0x%x\n",
|
||||
TRACE(("evalbackcmd done: fd=%d buf=%p nleft=%d jp=%p\n",
|
||||
result->fd, result->buf, result->nleft, result->jp));
|
||||
}
|
||||
|
||||
@@ -564,10 +569,8 @@ evalbackcmd(n, result)
|
||||
*/
|
||||
|
||||
STATIC void
|
||||
evalcommand(cmd, flags, backcmd)
|
||||
union node *cmd;
|
||||
struct backcmd *backcmd;
|
||||
{
|
||||
evalcommand(union node *cmd, int flags, struct backcmd *backcmd)
|
||||
{
|
||||
struct stackmark smark;
|
||||
union node *argp;
|
||||
struct arglist arglist;
|
||||
@@ -577,7 +580,6 @@ evalcommand(cmd, flags, backcmd)
|
||||
char **envp;
|
||||
int varflag;
|
||||
struct strlist *sp;
|
||||
register char *p;
|
||||
int mode;
|
||||
int pip[2];
|
||||
struct cmdentry cmdentry;
|
||||
@@ -589,27 +591,38 @@ evalcommand(cmd, flags, backcmd)
|
||||
struct localvar *volatile savelocalvars;
|
||||
volatile int e;
|
||||
char *lastarg;
|
||||
int realstatus;
|
||||
int do_clearcmdentry;
|
||||
#if __GNUC__
|
||||
/* Avoid longjmp clobbering */
|
||||
(void) &argv;
|
||||
(void) &argc;
|
||||
(void) &lastarg;
|
||||
(void) &flags;
|
||||
(void) &do_clearcmdentry;
|
||||
#endif
|
||||
|
||||
/* First expand the arguments. */
|
||||
TRACE(("evalcommand(0x%x, %d) called\n", (int)cmd, flags));
|
||||
TRACE(("evalcommand(0x%lx, %d) called\n", (long)cmd, flags));
|
||||
setstackmark(&smark);
|
||||
arglist.lastp = &arglist.list;
|
||||
varlist.lastp = &varlist.list;
|
||||
varflag = 1;
|
||||
oexitstatus = exitstatus;
|
||||
do_clearcmdentry = 0;
|
||||
oexitstatus = exitstatus;
|
||||
exitstatus = 0;
|
||||
for (argp = cmd->ncmd.args ; argp ; argp = argp->narg.next) {
|
||||
p = argp->narg.text;
|
||||
char *p = argp->narg.text;
|
||||
if (varflag && is_name(*p)) {
|
||||
do {
|
||||
p++;
|
||||
} while (is_in_name(*p));
|
||||
if (*p == '=') {
|
||||
expandarg(argp, &varlist, 0);
|
||||
expandarg(argp, &varlist, EXP_VARTILDE);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
expandarg(argp, &arglist, 1);
|
||||
expandarg(argp, &arglist, EXP_FULL | EXP_TILDE);
|
||||
varflag = 0;
|
||||
}
|
||||
*arglist.lastp = NULL;
|
||||
@@ -619,8 +632,11 @@ evalcommand(cmd, flags, backcmd)
|
||||
for (sp = arglist.list ; sp ; sp = sp->next)
|
||||
argc++;
|
||||
argv = stalloc(sizeof (char *) * (argc + 1));
|
||||
for (sp = arglist.list ; sp ; sp = sp->next)
|
||||
|
||||
for (sp = arglist.list ; sp ; sp = sp->next) {
|
||||
TRACE(("evalcommand arg: %s\n", sp->text));
|
||||
*argv++ = sp->text;
|
||||
}
|
||||
*argv = NULL;
|
||||
lastarg = NULL;
|
||||
if (iflag && funcnest == 0 && argc > 0)
|
||||
@@ -628,7 +644,7 @@ evalcommand(cmd, flags, backcmd)
|
||||
argv -= argc;
|
||||
|
||||
/* Print the command if xflag is set. */
|
||||
if (xflag == 1) {
|
||||
if (xflag) {
|
||||
outc('+', &errout);
|
||||
for (sp = varlist.list ; sp ; sp = sp->next) {
|
||||
outc(' ', &errout);
|
||||
@@ -647,11 +663,42 @@ evalcommand(cmd, flags, backcmd)
|
||||
cmdentry.cmdtype = CMDBUILTIN;
|
||||
cmdentry.u.index = BLTINCMD;
|
||||
} else {
|
||||
find_command(argv[0], &cmdentry, 1);
|
||||
static const char PATH[] = "PATH=";
|
||||
char *path = pathval();
|
||||
|
||||
/*
|
||||
* Modify the command lookup path, if a PATH= assignment
|
||||
* is present
|
||||
*/
|
||||
for (sp = varlist.list ; sp ; sp = sp->next)
|
||||
if (strncmp(sp->text, PATH, sizeof(PATH) - 1) == 0) {
|
||||
path = sp->text + sizeof(PATH) - 1;
|
||||
/*
|
||||
* On `PATH=... command`, we need to make
|
||||
* sure that the command isn't using the
|
||||
* non-updated hash table of the outer PATH
|
||||
* setting and we need to make sure that
|
||||
* the hash table isn't filled with items
|
||||
* from the temporary setting.
|
||||
*
|
||||
* It would be better to forbit using and
|
||||
* updating the table while this command
|
||||
* runs, by the command finding mechanism
|
||||
* is heavily integrated with hash handling,
|
||||
* so we just delete the hash before and after
|
||||
* the command runs. Partly deleting like
|
||||
* changepatch() does doesn't seem worth the
|
||||
* bookinging effort, since most such runs add
|
||||
* directories in front of the new PATH.
|
||||
*/
|
||||
clearcmdentry(0);
|
||||
do_clearcmdentry = 1;
|
||||
}
|
||||
|
||||
find_command(argv[0], &cmdentry, 1, path);
|
||||
if (cmdentry.cmdtype == CMDUNKNOWN) { /* command not found */
|
||||
exitstatus = 2;
|
||||
exitstatus = 127;
|
||||
flushout(&errout);
|
||||
popstackmark(&smark);
|
||||
return;
|
||||
}
|
||||
/* implement the bltin builtin here */
|
||||
@@ -662,9 +709,8 @@ evalcommand(cmd, flags, backcmd)
|
||||
break;
|
||||
if ((cmdentry.u.index = find_builtin(*argv)) < 0) {
|
||||
outfmt(&errout, "%s: not found\n", *argv);
|
||||
exitstatus = 2;
|
||||
exitstatus = 127;
|
||||
flushout(&errout);
|
||||
popstackmark(&smark);
|
||||
return;
|
||||
}
|
||||
if (cmdentry.u.index != BLTINCMD)
|
||||
@@ -675,17 +721,21 @@ evalcommand(cmd, flags, backcmd)
|
||||
|
||||
/* Fork off a child process if necessary. */
|
||||
if (cmd->ncmd.backgnd
|
||||
|| cmdentry.cmdtype == CMDNORMAL && (flags & EV_EXIT) == 0
|
||||
|| (flags & EV_BACKCMD) != 0
|
||||
|| (cmdentry.cmdtype == CMDNORMAL
|
||||
&& ((flags & EV_EXIT) == 0 || Tflag))
|
||||
|| ((flags & EV_BACKCMD) != 0
|
||||
&& (cmdentry.cmdtype != CMDBUILTIN
|
||||
|| cmdentry.u.index == CDCMD
|
||||
|| cmdentry.u.index == DOTCMD
|
||||
|| cmdentry.u.index == EVALCMD)) {
|
||||
|| cmdentry.u.index == EVALCMD))
|
||||
|| (cmdentry.cmdtype == CMDBUILTIN &&
|
||||
cmdentry.u.index == COMMANDCMD)) {
|
||||
jp = makejob(cmd, 1);
|
||||
mode = cmd->ncmd.backgnd;
|
||||
if (flags & EV_BACKCMD) {
|
||||
mode = FORK_NOJOB;
|
||||
if (pipe(pip) < 0)
|
||||
error("Pipe call failed");
|
||||
error("Pipe call failed: %s", strerror(errno));
|
||||
}
|
||||
if (forkshell(jp, cmd, mode) != 0)
|
||||
goto parent; /* at end of routine */
|
||||
@@ -693,8 +743,7 @@ evalcommand(cmd, flags, backcmd)
|
||||
FORCEINTON;
|
||||
close(pip[0]);
|
||||
if (pip[1] != 1) {
|
||||
close(1);
|
||||
copyfd(pip[1], 1);
|
||||
dup2(pip[1], 1);
|
||||
close(pip[1]);
|
||||
}
|
||||
}
|
||||
@@ -704,10 +753,13 @@ evalcommand(cmd, flags, backcmd)
|
||||
/* This is the child process if a fork occurred. */
|
||||
/* Execute the command. */
|
||||
if (cmdentry.cmdtype == CMDFUNCTION) {
|
||||
#if DEBUG
|
||||
trputs("Shell function: "); trargs(argv);
|
||||
#endif
|
||||
redirect(cmd->ncmd.redirect, REDIR_PUSH);
|
||||
saveparam = shellparam;
|
||||
shellparam.malloc = 0;
|
||||
shellparam.reset = 1;
|
||||
shellparam.nparam = argc - 1;
|
||||
shellparam.p = argv + 1;
|
||||
shellparam.optnext = NULL;
|
||||
@@ -752,7 +804,9 @@ evalcommand(cmd, flags, backcmd)
|
||||
if (flags & EV_EXIT)
|
||||
exitshell(exitstatus);
|
||||
} else if (cmdentry.cmdtype == CMDBUILTIN) {
|
||||
#if DEBUG
|
||||
trputs("builtin command: "); trargs(argv);
|
||||
#endif
|
||||
mode = (cmdentry.u.index == EXECCMD)? 0 : REDIR_PUSH;
|
||||
if (flags == EV_BACKCMD) {
|
||||
memout.nleft = 0;
|
||||
@@ -777,6 +831,7 @@ evalcommand(cmd, flags, backcmd)
|
||||
exitstatus = (*builtinfunc[cmdentry.u.index])(argc, argv);
|
||||
flushall();
|
||||
cmddone:
|
||||
cmdenviron = NULL;
|
||||
out1 = &output;
|
||||
out2 = &errout;
|
||||
freestdout();
|
||||
@@ -788,10 +843,15 @@ cmddone:
|
||||
}
|
||||
handler = savehandler;
|
||||
if (e != -1) {
|
||||
if (e != EXERROR || cmdentry.u.index == BLTINCMD
|
||||
|| cmdentry.u.index == DOTCMD
|
||||
|| cmdentry.u.index == EVALCMD
|
||||
|| cmdentry.u.index == EXECCMD)
|
||||
if ((e != EXERROR && e != EXEXEC)
|
||||
|| cmdentry.u.index == BLTINCMD
|
||||
|| cmdentry.u.index == DOTCMD
|
||||
|| cmdentry.u.index == EVALCMD
|
||||
#ifndef NO_HISTORY
|
||||
|| cmdentry.u.index == HISTCMD
|
||||
#endif
|
||||
|| cmdentry.u.index == EXECCMD
|
||||
|| cmdentry.u.index == COMMANDCMD)
|
||||
exraise(e);
|
||||
FORCEINTON;
|
||||
}
|
||||
@@ -803,19 +863,15 @@ cmddone:
|
||||
memout.buf = NULL;
|
||||
}
|
||||
} else {
|
||||
#if DEBUG
|
||||
trputs("normal command: "); trargs(argv);
|
||||
#endif
|
||||
clearredir();
|
||||
redirect(cmd->ncmd.redirect, 0);
|
||||
if (varlist.list) {
|
||||
p = stalloc(strlen(pathval()) + 1);
|
||||
scopy(pathval(), p);
|
||||
} else {
|
||||
p = pathval();
|
||||
}
|
||||
for (sp = varlist.list ; sp ; sp = sp->next)
|
||||
setvareq(sp->text, VEXPORT|VSTACK);
|
||||
envp = environment();
|
||||
shellexec(argv, envp, p, cmdentry.u.index);
|
||||
shellexec(argv, envp, pathval(), cmdentry.u.index);
|
||||
/*NOTREACHED*/
|
||||
}
|
||||
goto out;
|
||||
@@ -823,8 +879,12 @@ cmddone:
|
||||
parent: /* parent process gets here (if we forked) */
|
||||
if (mode == 0) { /* argument to fork */
|
||||
INTOFF;
|
||||
exitstatus = waitforjob(jp);
|
||||
exitstatus = waitforjob(jp, &realstatus);
|
||||
INTON;
|
||||
if (iflag && loopnest > 0 && WIFSIGNALED(realstatus)) {
|
||||
evalskip = SKIPBREAK;
|
||||
skipcount = loopnest;
|
||||
}
|
||||
} else if (mode == 2) {
|
||||
backcmd->fd = pip[0];
|
||||
close(pip[1]);
|
||||
@@ -834,6 +894,8 @@ parent: /* parent process gets here (if we forked) */
|
||||
out:
|
||||
if (lastarg)
|
||||
setvar("_", lastarg, 0);
|
||||
if (do_clearcmdentry)
|
||||
clearcmdentry(0);
|
||||
popstackmark(&smark);
|
||||
}
|
||||
|
||||
@@ -847,13 +909,14 @@ out:
|
||||
*/
|
||||
|
||||
STATIC void
|
||||
prehash(n)
|
||||
union node *n;
|
||||
{
|
||||
prehash(union node *n)
|
||||
{
|
||||
struct cmdentry entry;
|
||||
|
||||
if (n->type == NCMD && goodname(n->ncmd.args->narg.text))
|
||||
find_command(n->ncmd.args->narg.text, &entry, 0);
|
||||
if (n->type == NCMD && n->ncmd.args)
|
||||
if (goodname(n->ncmd.args->narg.text))
|
||||
find_command(n->ncmd.args->narg.text, &entry, 0,
|
||||
pathval());
|
||||
}
|
||||
|
||||
|
||||
@@ -868,8 +931,14 @@ prehash(n)
|
||||
* specified variables.
|
||||
*/
|
||||
|
||||
bltincmd(argc, argv) char **argv; {
|
||||
int
|
||||
bltincmd(int argc __unused, char **argv __unused)
|
||||
{
|
||||
listsetvar(cmdenviron);
|
||||
/*
|
||||
* Preserve exitstatus of a previous possible redirection
|
||||
* as POSIX mandates
|
||||
*/
|
||||
return exitstatus;
|
||||
}
|
||||
|
||||
@@ -885,12 +954,11 @@ bltincmd(argc, argv) char **argv; {
|
||||
* in the standard shell so we don't make it one here.
|
||||
*/
|
||||
|
||||
breakcmd(argc, argv) char **argv; {
|
||||
int n;
|
||||
int
|
||||
breakcmd(int argc, char **argv)
|
||||
{
|
||||
int n = argc > 1 ? number(argv[1]) : 1;
|
||||
|
||||
n = 1;
|
||||
if (argc > 1)
|
||||
n = number(argv[1]);
|
||||
if (n > loopnest)
|
||||
n = loopnest;
|
||||
if (n > 0) {
|
||||
@@ -900,40 +968,108 @@ breakcmd(argc, argv) char **argv; {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* The `command' command.
|
||||
*/
|
||||
int
|
||||
commandcmd(int argc, char **argv)
|
||||
{
|
||||
static char stdpath[] = _PATH_STDPATH;
|
||||
struct jmploc loc, *old;
|
||||
struct strlist *sp;
|
||||
char *path;
|
||||
int ch;
|
||||
|
||||
for (sp = cmdenviron; sp ; sp = sp->next)
|
||||
setvareq(sp->text, VEXPORT|VSTACK);
|
||||
path = pathval();
|
||||
|
||||
optind = optreset = 1;
|
||||
opterr = 0;
|
||||
while ((ch = getopt(argc, argv, "p")) != -1) {
|
||||
switch (ch) {
|
||||
case 'p':
|
||||
path = stdpath;
|
||||
break;
|
||||
case '?':
|
||||
default:
|
||||
error("unknown option: -%c", optopt);
|
||||
}
|
||||
}
|
||||
argc -= optind;
|
||||
argv += optind;
|
||||
|
||||
if (argc != 0) {
|
||||
old = handler;
|
||||
handler = &loc;
|
||||
if (setjmp(handler->loc) == 0)
|
||||
shellexec(argv, environment(), path, 0);
|
||||
handler = old;
|
||||
if (exception == EXEXEC)
|
||||
exit(exerrno);
|
||||
exraise(exception);
|
||||
}
|
||||
|
||||
/*
|
||||
* Do nothing successfully if no command was specified;
|
||||
* ksh also does this.
|
||||
*/
|
||||
exit(0);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* The return command.
|
||||
*/
|
||||
|
||||
returncmd(argc, argv) char **argv; {
|
||||
int ret;
|
||||
int
|
||||
returncmd(int argc, char **argv)
|
||||
{
|
||||
int ret = argc > 1 ? number(argv[1]) : oexitstatus;
|
||||
|
||||
ret = oexitstatus;
|
||||
if (argc > 1)
|
||||
ret = number(argv[1]);
|
||||
if (funcnest) {
|
||||
evalskip = SKIPFUNC;
|
||||
skipcount = 1;
|
||||
} else {
|
||||
/* skip the rest of the file */
|
||||
evalskip = SKIPFILE;
|
||||
skipcount = 1;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
truecmd(argc, argv) char **argv; {
|
||||
return strcmp(argv[0], "false") == 0 ? 1 : 0;
|
||||
int
|
||||
falsecmd(int argc __unused, char **argv __unused)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
execcmd(argc, argv) char **argv; {
|
||||
int
|
||||
truecmd(int argc __unused, char **argv __unused)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
execcmd(int argc, char **argv)
|
||||
{
|
||||
if (argc > 1) {
|
||||
struct strlist *sp;
|
||||
|
||||
iflag = 0; /* exit on error */
|
||||
setinteractive(0);
|
||||
#if JOBS
|
||||
jflag = 0;
|
||||
setjobctl(0);
|
||||
#endif
|
||||
mflag = 0;
|
||||
optschanged();
|
||||
for (sp = cmdenviron; sp ; sp = sp->next)
|
||||
setvareq(sp->text, VEXPORT|VSTACK);
|
||||
shellexec(argv + 1, environment(), pathval(), 0);
|
||||
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* $PchId: eval.c,v 1.7 2006/04/10 14:46:14 philip Exp $
|
||||
*/
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*-
|
||||
* Copyright (c) 1991 The Regents of the University of California.
|
||||
* All rights reserved.
|
||||
* 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.
|
||||
@@ -13,10 +13,6 @@
|
||||
* 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.
|
||||
@@ -33,7 +29,8 @@
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)eval.h 5.2 (Berkeley) 4/12/91
|
||||
* @(#)eval.h 8.2 (Berkeley) 5/4/95
|
||||
* $FreeBSD: src/bin/sh/eval.h,v 1.10 2004/04/06 20:06:51 markm Exp $
|
||||
*/
|
||||
|
||||
extern char *commandname; /* currently executing command */
|
||||
@@ -48,18 +45,30 @@ struct backcmd { /* result of evalbackcmd */
|
||||
struct job *jp; /* job structure for command */
|
||||
};
|
||||
|
||||
|
||||
#ifdef __STDC__
|
||||
int evalcmd(int, char **);
|
||||
void evalstring(char *);
|
||||
union node; /* BLETCH for ansi C */
|
||||
void evaltree(union node *, int);
|
||||
void evalbackcmd(union node *, struct backcmd *);
|
||||
#else
|
||||
void evalstring();
|
||||
void evaltree();
|
||||
void evalbackcmd();
|
||||
#endif
|
||||
int bltincmd(int, char **);
|
||||
int breakcmd(int, char **);
|
||||
int returncmd(int, char **);
|
||||
int falsecmd(int, char **);
|
||||
int truecmd(int, char **);
|
||||
int execcmd(int, char **);
|
||||
int commandcmd(int, char **);
|
||||
|
||||
/* 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
|
||||
|
||||
/*
|
||||
* $PchId: eval.h,v 1.3 2006/03/30 15:39:25 philip Exp $
|
||||
*/
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*-
|
||||
* Copyright (c) 1991 The Regents of the University of California.
|
||||
* All rights reserved.
|
||||
* 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.
|
||||
@@ -13,10 +13,6 @@
|
||||
* 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.
|
||||
@@ -35,8 +31,21 @@
|
||||
*/
|
||||
|
||||
#ifndef lint
|
||||
static char sccsid[] = "@(#)exec.c 5.2 (Berkeley) 3/13/91";
|
||||
#if 0
|
||||
static char sccsid[] = "@(#)exec.c 8.4 (Berkeley) 6/8/95";
|
||||
#endif
|
||||
#endif /* not lint */
|
||||
/*
|
||||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD: src/bin/sh/exec.c,v 1.24.2.1 2004/09/30 04:41:55 des Exp $");
|
||||
*/
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <errno.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
/*
|
||||
* When commands are first encountered, they are entered in a hash table.
|
||||
@@ -64,11 +73,9 @@ static char sccsid[] = "@(#)exec.c 5.2 (Berkeley) 3/13/91";
|
||||
#include "error.h"
|
||||
#include "init.h"
|
||||
#include "mystring.h"
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#include <errno.h>
|
||||
#include <limits.h>
|
||||
#include "show.h"
|
||||
#include "jobs.h"
|
||||
#include "alias.h"
|
||||
|
||||
|
||||
#define CMDTABLESIZE 31 /* should be prime */
|
||||
@@ -87,23 +94,14 @@ struct tblentry {
|
||||
|
||||
STATIC struct tblentry *cmdtable[CMDTABLESIZE];
|
||||
STATIC int builtinloc = -1; /* index in path of %builtin, or -1 */
|
||||
int exerrno = 0; /* Last exec error */
|
||||
|
||||
|
||||
#ifdef __STDC__
|
||||
STATIC void tryexec(char *, char **, char **);
|
||||
STATIC void execinterp(char **, char **);
|
||||
STATIC void printentry(struct tblentry *);
|
||||
STATIC void clearcmdentry(int);
|
||||
STATIC void printentry(struct tblentry *, int);
|
||||
STATIC struct tblentry *cmdlookup(char *, int);
|
||||
STATIC void delete_cmd_entry(void);
|
||||
#else
|
||||
STATIC void tryexec();
|
||||
STATIC void execinterp();
|
||||
STATIC void printentry();
|
||||
STATIC void clearcmdentry();
|
||||
STATIC struct tblentry *cmdlookup();
|
||||
STATIC void delete_cmd_entry();
|
||||
#endif
|
||||
STATIC void addcmdentry(char *, struct cmdentry *);
|
||||
|
||||
|
||||
|
||||
@@ -113,10 +111,8 @@ STATIC void delete_cmd_entry();
|
||||
*/
|
||||
|
||||
void
|
||||
shellexec(argv, envp, path, index)
|
||||
char **argv, **envp;
|
||||
char *path;
|
||||
{
|
||||
shellexec(char **argv, char **envp, char *path, int index)
|
||||
{
|
||||
char *cmdname;
|
||||
int e;
|
||||
|
||||
@@ -134,40 +130,37 @@ shellexec(argv, envp, path, index)
|
||||
stunalloc(cmdname);
|
||||
}
|
||||
}
|
||||
error2(argv[0], errmsg(e, E_EXEC));
|
||||
|
||||
/* Map to POSIX errors */
|
||||
switch (e) {
|
||||
case EACCES:
|
||||
exerrno = 126;
|
||||
break;
|
||||
case ENOENT:
|
||||
exerrno = 127;
|
||||
break;
|
||||
default:
|
||||
exerrno = 2;
|
||||
break;
|
||||
}
|
||||
if (e == ENOENT || e == ENOTDIR)
|
||||
exerror(EXEXEC, "%s: not found", argv[0]);
|
||||
exerror(EXEXEC, "%s: %s", argv[0], strerror(e));
|
||||
}
|
||||
|
||||
|
||||
STATIC void
|
||||
tryexec(cmd, argv, envp)
|
||||
char *cmd;
|
||||
char **argv;
|
||||
char **envp;
|
||||
{
|
||||
tryexec(char *cmd, char **argv, char **envp)
|
||||
{
|
||||
int e;
|
||||
char *p;
|
||||
|
||||
#ifdef SYSV
|
||||
do {
|
||||
execve(cmd, argv, envp);
|
||||
} while (errno == EINTR);
|
||||
#else
|
||||
execve(cmd, argv, envp);
|
||||
#endif
|
||||
#if HASHBANG
|
||||
#if !__minix_vmd
|
||||
e = errno;
|
||||
if (e == ENOEXEC) {
|
||||
initshellproc();
|
||||
setinputfile(cmd, 0);
|
||||
commandname = arg0 = savestr(argv[0]);
|
||||
#ifndef BSD
|
||||
pgetc(); pungetc(); /* fill up input buffer */
|
||||
p = parsenextc;
|
||||
if (parsenleft > 2 && p[0] == '#' && p[1] == '!') {
|
||||
argv[0] = cmd;
|
||||
execinterp(argv, envp);
|
||||
}
|
||||
#endif
|
||||
setparam(argv + 1);
|
||||
exraise(EXSHELLPROC);
|
||||
/*NOTREACHED*/
|
||||
@@ -176,88 +169,6 @@ tryexec(cmd, argv, envp)
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
#if !defined(BSD) && HASHBANG
|
||||
/*
|
||||
* Execute an interpreter introduced by "#!", for systems where this
|
||||
* feature has not been built into the kernel. If the interpreter is
|
||||
* the shell, return (effectively ignoring the "#!"). If the execution
|
||||
* of the interpreter fails, exit.
|
||||
*
|
||||
* This code peeks inside the input buffer in order to avoid actually
|
||||
* reading any input. It would benefit from a rewrite.
|
||||
*/
|
||||
|
||||
#define NEWARGS 5
|
||||
|
||||
STATIC void
|
||||
execinterp(argv, envp)
|
||||
char **argv, **envp;
|
||||
{
|
||||
int n;
|
||||
char *inp;
|
||||
char *outp;
|
||||
char c;
|
||||
char *p;
|
||||
char **ap;
|
||||
char *newargs[NEWARGS];
|
||||
int i;
|
||||
char **ap2;
|
||||
char **new;
|
||||
|
||||
n = parsenleft - 2;
|
||||
inp = parsenextc + 2;
|
||||
ap = newargs;
|
||||
for (;;) {
|
||||
while (--n >= 0 && (*inp == ' ' || *inp == '\t'))
|
||||
inp++;
|
||||
if (n < 0)
|
||||
goto bad;
|
||||
if ((c = *inp++) == '\n')
|
||||
break;
|
||||
if (ap == &newargs[NEWARGS])
|
||||
bad: error("Bad #! line");
|
||||
STARTSTACKSTR(outp);
|
||||
do {
|
||||
STPUTC(c, outp);
|
||||
} while (--n >= 0 && (c = *inp++) != ' ' && c != '\t' && c != '\n');
|
||||
STPUTC('\0', outp);
|
||||
n++, inp--;
|
||||
*ap++ = grabstackstr(outp);
|
||||
}
|
||||
#if !__minix
|
||||
if (ap == newargs + 1) { /* if no args, maybe no exec is needed */
|
||||
p = newargs[0];
|
||||
for (;;) {
|
||||
if (equal(p, "sh") || equal(p, "ash")) {
|
||||
return;
|
||||
}
|
||||
while (*p != '/') {
|
||||
if (*p == '\0')
|
||||
goto break2;
|
||||
p++;
|
||||
}
|
||||
p++;
|
||||
}
|
||||
break2:;
|
||||
}
|
||||
#endif
|
||||
i = (char *)ap - (char *)newargs; /* size in bytes */
|
||||
if (i == 0)
|
||||
error("Bad #! line");
|
||||
for (ap2 = argv ; *ap2++ != NULL ; );
|
||||
new = ckmalloc(i + ((char *)ap2 - (char *)argv));
|
||||
ap = newargs, ap2 = new;
|
||||
while ((i -= sizeof (char **)) >= 0)
|
||||
*ap2++ = *ap++;
|
||||
ap = argv;
|
||||
while (*ap2++ = *ap++);
|
||||
shellexec(new, envp, pathval(), 0);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Do a path search. The variable path (passed by reference) should be
|
||||
* set to the start of the path before the first call; padvance will update
|
||||
@@ -271,11 +182,9 @@ break2:;
|
||||
char *pathopt;
|
||||
|
||||
char *
|
||||
padvance(path, name)
|
||||
char **path;
|
||||
char *name;
|
||||
{
|
||||
register char *p, *q;
|
||||
padvance(char **path, char *name)
|
||||
{
|
||||
char *p, *q;
|
||||
char *start;
|
||||
int len;
|
||||
|
||||
@@ -288,7 +197,7 @@ padvance(path, name)
|
||||
growstackblock();
|
||||
q = stackblock();
|
||||
if (p != start) {
|
||||
bcopy(start, q, p - start);
|
||||
memcpy(q, start, p - start);
|
||||
q += p - start;
|
||||
*q++ = '/';
|
||||
}
|
||||
@@ -310,7 +219,9 @@ padvance(path, name)
|
||||
/*** Command hashing code ***/
|
||||
|
||||
|
||||
hashcmd(argc, argv) char **argv; {
|
||||
int
|
||||
hashcmd(int argc __unused, char **argv __unused)
|
||||
{
|
||||
struct tblentry **pp;
|
||||
struct tblentry *cmdp;
|
||||
int c;
|
||||
@@ -318,14 +229,6 @@ hashcmd(argc, argv) char **argv; {
|
||||
struct cmdentry entry;
|
||||
char *name;
|
||||
|
||||
if (argc <= 1) {
|
||||
for (pp = cmdtable ; pp < &cmdtable[CMDTABLESIZE] ; pp++) {
|
||||
for (cmdp = *pp ; cmdp ; cmdp = cmdp->next) {
|
||||
printentry(cmdp);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
verbose = 0;
|
||||
while ((c = nextopt("rv")) != '\0') {
|
||||
if (c == 'r') {
|
||||
@@ -334,16 +237,28 @@ hashcmd(argc, argv) char **argv; {
|
||||
verbose++;
|
||||
}
|
||||
}
|
||||
if (*argptr == NULL) {
|
||||
for (pp = cmdtable ; pp < &cmdtable[CMDTABLESIZE] ; pp++) {
|
||||
for (cmdp = *pp ; cmdp ; cmdp = cmdp->next) {
|
||||
if (cmdp->cmdtype == CMDNORMAL)
|
||||
printentry(cmdp, verbose);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
while ((name = *argptr) != NULL) {
|
||||
if ((cmdp = cmdlookup(name, 0)) != NULL
|
||||
&& (cmdp->cmdtype == CMDNORMAL
|
||||
|| cmdp->cmdtype == CMDBUILTIN && builtinloc >= 0))
|
||||
|| (cmdp->cmdtype == CMDBUILTIN && builtinloc >= 0)))
|
||||
delete_cmd_entry();
|
||||
find_command(name, &entry, 1);
|
||||
find_command(name, &entry, 1, pathval());
|
||||
if (verbose) {
|
||||
if (entry.cmdtype != CMDUNKNOWN) { /* if no error msg */
|
||||
cmdp = cmdlookup(name, 0);
|
||||
printentry(cmdp);
|
||||
if (cmdp != NULL)
|
||||
printentry(cmdp, verbose);
|
||||
else
|
||||
outfmt(&errout, "%s: not found\n", name);
|
||||
}
|
||||
flushall();
|
||||
}
|
||||
@@ -354,9 +269,8 @@ hashcmd(argc, argv) char **argv; {
|
||||
|
||||
|
||||
STATIC void
|
||||
printentry(cmdp)
|
||||
struct tblentry *cmdp;
|
||||
{
|
||||
printentry(struct tblentry *cmdp, int verbose)
|
||||
{
|
||||
int index;
|
||||
char *path;
|
||||
char *name;
|
||||
@@ -373,6 +287,14 @@ printentry(cmdp)
|
||||
out1fmt("builtin %s", cmdp->cmdname);
|
||||
} else if (cmdp->cmdtype == CMDFUNCTION) {
|
||||
out1fmt("function %s", cmdp->cmdname);
|
||||
if (verbose) {
|
||||
INTOFF;
|
||||
name = commandtext(cmdp->param.func);
|
||||
out1c(' ');
|
||||
out1str(name);
|
||||
ckfree(name);
|
||||
INTON;
|
||||
}
|
||||
#if DEBUG
|
||||
} else {
|
||||
error("internal error: cmdtype %d", cmdp->cmdtype);
|
||||
@@ -391,14 +313,11 @@ printentry(cmdp)
|
||||
*/
|
||||
|
||||
void
|
||||
find_command(name, entry, printerr)
|
||||
char *name;
|
||||
struct cmdentry *entry;
|
||||
{
|
||||
find_command(char *name, struct cmdentry *entry, int printerr, char *path)
|
||||
{
|
||||
struct tblentry *cmdp;
|
||||
int index;
|
||||
int prev;
|
||||
char *path;
|
||||
char *fullname;
|
||||
struct stat statb;
|
||||
int e;
|
||||
@@ -434,7 +353,6 @@ find_command(name, entry, printerr)
|
||||
prev = cmdp->param.index;
|
||||
}
|
||||
|
||||
path = pathval();
|
||||
e = ENOENT;
|
||||
index = -1;
|
||||
loop:
|
||||
@@ -464,17 +382,13 @@ loop:
|
||||
TRACE(("searchexec \"%s\": no change\n", name));
|
||||
goto success;
|
||||
}
|
||||
while (stat(fullname, &statb) < 0) {
|
||||
#ifdef SYSV
|
||||
if (errno == EINTR)
|
||||
continue;
|
||||
#endif
|
||||
if (stat(fullname, &statb) < 0) {
|
||||
if (errno != ENOENT && errno != ENOTDIR)
|
||||
e = errno;
|
||||
goto loop;
|
||||
}
|
||||
e = EACCES; /* if we fail, this will be the error */
|
||||
if ((statb.st_mode & S_IFMT) != S_IFREG)
|
||||
if (!S_ISREG(statb.st_mode))
|
||||
goto loop;
|
||||
if (pathopt) { /* this is a %func directory */
|
||||
stalloc(strlen(fullname) + 1);
|
||||
@@ -484,6 +398,7 @@ loop:
|
||||
stunalloc(fullname);
|
||||
goto success;
|
||||
}
|
||||
#ifdef notdef
|
||||
if (statb.st_uid == geteuid()) {
|
||||
if ((statb.st_mode & 0100) == 0)
|
||||
goto loop;
|
||||
@@ -491,23 +406,10 @@ loop:
|
||||
if ((statb.st_mode & 010) == 0)
|
||||
goto loop;
|
||||
} else {
|
||||
#if __minix_vmd || defined(BSD)
|
||||
gid_t group_list[NGROUPS_MAX];
|
||||
int ngroups, i;
|
||||
|
||||
ngroups = getgroups(NGROUPS_MAX, group_list);
|
||||
|
||||
for (i = 0; i < ngroups; i++) {
|
||||
if (statb.st_gid == group_list[i]) break;
|
||||
}
|
||||
if (i < ngroups) {
|
||||
if ((statb.st_mode & 010) == 0)
|
||||
goto loop;
|
||||
} else
|
||||
#endif
|
||||
if ((statb.st_mode & 01) == 0)
|
||||
goto loop;
|
||||
}
|
||||
#endif
|
||||
TRACE(("searchexec \"%s\" returns \"%s\"\n", name, fullname));
|
||||
INTOFF;
|
||||
cmdp = cmdlookup(name, 1);
|
||||
@@ -520,8 +422,12 @@ loop:
|
||||
/* We failed. If there was an entry for this command, delete it */
|
||||
if (cmdp)
|
||||
delete_cmd_entry();
|
||||
if (printerr)
|
||||
outfmt(out2, "%s: %s\n", name, errmsg(e, E_EXEC));
|
||||
if (printerr) {
|
||||
if (e == ENOENT || e == ENOTDIR)
|
||||
outfmt(out2, "%s: not found\n", name);
|
||||
else
|
||||
outfmt(out2, "%s: %s\n", name, strerror(e));
|
||||
}
|
||||
entry->cmdtype = CMDUNKNOWN;
|
||||
return;
|
||||
|
||||
@@ -538,10 +444,9 @@ success:
|
||||
*/
|
||||
|
||||
int
|
||||
find_builtin(name)
|
||||
char *name;
|
||||
{
|
||||
const register struct builtincmd *bp;
|
||||
find_builtin(char *name)
|
||||
{
|
||||
const struct builtincmd *bp;
|
||||
|
||||
for (bp = builtincmd ; bp->name ; bp++) {
|
||||
if (*bp->name == *name && equal(bp->name, name))
|
||||
@@ -558,14 +463,15 @@ find_builtin(name)
|
||||
*/
|
||||
|
||||
void
|
||||
hashcd() {
|
||||
hashcd(void)
|
||||
{
|
||||
struct tblentry **pp;
|
||||
struct tblentry *cmdp;
|
||||
|
||||
for (pp = cmdtable ; pp < &cmdtable[CMDTABLESIZE] ; pp++) {
|
||||
for (cmdp = *pp ; cmdp ; cmdp = cmdp->next) {
|
||||
if (cmdp->cmdtype == CMDNORMAL
|
||||
|| cmdp->cmdtype == CMDBUILTIN && builtinloc >= 0)
|
||||
|| (cmdp->cmdtype == CMDBUILTIN && builtinloc >= 0))
|
||||
cmdp->rehash = 1;
|
||||
}
|
||||
}
|
||||
@@ -580,10 +486,9 @@ hashcd() {
|
||||
*/
|
||||
|
||||
void
|
||||
changepath(newval)
|
||||
char *newval;
|
||||
{
|
||||
char *old, *new;
|
||||
changepath(const char *newval)
|
||||
{
|
||||
const char *old, *new;
|
||||
int index;
|
||||
int firstchange;
|
||||
int bltin;
|
||||
@@ -596,8 +501,8 @@ changepath(newval)
|
||||
for (;;) {
|
||||
if (*old != *new) {
|
||||
firstchange = index;
|
||||
if (*old == '\0' && *new == ':'
|
||||
|| *old == ':' && *new == '\0')
|
||||
if ((*old == '\0' && *new == ':')
|
||||
|| (*old == ':' && *new == '\0'))
|
||||
firstchange++;
|
||||
old = new; /* ignore subsequent differences */
|
||||
}
|
||||
@@ -624,8 +529,9 @@ changepath(newval)
|
||||
* PATH which has changed.
|
||||
*/
|
||||
|
||||
STATIC void
|
||||
clearcmdentry(firstchange) {
|
||||
void
|
||||
clearcmdentry(int firstchange)
|
||||
{
|
||||
struct tblentry **tblp;
|
||||
struct tblentry **pp;
|
||||
struct tblentry *cmdp;
|
||||
@@ -634,8 +540,10 @@ clearcmdentry(firstchange) {
|
||||
for (tblp = cmdtable ; tblp < &cmdtable[CMDTABLESIZE] ; tblp++) {
|
||||
pp = tblp;
|
||||
while ((cmdp = *pp) != NULL) {
|
||||
if (cmdp->cmdtype == CMDNORMAL && cmdp->param.index >= firstchange
|
||||
|| cmdp->cmdtype == CMDBUILTIN && builtinloc >= firstchange) {
|
||||
if ((cmdp->cmdtype == CMDNORMAL &&
|
||||
cmdp->param.index >= firstchange)
|
||||
|| (cmdp->cmdtype == CMDBUILTIN &&
|
||||
builtinloc >= firstchange)) {
|
||||
*pp = cmdp->next;
|
||||
ckfree(cmdp);
|
||||
} else {
|
||||
@@ -652,15 +560,15 @@ clearcmdentry(firstchange) {
|
||||
*/
|
||||
|
||||
#ifdef mkinit
|
||||
MKINIT void deletefuncs();
|
||||
|
||||
INCLUDE "exec.h"
|
||||
SHELLPROC {
|
||||
deletefuncs();
|
||||
}
|
||||
#endif
|
||||
|
||||
void
|
||||
deletefuncs() {
|
||||
deletefuncs(void)
|
||||
{
|
||||
struct tblentry **tblp;
|
||||
struct tblentry **pp;
|
||||
struct tblentry *cmdp;
|
||||
@@ -691,15 +599,14 @@ deletefuncs() {
|
||||
* entry.
|
||||
*/
|
||||
|
||||
struct tblentry **lastcmdentry;
|
||||
STATIC struct tblentry **lastcmdentry;
|
||||
|
||||
|
||||
STATIC struct tblentry *
|
||||
cmdlookup(name, add)
|
||||
char *name;
|
||||
{
|
||||
cmdlookup(char *name, int add)
|
||||
{
|
||||
int hashval;
|
||||
register char *p;
|
||||
char *p;
|
||||
struct tblentry *cmdp;
|
||||
struct tblentry **pp;
|
||||
|
||||
@@ -728,13 +635,13 @@ cmdlookup(name, add)
|
||||
return cmdp;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Delete the command entry returned on the last lookup.
|
||||
*/
|
||||
|
||||
STATIC void
|
||||
delete_cmd_entry() {
|
||||
delete_cmd_entry(void)
|
||||
{
|
||||
struct tblentry *cmdp;
|
||||
|
||||
INTOFF;
|
||||
@@ -746,35 +653,14 @@ delete_cmd_entry() {
|
||||
|
||||
|
||||
|
||||
#ifdef notdef
|
||||
void
|
||||
getcmdentry(name, entry)
|
||||
char *name;
|
||||
struct cmdentry *entry;
|
||||
{
|
||||
struct tblentry *cmdp = cmdlookup(name, 0);
|
||||
|
||||
if (cmdp) {
|
||||
entry->u = cmdp->param;
|
||||
entry->cmdtype = cmdp->cmdtype;
|
||||
} else {
|
||||
entry->cmdtype = CMDUNKNOWN;
|
||||
entry->u.index = 0;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
* Add a new command entry, replacing any existing command entry for
|
||||
* the same name.
|
||||
*/
|
||||
|
||||
void
|
||||
addcmdentry(name, entry)
|
||||
char *name;
|
||||
struct cmdentry *entry;
|
||||
{
|
||||
static void
|
||||
addcmdentry(char *name, struct cmdentry *entry)
|
||||
{
|
||||
struct tblentry *cmdp;
|
||||
|
||||
INTOFF;
|
||||
@@ -793,10 +679,8 @@ addcmdentry(name, entry)
|
||||
*/
|
||||
|
||||
void
|
||||
defun(name, func)
|
||||
char *name;
|
||||
union node *func;
|
||||
{
|
||||
defun(char *name, union node *func)
|
||||
{
|
||||
struct cmdentry entry;
|
||||
|
||||
INTOFF;
|
||||
@@ -811,14 +695,98 @@ defun(name, func)
|
||||
* Delete a function if it exists.
|
||||
*/
|
||||
|
||||
void
|
||||
unsetfunc(name)
|
||||
char *name;
|
||||
{
|
||||
int
|
||||
unsetfunc(char *name)
|
||||
{
|
||||
struct tblentry *cmdp;
|
||||
|
||||
if ((cmdp = cmdlookup(name, 0)) != NULL && cmdp->cmdtype == CMDFUNCTION) {
|
||||
freefunc(cmdp->param.func);
|
||||
delete_cmd_entry();
|
||||
return (0);
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Locate and print what a word is...
|
||||
*/
|
||||
|
||||
int
|
||||
typecmd(int argc, char **argv)
|
||||
{
|
||||
struct cmdentry entry;
|
||||
struct tblentry *cmdp;
|
||||
char **pp;
|
||||
struct alias *ap;
|
||||
int i;
|
||||
int error = 0;
|
||||
extern char *const parsekwd[];
|
||||
|
||||
for (i = 1; i < argc; i++) {
|
||||
out1str(argv[i]);
|
||||
/* First look at the keywords */
|
||||
for (pp = (char **)parsekwd; *pp; pp++)
|
||||
if (**pp == *argv[i] && equal(*pp, argv[i]))
|
||||
break;
|
||||
|
||||
if (*pp) {
|
||||
out1str(" is a shell keyword\n");
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Then look at the aliases */
|
||||
if ((ap = lookupalias(argv[i], 1)) != NULL) {
|
||||
out1fmt(" is an alias for %s\n", ap->val);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Then check if it is a tracked alias */
|
||||
if ((cmdp = cmdlookup(argv[i], 0)) != NULL) {
|
||||
entry.cmdtype = cmdp->cmdtype;
|
||||
entry.u = cmdp->param;
|
||||
}
|
||||
else {
|
||||
/* Finally use brute force */
|
||||
find_command(argv[i], &entry, 0, pathval());
|
||||
}
|
||||
|
||||
switch (entry.cmdtype) {
|
||||
case CMDNORMAL: {
|
||||
if (strchr(argv[i], '/') == NULL) {
|
||||
char *path = pathval(), *name;
|
||||
int j = entry.u.index;
|
||||
do {
|
||||
name = padvance(&path, argv[i]);
|
||||
stunalloc(name);
|
||||
} while (--j >= 0);
|
||||
out1fmt(" is%s %s\n",
|
||||
cmdp ? " a tracked alias for" : "", name);
|
||||
} else {
|
||||
if (access(argv[i], X_OK) == 0)
|
||||
out1fmt(" is %s\n", argv[i]);
|
||||
else
|
||||
out1fmt(": %s\n", strerror(errno));
|
||||
}
|
||||
break;
|
||||
}
|
||||
case CMDFUNCTION:
|
||||
out1str(" is a shell function\n");
|
||||
break;
|
||||
|
||||
case CMDBUILTIN:
|
||||
out1str(" is a shell builtin\n");
|
||||
break;
|
||||
|
||||
default:
|
||||
out1str(": not found\n");
|
||||
error |= 127;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return error;
|
||||
}
|
||||
|
||||
/*
|
||||
* $PchId: exec.c,v 1.6 2006/04/10 14:47:03 philip Exp $
|
||||
*/
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*-
|
||||
* Copyright (c) 1991 The Regents of the University of California.
|
||||
* All rights reserved.
|
||||
* 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.
|
||||
@@ -13,10 +13,6 @@
|
||||
* 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.
|
||||
@@ -33,7 +29,8 @@
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)exec.h 5.1 (Berkeley) 3/7/91
|
||||
* @(#)exec.h 8.3 (Berkeley) 6/8/95
|
||||
* $FreeBSD: src/bin/sh/exec.h,v 1.12 2004/04/06 20:06:51 markm Exp $
|
||||
*/
|
||||
|
||||
/* values of cmdtype */
|
||||
@@ -53,23 +50,21 @@ struct cmdentry {
|
||||
|
||||
|
||||
extern char *pathopt; /* set by padvance */
|
||||
extern int exerrno; /* last exec error */
|
||||
|
||||
#ifdef __STDC__
|
||||
void shellexec(char **, char **, char *, int);
|
||||
char *padvance(char **, char *);
|
||||
void find_command(char *, struct cmdentry *, int);
|
||||
int hashcmd(int, char **);
|
||||
void find_command(char *, struct cmdentry *, int, char *);
|
||||
int find_builtin(char *);
|
||||
void hashcd(void);
|
||||
void changepath(char *);
|
||||
void changepath(const char *);
|
||||
void deletefuncs(void);
|
||||
void defun(char *, union node *);
|
||||
void unsetfunc(char *);
|
||||
#else
|
||||
void shellexec();
|
||||
char *padvance();
|
||||
void find_command();
|
||||
int find_builtin();
|
||||
void hashcd();
|
||||
void changepath();
|
||||
void defun();
|
||||
void unsetfunc();
|
||||
#endif
|
||||
int unsetfunc(char *);
|
||||
int typecmd(int, char **);
|
||||
void clearcmdentry(int);
|
||||
|
||||
/*
|
||||
* $PchId: exec.h,v 1.5 2006/04/10 14:47:34 philip Exp $
|
||||
*/
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,6 +1,6 @@
|
||||
/*-
|
||||
* Copyright (c) 1991 The Regents of the University of California.
|
||||
* All rights reserved.
|
||||
* 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.
|
||||
@@ -13,10 +13,6 @@
|
||||
* 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.
|
||||
@@ -33,7 +29,8 @@
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)expand.h 5.1 (Berkeley) 3/7/91
|
||||
* @(#)expand.h 8.2 (Berkeley) 5/4/95
|
||||
* $FreeBSD: src/bin/sh/expand.h,v 1.12 2004/04/06 20:06:51 markm Exp $
|
||||
*/
|
||||
|
||||
struct strlist {
|
||||
@@ -47,17 +44,24 @@ struct arglist {
|
||||
struct strlist **lastp;
|
||||
};
|
||||
|
||||
#ifdef __STDC__
|
||||
/*
|
||||
* 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 */
|
||||
|
||||
|
||||
union node;
|
||||
void expandarg(union node *, struct arglist *, int);
|
||||
void expandhere(union node *, int);
|
||||
int patmatch(char *, char *);
|
||||
void expandarg(union node *, struct arglist *, int);
|
||||
int patmatch(char *, char *, int);
|
||||
void rmescapes(char *);
|
||||
int casematch(union node *, char *);
|
||||
#else
|
||||
void expandarg();
|
||||
void expandhere();
|
||||
int patmatch();
|
||||
void rmescapes();
|
||||
int casematch();
|
||||
#endif
|
||||
int wordexpcmd(int, char **);
|
||||
|
||||
/*
|
||||
* $PchId: expand.h,v 1.4 2006/03/30 14:50:52 philip Exp $
|
||||
*/
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# Copyright (c) 1991 The Regents of the University of California.
|
||||
# All rights reserved.
|
||||
# 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.
|
||||
@@ -12,10 +12,6 @@
|
||||
# 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.
|
||||
@@ -32,7 +28,8 @@
|
||||
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
# SUCH DAMAGE.
|
||||
#
|
||||
# @(#)cmv 5.1 (Berkeley) 3/7/91
|
||||
# @(#)cmv 8.2 (Berkeley) 5/4/95
|
||||
# $FreeBSD: src/bin/sh/funcs/cmv,v 1.7 2004/04/06 20:06:53 markm Exp $
|
||||
|
||||
# Conditional move--don't replace an existing file.
|
||||
|
||||
@@ -47,3 +44,6 @@ cmv() {
|
||||
fi
|
||||
/bin/mv "$1" "$2"
|
||||
}
|
||||
|
||||
#
|
||||
# $PchId: cmv,v 1.2 2006/03/29 10:43:18 philip Exp $
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# Copyright (c) 1991 The Regents of the University of California.
|
||||
# All rights reserved.
|
||||
# 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.
|
||||
@@ -12,10 +12,6 @@
|
||||
# 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.
|
||||
@@ -32,7 +28,8 @@
|
||||
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
# SUCH DAMAGE.
|
||||
#
|
||||
# @(#)dirs 5.1 (Berkeley) 3/7/91
|
||||
# @(#)dirs 8.2 (Berkeley) 5/4/95
|
||||
# $FreeBSD: src/bin/sh/funcs/dirs,v 1.7 2004/04/06 20:06:53 markm Exp $
|
||||
|
||||
# pushd, popd, and dirs --- written by Chris Bertin
|
||||
# Pixel Computer Inc. ...!wjh12!pixel!pixutl!chris
|
||||
@@ -71,3 +68,6 @@ dirs () {
|
||||
echo "`pwd` $DSTACK"
|
||||
return 0
|
||||
}
|
||||
|
||||
#
|
||||
# $PchId: dirs,v 1.2 2006/03/29 10:43:18 philip Exp $
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# Copyright (c) 1991 The Regents of the University of California.
|
||||
# All rights reserved.
|
||||
# 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.
|
||||
@@ -12,10 +12,6 @@
|
||||
# 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.
|
||||
@@ -32,7 +28,8 @@
|
||||
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
# SUCH DAMAGE.
|
||||
#
|
||||
# @(#)kill 5.1 (Berkeley) 3/7/91
|
||||
# @(#)kill 8.2 (Berkeley) 5/4/95
|
||||
# $FreeBSD: src/bin/sh/funcs/kill,v 1.7 2004/04/06 20:06:53 markm Exp $
|
||||
|
||||
# Convert job names to process ids and then run /bin/kill.
|
||||
|
||||
@@ -47,3 +44,6 @@ kill() {
|
||||
done
|
||||
/bin/kill $args
|
||||
}
|
||||
|
||||
#
|
||||
# $PchId: kill,v 1.2 2006/03/29 10:43:18 philip Exp $
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# Copyright (c) 1991 The Regents of the University of California.
|
||||
# All rights reserved.
|
||||
# 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.
|
||||
@@ -12,10 +12,6 @@
|
||||
# 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.
|
||||
@@ -32,7 +28,11 @@
|
||||
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
# SUCH DAMAGE.
|
||||
#
|
||||
# @(#)login 5.1 (Berkeley) 3/7/91
|
||||
# @(#)login 8.2 (Berkeley) 5/4/95
|
||||
# $FreeBSD: src/bin/sh/funcs/login,v 1.7 2004/04/06 20:06:53 markm Exp $
|
||||
|
||||
# replaces the login builtin in the BSD shell
|
||||
login () exec login "$@"
|
||||
|
||||
#
|
||||
# $PchId: login,v 1.2 2006/03/29 10:43:18 philip Exp $
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# Copyright (c) 1991 The Regents of the University of California.
|
||||
# All rights reserved.
|
||||
# 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.
|
||||
@@ -12,10 +12,6 @@
|
||||
# 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.
|
||||
@@ -32,6 +28,10 @@
|
||||
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
# SUCH DAMAGE.
|
||||
#
|
||||
# @(#)newgrp 5.1 (Berkeley) 3/7/91
|
||||
# @(#)newgrp 8.2 (Berkeley) 5/4/95
|
||||
# $FreeBSD: src/bin/sh/funcs/newgrp,v 1.7 2004/04/06 20:06:53 markm Exp $
|
||||
|
||||
newgrp() exec newgrp "$@"
|
||||
|
||||
#
|
||||
# $PchId: newgrp,v 1.2 2006/03/29 10:43:18 philip Exp $
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# Copyright (c) 1991 The Regents of the University of California.
|
||||
# All rights reserved.
|
||||
# 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.
|
||||
@@ -12,10 +12,6 @@
|
||||
# 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.
|
||||
@@ -32,7 +28,8 @@
|
||||
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
# SUCH DAMAGE.
|
||||
#
|
||||
# @(#)popd 5.1 (Berkeley) 3/7/91
|
||||
# @(#)popd 8.2 (Berkeley) 5/4/95
|
||||
# $FreeBSD: src/bin/sh/funcs/popd,v 1.7 2004/04/06 20:06:53 markm Exp $
|
||||
|
||||
# pushd, popd, and dirs --- written by Chris Bertin
|
||||
# Pixel Computer Inc. ...!wjh12!pixel!pixutl!chris
|
||||
@@ -71,3 +68,6 @@ dirs () {
|
||||
echo "`pwd` $DSTACK"
|
||||
return 0
|
||||
}
|
||||
|
||||
#
|
||||
# $PchId: popd,v 1.2 2006/03/29 10:43:18 philip Exp $
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# Copyright (c) 1991 The Regents of the University of California.
|
||||
# All rights reserved.
|
||||
# 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.
|
||||
@@ -12,10 +12,6 @@
|
||||
# 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.
|
||||
@@ -32,7 +28,8 @@
|
||||
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
# SUCH DAMAGE.
|
||||
#
|
||||
# @(#)pushd 5.1 (Berkeley) 3/7/91
|
||||
# @(#)pushd 8.2 (Berkeley) 5/4/95
|
||||
# $FreeBSD: src/bin/sh/funcs/pushd,v 1.7 2004/04/06 20:06:53 markm Exp $
|
||||
|
||||
# pushd, popd, and dirs --- written by Chris Bertin
|
||||
# Pixel Computer Inc. ...!wjh12!pixel!pixutl!chris
|
||||
@@ -71,3 +68,6 @@ dirs () {
|
||||
echo "`pwd` $DSTACK"
|
||||
return 0
|
||||
}
|
||||
|
||||
#
|
||||
# $PchId: pushd,v 1.2 2006/03/29 10:43:18 philip Exp $
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# Copyright (c) 1991 The Regents of the University of California.
|
||||
# All rights reserved.
|
||||
# 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.
|
||||
@@ -12,10 +12,6 @@
|
||||
# 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.
|
||||
@@ -32,10 +28,14 @@
|
||||
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
# SUCH DAMAGE.
|
||||
#
|
||||
# @(#)suspend 5.1 (Berkeley) 3/7/91
|
||||
# @(#)suspend 8.2 (Berkeley) 5/4/95
|
||||
# $FreeBSD: src/bin/sh/funcs/suspend,v 1.7 2004/04/06 20:06:53 markm Exp $
|
||||
|
||||
suspend() {
|
||||
local -
|
||||
set +j
|
||||
kill -TSTP 0
|
||||
}
|
||||
|
||||
#
|
||||
# $PchId: suspend,v 1.2 2006/03/29 10:43:18 philip Exp $
|
||||
|
||||
533
commands/ash/histedit.c
Normal file
533
commands/ash/histedit.c
Normal file
@@ -0,0 +1,533 @@
|
||||
/*-
|
||||
* 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.
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef lint
|
||||
#if 0
|
||||
static char sccsid[] = "@(#)histedit.c 8.2 (Berkeley) 5/4/95";
|
||||
#endif
|
||||
#endif /* not lint */
|
||||
/*
|
||||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD: src/bin/sh/histedit.c,v 1.26 2004/04/06 20:06:51 markm Exp $");
|
||||
*/
|
||||
|
||||
#include <limits.h>
|
||||
#ifndef NO_PATHS_H
|
||||
#include <paths.h>
|
||||
#endif
|
||||
#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 "builtins.h"
|
||||
#if !defined(NO_HISTORY) && !defined(EDITLINE)
|
||||
#include "myhistedit.h"
|
||||
#include "complete.h"
|
||||
#include "error.h"
|
||||
#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, *el_err;
|
||||
|
||||
STATIC char *fc_replace(const char *, char *, char *);
|
||||
STATIC int not_fcnumber(char *);
|
||||
STATIC int str_to_event(char *, int);
|
||||
|
||||
/*
|
||||
* Set history and editing status. Called whenever the status may
|
||||
* have changed (figures out what to do).
|
||||
*/
|
||||
void
|
||||
histedit(void)
|
||||
{
|
||||
|
||||
#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
|
||||
*/
|
||||
INTOFF;
|
||||
if (el_in == NULL)
|
||||
el_in = fdopen(0, "r");
|
||||
if (el_err == NULL)
|
||||
el_err = fdopen(1, "w");
|
||||
if (el_out == NULL)
|
||||
el_out = fdopen(2, "w");
|
||||
if (el_in == NULL || el_err == NULL || el_out == NULL)
|
||||
goto bad;
|
||||
el = el_init(arg0, el_in, el_out, el_err);
|
||||
if (el != NULL) {
|
||||
if (hist)
|
||||
el_set(el, EL_HIST, history, hist);
|
||||
el_set(el, EL_PROMPT, getprompt);
|
||||
} 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_set(el, EL_ADDFN, "ed-do-complete",
|
||||
"Complete Argument", complete);
|
||||
el_set(el, EL_ADDFN, "ed-list-complete",
|
||||
"List Argument Completions", complete_list);
|
||||
el_set(el, EL_ADDFN, "ed-maybe-complete",
|
||||
"Complete Argument Or List Completions",
|
||||
complete_or_list);
|
||||
el_set(el, EL_ADDFN, "ed-expand",
|
||||
"Expand Completions", complete_expand);
|
||||
el_set(el, EL_BIND, "^I", "ed-maybe-complete", NULL);
|
||||
el_set(el, EL_BIND, "-a", "=", "ed-list-complete",
|
||||
NULL);
|
||||
el_set(el, EL_BIND, "-a", "\\\\", "ed-do-complete",
|
||||
NULL);
|
||||
el_set(el, EL_BIND, "-a", "*", "ed-expand",
|
||||
NULL);
|
||||
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(hs)
|
||||
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_EVENT, histsize);
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
histcmd(int argc, char **argv)
|
||||
{
|
||||
int ch;
|
||||
char *editor = NULL;
|
||||
HistEvent he;
|
||||
int lflg = 0, nflg = 0, rflg = 0, sflg = 0;
|
||||
int i, retval;
|
||||
char *firststr, *laststr;
|
||||
int first, last, direction;
|
||||
char *pat = NULL, *repl;
|
||||
static int active = 0;
|
||||
struct jmploc jmploc;
|
||||
struct jmploc *volatile savehandler;
|
||||
char editfile[PATH_MAX];
|
||||
FILE *efp;
|
||||
int oldhistnum;
|
||||
#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 */
|
||||
opterr = 0;
|
||||
while (not_fcnumber(argv[optind]) &&
|
||||
(ch = getopt(argc, argv, ":e:lnrs")) != -1)
|
||||
switch ((char)ch) {
|
||||
case 'e':
|
||||
editor = optarg;
|
||||
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);
|
||||
case '?':
|
||||
default:
|
||||
error("unknown option: -%c", optopt);
|
||||
}
|
||||
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");
|
||||
}
|
||||
/*
|
||||
* 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 */
|
||||
sprintf(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 {
|
||||
char *s = pat ?
|
||||
fc_replace(he.str, pat, repl) : (char *)he.str;
|
||||
|
||||
if (sflg) {
|
||||
if (displayhist) {
|
||||
out2str(s);
|
||||
}
|
||||
evalstring(s);
|
||||
if (displayhist && hist) {
|
||||
/*
|
||||
* XXX what about recursive and
|
||||
* relative histnums.
|
||||
*/
|
||||
oldhistnum = he.num;
|
||||
history(hist, &he, H_ENTER, s);
|
||||
/*
|
||||
* XXX H_ENTER moves the internal
|
||||
* cursor, set it back to the current
|
||||
* entry.
|
||||
*/
|
||||
retval = history(hist, &he,
|
||||
H_NEXT_EVENT, oldhistnum);
|
||||
}
|
||||
} else
|
||||
fputs(s, efp);
|
||||
}
|
||||
/*
|
||||
* At end? (if we were to loose 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); /* 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 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);
|
||||
}
|
||||
|
||||
STATIC int
|
||||
not_fcnumber(char *s)
|
||||
{
|
||||
if (s == NULL)
|
||||
return (0);
|
||||
if (*s == '-')
|
||||
s++;
|
||||
return (!is_number(s));
|
||||
}
|
||||
|
||||
STATIC int
|
||||
str_to_event(char *str, int last)
|
||||
{
|
||||
HistEvent he;
|
||||
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);
|
||||
}
|
||||
|
||||
int
|
||||
bindcmd(int argc, char **argv)
|
||||
{
|
||||
|
||||
if (el == NULL)
|
||||
error("line editing is disabled");
|
||||
return (el_parse(el, argc, argv));
|
||||
}
|
||||
|
||||
#else
|
||||
#include "error.h"
|
||||
|
||||
int
|
||||
histcmd(int argc, char **argv)
|
||||
{
|
||||
|
||||
error("not compiled with history support");
|
||||
/*NOTREACHED*/
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
bindcmd(int argc, char **argv)
|
||||
{
|
||||
|
||||
error("not compiled with line editing support");
|
||||
return (0);
|
||||
}
|
||||
#endif /* !NO_HISTORY && !EDITLINE */
|
||||
|
||||
/*
|
||||
* $PchId: histedit.c,v 1.6 2006/04/10 14:52:58 philip Exp $
|
||||
*/
|
||||
@@ -1,6 +1,6 @@
|
||||
/*-
|
||||
* Copyright (c) 1991 The Regents of the University of California.
|
||||
* All rights reserved.
|
||||
* 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.
|
||||
@@ -13,10 +13,6 @@
|
||||
* 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.
|
||||
@@ -33,15 +29,14 @@
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)init.h 5.1 (Berkeley) 3/7/91
|
||||
* @(#)init.h 8.2 (Berkeley) 5/4/95
|
||||
* $FreeBSD: src/bin/sh/init.h,v 1.8 2004/04/06 20:06:51 markm Exp $
|
||||
*/
|
||||
|
||||
#ifdef __STDC__
|
||||
void init(void);
|
||||
void reset(void);
|
||||
void initshellproc(void);
|
||||
#else
|
||||
void init();
|
||||
void reset();
|
||||
void initshellproc();
|
||||
#endif
|
||||
|
||||
/*
|
||||
* $PchId: init.h,v 1.3 2006/03/30 14:31:06 philip Exp $
|
||||
*/
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*-
|
||||
* Copyright (c) 1991 The Regents of the University of California.
|
||||
* All rights reserved.
|
||||
* 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.
|
||||
@@ -13,10 +13,6 @@
|
||||
* 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.
|
||||
@@ -35,26 +31,62 @@
|
||||
*/
|
||||
|
||||
#ifndef lint
|
||||
static char sccsid[] = "@(#)input.c 5.4 (Berkeley) 7/1/91";
|
||||
#if 0
|
||||
static char sccsid[] = "@(#)input.c 8.3 (Berkeley) 6/9/95";
|
||||
#endif
|
||||
#endif /* not lint */
|
||||
/*
|
||||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD: src/bin/sh/input.c,v 1.22 2004/04/06 20:06:51 markm Exp $");
|
||||
*/
|
||||
|
||||
#include <sys/types.h>
|
||||
#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 <sys/types.h>
|
||||
#include <stdio.h> /* defines BUFSIZ */
|
||||
#include "shell.h"
|
||||
#include <fcntl.h>
|
||||
#include <errno.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"
|
||||
#ifdef EDITLINE
|
||||
#ifdef __minix_vmd
|
||||
#include <readline/readline.h>
|
||||
#else
|
||||
/* What about other systems? */
|
||||
char *readline(char *prompt);
|
||||
#endif
|
||||
#else
|
||||
#include "myhistedit.h"
|
||||
#endif
|
||||
#include "redir.h"
|
||||
#include "trap.h"
|
||||
|
||||
static void popstring(void);
|
||||
|
||||
#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
|
||||
@@ -63,36 +95,34 @@ static char sccsid[] = "@(#)input.c 5.4 (Berkeley) 7/1/91";
|
||||
|
||||
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 buffer */
|
||||
int nleft; /* number of chars left in this line */
|
||||
int lleft; /* number of lines left in this buffer */
|
||||
char *nextc; /* next char in buffer */
|
||||
struct parsefile *prev; /* preceding file on stack */
|
||||
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 */
|
||||
MKINIT 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 */
|
||||
char basebuf[BUFSIZ]; /* buffer for top level input file */
|
||||
struct parsefile *parsefile = &basepf; /* current input file */
|
||||
char *pushedstring; /* copy of parsenextc when text pushed back */
|
||||
int pushednleft; /* copy of parsenleft when text pushed back */
|
||||
STATIC struct parsefile *parsefile = &basepf; /* current input file */
|
||||
int init_editline = 0; /* editline library initialized? */
|
||||
int whichprompt; /* -1 == PSE, 1 == PS1, 2 == PS2 */
|
||||
|
||||
#if READLINE
|
||||
char *readline __P((const char *prompt));
|
||||
char *r_use_prompt = NULL; /* the prompt to use with readline */
|
||||
#ifndef EDITLINE
|
||||
EditLine *el; /* cookie for editline package */
|
||||
#endif
|
||||
|
||||
#ifdef __STDC__
|
||||
STATIC void pushfile(void);
|
||||
#else
|
||||
STATIC void pushfile();
|
||||
#endif
|
||||
|
||||
|
||||
static int preadfd(void);
|
||||
|
||||
#ifdef mkinit
|
||||
INCLUDE "input.h"
|
||||
@@ -106,7 +136,7 @@ INIT {
|
||||
|
||||
RESET {
|
||||
if (exception != EXSHELLPROC)
|
||||
parsenleft = 0; /* clear input buffer */
|
||||
parselleft = parsenleft = 0; /* clear input buffer */
|
||||
popallfiles();
|
||||
}
|
||||
|
||||
@@ -121,10 +151,9 @@ SHELLPROC {
|
||||
*/
|
||||
|
||||
char *
|
||||
pfgets(line, len)
|
||||
char *line;
|
||||
{
|
||||
register char *p = line;
|
||||
pfgets(char *line, int len)
|
||||
{
|
||||
char *p = line;
|
||||
int nleft = len;
|
||||
int c;
|
||||
|
||||
@@ -151,64 +180,74 @@ pfgets(line, len)
|
||||
*/
|
||||
|
||||
int
|
||||
pgetc() {
|
||||
pgetc(void)
|
||||
{
|
||||
return pgetc_macro();
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Refill the input buffer and return the next input character:
|
||||
*
|
||||
* 1) If a string was pushed back on the input, switch back to the regular
|
||||
* buffer.
|
||||
* 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) Call read to read in the characters.
|
||||
* 4) Delete all nul characters from the buffer.
|
||||
*/
|
||||
static int
|
||||
preadfd(void)
|
||||
{
|
||||
int nr;
|
||||
parsenextc = parsefile->buf;
|
||||
|
||||
int
|
||||
preadbuffer() {
|
||||
register char *p, *q;
|
||||
register int i;
|
||||
|
||||
if (pushedstring) {
|
||||
parsenextc = pushedstring;
|
||||
pushedstring = NULL;
|
||||
parsenleft = pushednleft;
|
||||
if (--parsenleft >= 0)
|
||||
return *parsenextc++;
|
||||
#if !defined(NO_HISTORY) && !defined(EDITLINE)
|
||||
if (el != NULL && gotwinch) {
|
||||
gotwinch = 0;
|
||||
el_resize(el);
|
||||
}
|
||||
if (parsenleft == EOF_NLEFT || parsefile->buf == NULL)
|
||||
return PEOF;
|
||||
flushout(&output);
|
||||
flushout(&errout);
|
||||
#if READLINE
|
||||
/* Use the readline() call if a prompt is to be printed (interactive). */
|
||||
if (r_use_prompt != NULL) {
|
||||
char *prompt;
|
||||
char *line;
|
||||
|
||||
p = parsenextc = parsefile->buf;
|
||||
|
||||
prompt = r_use_prompt;
|
||||
r_use_prompt = NULL;
|
||||
|
||||
if ((line = readline(prompt)) == NULL) {
|
||||
parsenleft = EOF_NLEFT;
|
||||
return PEOF;
|
||||
}
|
||||
strcpy(p, line);
|
||||
free(line);
|
||||
i = strlen(p);
|
||||
p[i++] = '\n';
|
||||
} else {
|
||||
#endif
|
||||
retry:
|
||||
p = parsenextc = parsefile->buf;
|
||||
i = read(parsefile->fd, p, BUFSIZ);
|
||||
if (i <= 0) {
|
||||
if (i < 0) {
|
||||
#ifndef NO_HISTORY
|
||||
#ifdef EDITLINE
|
||||
if (parsefile->fd == 0 && editable) {
|
||||
static const char *rl_cp= NULL;
|
||||
static size_t rl_off= 0;
|
||||
|
||||
if (!rl_cp)
|
||||
{
|
||||
rl_cp = readline(getprompt(NULL));
|
||||
if (rl_cp == NULL)
|
||||
nr = 0;
|
||||
}
|
||||
if (rl_cp)
|
||||
{
|
||||
nr= strlen(rl_cp+rl_off);
|
||||
if (nr >= BUFSIZ-1)
|
||||
{
|
||||
nr= BUFSIZ-1;
|
||||
(void) memcpy(parsenextc, rl_cp+rl_off, nr);
|
||||
rl_off += nr;
|
||||
}
|
||||
else
|
||||
{
|
||||
(void) memcpy(parsenextc, rl_cp+rl_off, nr);
|
||||
parsenextc[nr++]= '\n';
|
||||
free(rl_cp);
|
||||
rl_cp= NULL;
|
||||
rl_off= 0;
|
||||
}
|
||||
}
|
||||
} else
|
||||
#else /* !EDITLINE */
|
||||
if (parsefile->fd == 0 && el) {
|
||||
const char *rl_cp;
|
||||
|
||||
rl_cp = el_gets(el, &nr);
|
||||
if (rl_cp == NULL)
|
||||
nr = 0;
|
||||
else {
|
||||
/* XXX - BUFSIZE should redesign so not necessary */
|
||||
(void) strcpy(parsenextc, rl_cp);
|
||||
}
|
||||
} else
|
||||
#endif /* !EDITLINE */
|
||||
#endif
|
||||
nr = read(parsefile->fd, parsenextc, BUFSIZ - 1);
|
||||
|
||||
if (nr <= 0) {
|
||||
if (nr < 0) {
|
||||
if (errno == EINTR)
|
||||
goto retry;
|
||||
#ifdef EWOULDBLOCK
|
||||
@@ -222,35 +261,106 @@ retry:
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#endif /* EWOULDBLOCK */
|
||||
}
|
||||
parsenleft = EOF_NLEFT;
|
||||
return PEOF;
|
||||
nr = -1;
|
||||
}
|
||||
#if READLINE
|
||||
}
|
||||
#endif
|
||||
parsenleft = i - 1;
|
||||
|
||||
/* delete nul characters */
|
||||
for (;;) {
|
||||
if (*p++ == '\0')
|
||||
break;
|
||||
if (--i <= 0)
|
||||
return *parsenextc++; /* no nul characters */
|
||||
}
|
||||
q = p - 1;
|
||||
while (--i > 0) {
|
||||
if (*p != '\0')
|
||||
*q++ = *p;
|
||||
p++;
|
||||
}
|
||||
if (q == parsefile->buf)
|
||||
goto retry; /* buffer contained nothing but nuls */
|
||||
parsenleft = q - parsefile->buf - 1;
|
||||
return *parsenextc++;
|
||||
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 there is more 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';
|
||||
|
||||
#if !defined(NO_HISTORY) && !defined(EDITLINE)
|
||||
if (parsefile->fd == 0 && hist && something) {
|
||||
HistEvent he;
|
||||
INTOFF;
|
||||
history(hist, &he, whichprompt == 1 ? H_ENTER : H_ADD,
|
||||
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.
|
||||
@@ -258,28 +368,57 @@ retry:
|
||||
*/
|
||||
|
||||
void
|
||||
pungetc() {
|
||||
pungetc(void)
|
||||
{
|
||||
parsenleft++;
|
||||
parsenextc--;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Push a string back onto the input. This code doesn't work if the user
|
||||
* tries to push back more than one string at once.
|
||||
* Push a string back onto the input at this current parsefile level.
|
||||
* We handle aliases this way.
|
||||
*/
|
||||
|
||||
void
|
||||
ppushback(string, length)
|
||||
char *string;
|
||||
{
|
||||
pushedstring = parsenextc;
|
||||
pushednleft = parsenleft;
|
||||
parsenextc = string;
|
||||
parsenleft = length;
|
||||
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;
|
||||
}
|
||||
|
||||
static 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
|
||||
@@ -287,17 +426,16 @@ ppushback(string, length)
|
||||
*/
|
||||
|
||||
void
|
||||
setinputfile(fname, push)
|
||||
char *fname;
|
||||
{
|
||||
setinputfile(char *fname, int push)
|
||||
{
|
||||
int fd;
|
||||
int fd2;
|
||||
|
||||
INTOFF;
|
||||
if ((fd = open(fname, O_RDONLY)) < 0)
|
||||
error("Can't open %s", fname);
|
||||
error("Can't open %s: %s", fname, strerror(errno));
|
||||
if (fd < 10) {
|
||||
fd2 = copyfd(fd, 10);
|
||||
fd2 = fcntl(fd, F_DUPFD, 10);
|
||||
close(fd);
|
||||
if (fd2 < 0)
|
||||
error("Out of file descriptors");
|
||||
@@ -314,8 +452,9 @@ setinputfile(fname, push)
|
||||
*/
|
||||
|
||||
void
|
||||
setinputfd(fd, push) {
|
||||
(void) fcntl(fd, F_SETFD, fcntl(fd, F_GETFD) | FD_CLOEXEC);
|
||||
setinputfd(int fd, int push)
|
||||
{
|
||||
(void)fcntl(fd, F_SETFD, FD_CLOEXEC);
|
||||
if (push) {
|
||||
pushfile();
|
||||
parsefile->buf = ckmalloc(BUFSIZ);
|
||||
@@ -325,7 +464,7 @@ setinputfd(fd, push) {
|
||||
parsefile->fd = fd;
|
||||
if (parsefile->buf == NULL)
|
||||
parsefile->buf = ckmalloc(BUFSIZ);
|
||||
parsenleft = 0;
|
||||
parselleft = parsenleft = 0;
|
||||
plinno = 1;
|
||||
}
|
||||
|
||||
@@ -335,14 +474,13 @@ setinputfd(fd, push) {
|
||||
*/
|
||||
|
||||
void
|
||||
setinputstring(string, push)
|
||||
char *string;
|
||||
{
|
||||
setinputstring(char *string, int push)
|
||||
{
|
||||
INTOFF;
|
||||
if (push)
|
||||
pushfile();
|
||||
parsenextc = string;
|
||||
parsenleft = strlen(string);
|
||||
parselleft = parsenleft = strlen(string);
|
||||
parsefile->buf = NULL;
|
||||
plinno = 1;
|
||||
INTON;
|
||||
@@ -356,21 +494,26 @@ setinputstring(string, push)
|
||||
*/
|
||||
|
||||
STATIC void
|
||||
pushfile() {
|
||||
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() {
|
||||
popfile(void)
|
||||
{
|
||||
struct parsefile *pf = parsefile;
|
||||
|
||||
INTOFF;
|
||||
@@ -378,9 +521,12 @@ popfile() {
|
||||
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;
|
||||
@@ -392,7 +538,8 @@ popfile() {
|
||||
*/
|
||||
|
||||
void
|
||||
popallfiles() {
|
||||
popallfiles(void)
|
||||
{
|
||||
while (parsefile != &basepf)
|
||||
popfile();
|
||||
}
|
||||
@@ -405,10 +552,15 @@ popallfiles() {
|
||||
*/
|
||||
|
||||
void
|
||||
closescript() {
|
||||
closescript(void)
|
||||
{
|
||||
popallfiles();
|
||||
if (parsefile->fd > 0) {
|
||||
close(parsefile->fd);
|
||||
parsefile->fd = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* $PchId: input.c,v 1.7 2006/05/29 13:09:38 philip Exp $
|
||||
*/
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*-
|
||||
* Copyright (c) 1991 The Regents of the University of California.
|
||||
* All rights reserved.
|
||||
* 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.
|
||||
@@ -13,10 +13,6 @@
|
||||
* 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.
|
||||
@@ -33,7 +29,8 @@
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)input.h 5.1 (Berkeley) 3/7/91
|
||||
* @(#)input.h 8.2 (Berkeley) 5/4/95
|
||||
* $FreeBSD: src/bin/sh/input.h,v 1.9 2004/04/06 20:06:51 markm Exp $
|
||||
*/
|
||||
|
||||
/* PEOF (the end of file marker) is defined in syntax.h */
|
||||
@@ -46,39 +43,22 @@
|
||||
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 */
|
||||
|
||||
|
||||
#ifdef __STDC__
|
||||
char *pfgets(char *, int);
|
||||
int pgetc(void);
|
||||
int preadbuffer(void);
|
||||
void pungetc(void);
|
||||
void ppushback(char *, int);
|
||||
void pushstring(char *, int, void *);
|
||||
void setinputfile(char *, int);
|
||||
void setinputfd(int, int);
|
||||
void setinputstring(char *, int);
|
||||
void popfile(void);
|
||||
void popallfiles(void);
|
||||
void closescript(void);
|
||||
#else
|
||||
char *pfgets();
|
||||
int pgetc();
|
||||
int preadbuffer();
|
||||
void pungetc();
|
||||
void ppushback();
|
||||
void setinputfile();
|
||||
void setinputfd();
|
||||
void setinputstring();
|
||||
void popfile();
|
||||
void popallfiles();
|
||||
void closescript();
|
||||
#endif
|
||||
|
||||
#define pgetc_macro() (--parsenleft >= 0? *parsenextc++ : preadbuffer())
|
||||
|
||||
#if READLINE
|
||||
/* The variable "r_use_prompt" indicates the prompt to use with readline,
|
||||
* *and* that readline may only be used if non-NULL.
|
||||
/*
|
||||
* $PchId: input.h,v 1.3 2006/03/30 13:49:37 philip Exp $
|
||||
*/
|
||||
extern char *r_use_prompt;
|
||||
#endif
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,6 +1,6 @@
|
||||
/*-
|
||||
* Copyright (c) 1991 The Regents of the University of California.
|
||||
* All rights reserved.
|
||||
* 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.
|
||||
@@ -13,10 +13,6 @@
|
||||
* 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.
|
||||
@@ -33,7 +29,8 @@
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)jobs.h 5.1 (Berkeley) 3/7/91
|
||||
* @(#)jobs.h 8.2 (Berkeley) 5/4/95
|
||||
* $FreeBSD: src/bin/sh/jobs.h,v 1.18 2004/04/06 20:06:51 markm Exp $
|
||||
*/
|
||||
|
||||
/* Mode argument to forkshell. Don't change FORK_FG or FORK_BG. */
|
||||
@@ -41,6 +38,7 @@
|
||||
#define FORK_BG 1
|
||||
#define FORK_NOJOB 2
|
||||
|
||||
#include <signal.h> /* for sig_atomic_t */
|
||||
|
||||
/*
|
||||
* A job structure contains information about a job. A job is either a
|
||||
@@ -51,7 +49,7 @@
|
||||
|
||||
struct procstat {
|
||||
pid_t pid; /* process id */
|
||||
short status; /* status flags (defined above) */
|
||||
int status; /* status flags (defined above) */
|
||||
char *cmd; /* text of command being run */
|
||||
};
|
||||
|
||||
@@ -64,33 +62,41 @@ struct procstat {
|
||||
struct job {
|
||||
struct procstat ps0; /* status of process */
|
||||
struct procstat *ps; /* status or processes when more than one */
|
||||
pid_t nprocs; /* number of processes */
|
||||
short nprocs; /* number of processes */
|
||||
pid_t pgrp; /* process group of this job */
|
||||
char state; /* true if job is finished */
|
||||
char used; /* true if this entry is in used */
|
||||
char changed; /* true if status has changed */
|
||||
char foreground; /* true if running in the foreground */
|
||||
#if JOBS
|
||||
char jobctl; /* job running under job control */
|
||||
struct job *next; /* job used after this one */
|
||||
#endif
|
||||
};
|
||||
|
||||
extern pid_t backgndpid; /* pid of last background process */
|
||||
extern int job_warning; /* user was warned about stopped jobs */
|
||||
extern int in_waitcmd; /* are we in waitcmd()? */
|
||||
extern int in_dowait; /* are we in dowait()? */
|
||||
extern volatile sig_atomic_t breakwaitcmd; /* break wait to process traps? */
|
||||
|
||||
|
||||
#ifdef __STDC__
|
||||
void setjobctl(int);
|
||||
void showjobs(int);
|
||||
int fgcmd(int, char **);
|
||||
int bgcmd(int, char **);
|
||||
int jobscmd(int, char **);
|
||||
void showjobs(int, int, int);
|
||||
int waitcmd(int, char **);
|
||||
int jobidcmd(int, char **);
|
||||
struct job *makejob(union node *, int);
|
||||
int forkshell(struct job *, union node *, int);
|
||||
int waitforjob(struct job *);
|
||||
#else
|
||||
void setjobctl();
|
||||
void showjobs();
|
||||
struct job *makejob();
|
||||
int forkshell();
|
||||
int waitforjob();
|
||||
#endif
|
||||
pid_t forkshell(struct job *, union node *, int);
|
||||
int waitforjob(struct job *, int *);
|
||||
int stoppedjobs(void);
|
||||
char *commandtext(union node *);
|
||||
|
||||
#if ! JOBS
|
||||
#define setjobctl(on) /* do nothing */
|
||||
#endif
|
||||
|
||||
/*
|
||||
* $PchId: jobs.h,v 1.4 2006/03/30 12:07:24 philip Exp $
|
||||
*/
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*-
|
||||
* Copyright (c) 1991 The Regents of the University of California.
|
||||
* All rights reserved.
|
||||
* 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.
|
||||
@@ -33,7 +33,7 @@
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)machdep.h 5.1 (Berkeley) 3/7/91
|
||||
* @(#)machdep.h 8.2 (Berkeley) 5/4/95
|
||||
*/
|
||||
|
||||
/*
|
||||
@@ -47,5 +47,9 @@ union align {
|
||||
char *cp;
|
||||
};
|
||||
|
||||
#define ALIGN(nbytes) ((nbytes) + sizeof(union align) - 1 &~ (sizeof(union align) - 1))
|
||||
#define ALIGN(nbytes) (((nbytes) + sizeof(union align) - 1) & ~(sizeof(union align) - 1))
|
||||
#endif
|
||||
|
||||
/*
|
||||
* $PchId: machdep.h,v 1.2 2001/05/15 16:36:26 philip Exp $
|
||||
*/
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*-
|
||||
* Copyright (c) 1991 The Regents of the University of California.
|
||||
* All rights reserved.
|
||||
* 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.
|
||||
@@ -13,10 +13,6 @@
|
||||
* 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.
|
||||
@@ -35,8 +31,14 @@
|
||||
*/
|
||||
|
||||
#ifndef lint
|
||||
static char sccsid[] = "@(#)mail.c 5.1 (Berkeley) 3/7/91";
|
||||
#if 0
|
||||
static char sccsid[] = "@(#)mail.c 8.2 (Berkeley) 5/4/95";
|
||||
#endif
|
||||
#endif /* not lint */
|
||||
/*
|
||||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD: src/bin/sh/mail.c,v 1.13 2004/04/06 20:06:51 markm Exp $");
|
||||
*/
|
||||
|
||||
/*
|
||||
* Routines to check for mail. (Perhaps make part of main.c?)
|
||||
@@ -48,8 +50,10 @@ static char sccsid[] = "@(#)mail.c 5.1 (Berkeley) 3/7/91";
|
||||
#include "output.h"
|
||||
#include "memalloc.h"
|
||||
#include "error.h"
|
||||
#include "mail.h"
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
|
||||
#define MAXMBOXES 10
|
||||
@@ -67,11 +71,12 @@ STATIC time_t mailtime[MAXMBOXES]; /* times of mailboxes */
|
||||
*/
|
||||
|
||||
void
|
||||
chkmail(silent) {
|
||||
register int i;
|
||||
chkmail(int silent)
|
||||
{
|
||||
int i;
|
||||
char *mpath;
|
||||
char *p;
|
||||
register char *q;
|
||||
char *q;
|
||||
struct stackmark smark;
|
||||
struct stat statb;
|
||||
|
||||
@@ -91,18 +96,28 @@ chkmail(silent) {
|
||||
if (q[-1] != '/')
|
||||
abort();
|
||||
q[-1] = '\0'; /* delete trailing '/' */
|
||||
#ifdef notdef /* this is what the System V shell claims to do (it lies) */
|
||||
if (stat(p, &statb) < 0)
|
||||
statb.st_mtime = 0;
|
||||
if (!silent
|
||||
&& statb.st_size > 0
|
||||
&& statb.st_mtime > mailtime[i]
|
||||
&& statb.st_mtime > statb.st_atime
|
||||
) {
|
||||
out2str(pathopt? pathopt : "You have mail");
|
||||
if (statb.st_mtime > mailtime[i] && ! silent) {
|
||||
out2str(pathopt? pathopt : "you have mail");
|
||||
out2c('\n');
|
||||
}
|
||||
mailtime[i] = statb.st_mtime;
|
||||
#else /* this is what it should do */
|
||||
if (stat(p, &statb) < 0)
|
||||
statb.st_size = 0;
|
||||
if (statb.st_size > mailtime[i] && ! silent) {
|
||||
out2str(pathopt? pathopt : "you have mail");
|
||||
out2c('\n');
|
||||
}
|
||||
mailtime[i] = statb.st_size;
|
||||
#endif
|
||||
}
|
||||
nmboxes = i;
|
||||
popstackmark(&smark);
|
||||
}
|
||||
|
||||
/*
|
||||
* $PchId: mail.c,v 1.5 2006/05/22 12:02:37 philip Exp $
|
||||
*/
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*-
|
||||
* Copyright (c) 1991 The Regents of the University of California.
|
||||
* All rights reserved.
|
||||
* 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.
|
||||
@@ -13,10 +13,6 @@
|
||||
* 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.
|
||||
@@ -33,11 +29,12 @@
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)mail.h 5.1 (Berkeley) 3/7/91
|
||||
* @(#)mail.h 8.2 (Berkeley) 5/4/95
|
||||
* $FreeBSD: src/bin/sh/mail.h,v 1.8 2004/04/06 20:06:51 markm Exp $
|
||||
*/
|
||||
|
||||
#ifdef __STDC__
|
||||
void chkmail(int);
|
||||
#else
|
||||
void chkmail();
|
||||
#endif
|
||||
|
||||
/*
|
||||
* $PchId: mail.h,v 1.3 2006/03/30 11:53:44 philip Exp $
|
||||
*/
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*-
|
||||
* Copyright (c) 1991 The Regents of the University of California.
|
||||
* All rights reserved.
|
||||
* 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.
|
||||
@@ -13,10 +13,6 @@
|
||||
* 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.
|
||||
@@ -35,18 +31,29 @@
|
||||
*/
|
||||
|
||||
#ifndef lint
|
||||
char copyright[] =
|
||||
"@(#) Copyright (c) 1991 The Regents of the University of California.\n\
|
||||
All rights reserved.\n";
|
||||
static char const copyright[] =
|
||||
"@(#) Copyright (c) 1991, 1993\n\
|
||||
The Regents of the University of California. All rights reserved.\n";
|
||||
#endif /* not lint */
|
||||
|
||||
#ifndef lint
|
||||
static char sccsid[] = "@(#)main.c 5.2 (Berkeley) 3/13/91";
|
||||
#if 0
|
||||
static char sccsid[] = "@(#)main.c 8.6 (Berkeley) 5/28/95";
|
||||
#endif
|
||||
#endif /* not lint */
|
||||
/*
|
||||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD: src/bin/sh/main.c,v 1.26 2004/04/06 20:06:51 markm Exp $");
|
||||
*/
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <stdio.h>
|
||||
#include <signal.h>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <locale.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include "shell.h"
|
||||
#include "main.h"
|
||||
#include "mail.h"
|
||||
@@ -54,38 +61,26 @@ static char sccsid[] = "@(#)main.c 5.2 (Berkeley) 3/13/91";
|
||||
#include "output.h"
|
||||
#include "parser.h"
|
||||
#include "nodes.h"
|
||||
#include "expand.h"
|
||||
#include "eval.h"
|
||||
#include "jobs.h"
|
||||
#include "input.h"
|
||||
#include "trap.h"
|
||||
#if ATTY
|
||||
#include "var.h"
|
||||
#endif
|
||||
#include "show.h"
|
||||
#include "memalloc.h"
|
||||
#include "error.h"
|
||||
#include "init.h"
|
||||
#include "mystring.h"
|
||||
|
||||
#define PROFILE 0
|
||||
#include "exec.h"
|
||||
#include "cd.h"
|
||||
#include "builtins.h"
|
||||
|
||||
int rootpid;
|
||||
int rootshell;
|
||||
STATIC union node *curcmd;
|
||||
STATIC union node *prevcmd;
|
||||
extern int errno;
|
||||
#if PROFILE
|
||||
short profile_buf[16384];
|
||||
extern int etext();
|
||||
#endif
|
||||
|
||||
#ifdef __STDC__
|
||||
STATIC void read_profile(char *);
|
||||
char *getenv(char *);
|
||||
#else
|
||||
STATIC void read_profile();
|
||||
char *getenv();
|
||||
#endif
|
||||
|
||||
STATIC char *find_dot_file(char *);
|
||||
|
||||
/*
|
||||
* Main routine. We initialize things, parse the arguments, execute
|
||||
@@ -95,16 +90,15 @@ char *getenv();
|
||||
* is used to figure out how far we had gotten.
|
||||
*/
|
||||
|
||||
main(argc, argv) char **argv; {
|
||||
int
|
||||
main(int argc, char *argv[])
|
||||
{
|
||||
struct jmploc jmploc;
|
||||
struct stackmark smark;
|
||||
volatile int state;
|
||||
char *shinit, *home;
|
||||
char *profile = NULL, *ashrc = NULL;
|
||||
char *shinit;
|
||||
|
||||
#if PROFILE
|
||||
monitor(4, etext, profile_buf, sizeof profile_buf, 50);
|
||||
#endif
|
||||
(void) setlocale(LC_ALL, "");
|
||||
state = 0;
|
||||
if (setjmp(jmploc.loc)) {
|
||||
/*
|
||||
@@ -112,20 +106,32 @@ main(argc, argv) char **argv; {
|
||||
* exception EXSHELLPROC to clean up before executing
|
||||
* the shell procedure.
|
||||
*/
|
||||
if (exception == EXSHELLPROC) {
|
||||
switch (exception) {
|
||||
case EXSHELLPROC:
|
||||
rootpid = getpid();
|
||||
rootshell = 1;
|
||||
minusc = NULL;
|
||||
state = 3;
|
||||
} else if (state == 0 || iflag == 0 || ! rootshell)
|
||||
exitshell(2);
|
||||
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 ATTY
|
||||
if (exception == EXINT
|
||||
&& (! attyset() || equal(termval(), "emacs"))) {
|
||||
#else
|
||||
if (exception == EXINT) {
|
||||
#endif
|
||||
out2c('\n');
|
||||
flushout(&errout);
|
||||
}
|
||||
@@ -150,57 +156,38 @@ main(argc, argv) char **argv; {
|
||||
init();
|
||||
setstackmark(&smark);
|
||||
procargs(argc, argv);
|
||||
if (eflag) eflag = 2; /* Truly enable [ex]flag after init. */
|
||||
if (xflag) xflag = 2;
|
||||
if (getpwd() == NULL && iflag)
|
||||
out2str("sh: cannot determine working directory\n");
|
||||
if (argv[0] && argv[0][0] == '-') {
|
||||
state = 1;
|
||||
read_profile("/etc/profile");
|
||||
state1:
|
||||
state = 2;
|
||||
if ((home = getenv("HOME")) != NULL
|
||||
&& (profile = (char *) malloc(strlen(home) + 10)) != NULL)
|
||||
{
|
||||
strcpy(profile, home);
|
||||
strcat(profile, "/.profile");
|
||||
read_profile(profile);
|
||||
} else {
|
||||
if (privileged == 0)
|
||||
read_profile(".profile");
|
||||
}
|
||||
} else if ((sflag || minusc) && (shinit = getenv("SHINIT")) != NULL) {
|
||||
state = 2;
|
||||
evalstring(shinit);
|
||||
else
|
||||
read_profile("/etc/suid_profile");
|
||||
}
|
||||
state2:
|
||||
if (profile != NULL) free(profile);
|
||||
|
||||
state = 3;
|
||||
if (!argv[0] || argv[0][0] != '-') {
|
||||
if ((home = getenv("HOME")) != NULL
|
||||
&& (ashrc = (char *) malloc(strlen(home) + 8)) != NULL)
|
||||
{
|
||||
strcpy(ashrc, home);
|
||||
strcat(ashrc, "/.ashrc");
|
||||
read_profile(ashrc);
|
||||
if (!privileged && iflag) {
|
||||
if ((shinit = lookupvar("ENV")) != NULL && *shinit != '\0') {
|
||||
state = 3;
|
||||
read_profile(shinit);
|
||||
}
|
||||
}
|
||||
state3:
|
||||
if (ashrc != NULL) free(ashrc);
|
||||
if (eflag) eflag = 1; /* Init done, enable [ex]flag */
|
||||
if (xflag) xflag = 1;
|
||||
exitstatus = 0; /* Init shouldn't influence initial $? */
|
||||
|
||||
state = 4;
|
||||
if (minusc) {
|
||||
evalstring(minusc);
|
||||
}
|
||||
if (sflag || minusc == NULL) {
|
||||
state4:
|
||||
state4: /* XXX ??? - why isn't this before the "if" statement */
|
||||
cmdloop(1);
|
||||
}
|
||||
#if PROFILE
|
||||
monitor(0);
|
||||
#endif
|
||||
exitshell(exitstatus);
|
||||
/*NOTREACHED*/
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -210,52 +197,49 @@ state4:
|
||||
*/
|
||||
|
||||
void
|
||||
cmdloop(top) {
|
||||
cmdloop(int top)
|
||||
{
|
||||
union node *n;
|
||||
struct stackmark smark;
|
||||
int inter;
|
||||
int numeof;
|
||||
int numeof = 0;
|
||||
|
||||
TRACE(("cmdloop(%d) called\n", top));
|
||||
setstackmark(&smark);
|
||||
numeof = 0;
|
||||
for (;;) {
|
||||
if (pendingsigs)
|
||||
dotrap();
|
||||
inter = 0;
|
||||
if (iflag && top) {
|
||||
inter++;
|
||||
showjobs(1);
|
||||
showjobs(1, 0, 0);
|
||||
chkmail(0);
|
||||
flushout(&output);
|
||||
}
|
||||
n = parsecmd(inter);
|
||||
#if DEBUG
|
||||
/* showtree(n); */
|
||||
#endif
|
||||
/* showtree(n); DEBUG */
|
||||
if (n == NEOF) {
|
||||
if (Iflag == 0 || numeof >= 50)
|
||||
if (!top || numeof >= 50)
|
||||
break;
|
||||
out2str("\nUse \"exit\" to leave shell.\n");
|
||||
if (!stoppedjobs()) {
|
||||
if (!Iflag)
|
||||
break;
|
||||
out2str("\nUse \"exit\" to leave shell.\n");
|
||||
}
|
||||
numeof++;
|
||||
} else if (n != NULL && nflag == 0) {
|
||||
if (inter) {
|
||||
INTOFF;
|
||||
if (prevcmd)
|
||||
freefunc(prevcmd);
|
||||
prevcmd = curcmd;
|
||||
curcmd = copyfunc(n);
|
||||
INTON;
|
||||
}
|
||||
job_warning = (job_warning == 2) ? 1 : 0;
|
||||
numeof = 0;
|
||||
evaltree(n, 0);
|
||||
#ifdef notdef
|
||||
if (exitstatus) /*DEBUG*/
|
||||
outfmt(&errout, "Exit status 0x%X\n", exitstatus);
|
||||
#endif
|
||||
}
|
||||
popstackmark(&smark);
|
||||
setstackmark(&smark);
|
||||
if (evalskip == SKIPFILE) {
|
||||
evalskip = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
popstackmark(&smark); /* unnecessary */
|
||||
popstackmark(&smark);
|
||||
}
|
||||
|
||||
|
||||
@@ -265,9 +249,8 @@ cmdloop(top) {
|
||||
*/
|
||||
|
||||
STATIC void
|
||||
read_profile(name)
|
||||
char *name;
|
||||
{
|
||||
read_profile(char *name)
|
||||
{
|
||||
int fd;
|
||||
|
||||
INTOFF;
|
||||
@@ -287,32 +270,63 @@ read_profile(name)
|
||||
*/
|
||||
|
||||
void
|
||||
readcmdfile(name)
|
||||
char *name;
|
||||
{
|
||||
readcmdfile(char *name)
|
||||
{
|
||||
int fd;
|
||||
|
||||
INTOFF;
|
||||
if ((fd = open(name, O_RDONLY)) >= 0)
|
||||
setinputfd(fd, 1);
|
||||
else
|
||||
error("Can't open %s", name);
|
||||
error("Can't open %s: %s", name, strerror(errno));
|
||||
INTON;
|
||||
cmdloop(0);
|
||||
popfile();
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Take commands from a file. To be compatable we should do a path
|
||||
* search for the file, but a path search doesn't make any sense.
|
||||
* Take commands from a file. To be compatible we should do a path
|
||||
* search for the file, which is necessary to find sub-commands.
|
||||
*/
|
||||
|
||||
dotcmd(argc, argv) char **argv; {
|
||||
|
||||
STATIC char *
|
||||
find_dot_file(char *basename)
|
||||
{
|
||||
static char localname[FILENAME_MAX+1];
|
||||
char *fullname;
|
||||
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) {
|
||||
strcpy(localname, fullname);
|
||||
stunalloc(fullname);
|
||||
if ((stat(fullname, &statb) == 0) && S_ISREG(statb.st_mode))
|
||||
return localname;
|
||||
}
|
||||
return basename;
|
||||
}
|
||||
|
||||
int
|
||||
dotcmd(int argc, char **argv)
|
||||
{
|
||||
struct strlist *sp;
|
||||
exitstatus = 0;
|
||||
|
||||
for (sp = cmdenviron; sp ; sp = sp->next)
|
||||
setvareq(savestr(sp->text), VSTRFIXED|VTEXTFIXED);
|
||||
|
||||
if (argc >= 2) { /* That's what SVR2 does */
|
||||
setinputfile(argv[1], 1);
|
||||
commandname = argv[1];
|
||||
char *fullname = find_dot_file(argv[1]);
|
||||
|
||||
setinputfile(fullname, 1);
|
||||
commandname = fullname;
|
||||
cmdloop(0);
|
||||
popfile();
|
||||
}
|
||||
@@ -320,40 +334,22 @@ dotcmd(argc, argv) char **argv; {
|
||||
}
|
||||
|
||||
|
||||
exitcmd(argc, argv) char **argv; {
|
||||
int
|
||||
exitcmd(int argc, char **argv)
|
||||
{
|
||||
extern int oexitstatus;
|
||||
|
||||
if (stoppedjobs())
|
||||
return 0;
|
||||
if (argc > 1)
|
||||
exitstatus = number(argv[1]);
|
||||
else
|
||||
exitstatus = oexitstatus;
|
||||
exitshell(exitstatus);
|
||||
/*NOTREACHED*/
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
lccmd(argc, argv) char **argv; {
|
||||
if (argc > 1) {
|
||||
defun(argv[1], prevcmd);
|
||||
return 0;
|
||||
} else {
|
||||
INTOFF;
|
||||
freefunc(curcmd);
|
||||
curcmd = prevcmd;
|
||||
prevcmd = NULL;
|
||||
INTON;
|
||||
evaltree(curcmd, 0);
|
||||
return exitstatus;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
#ifdef notdef
|
||||
/*
|
||||
* Should never be called.
|
||||
* $PchId: main.c,v 1.5 2006/05/22 12:03:02 philip Exp $
|
||||
*/
|
||||
|
||||
void
|
||||
exit(exitstatus) {
|
||||
_exit(exitstatus);
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*-
|
||||
* Copyright (c) 1991 The Regents of the University of California.
|
||||
* All rights reserved.
|
||||
* 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.
|
||||
@@ -13,10 +13,6 @@
|
||||
* 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.
|
||||
@@ -33,16 +29,18 @@
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)main.h 5.1 (Berkeley) 3/7/91
|
||||
* @(#)main.h 8.2 (Berkeley) 5/4/95
|
||||
* $FreeBSD: src/bin/sh/main.h,v 1.8 2004/04/06 20:06:51 markm Exp $
|
||||
*/
|
||||
|
||||
extern int rootpid; /* pid of main shell */
|
||||
extern int rootshell; /* true if we aren't a child of the main shell */
|
||||
|
||||
#ifdef __STDC__
|
||||
void readcmdfile(char *);
|
||||
void cmdloop(int);
|
||||
#else
|
||||
void readcmdfile();
|
||||
void cmdloop();
|
||||
#endif
|
||||
int dotcmd(int, char **);
|
||||
int exitcmd(int, char **);
|
||||
|
||||
/*
|
||||
* $PchId: main.h,v 1.3 2006/03/30 11:43:59 philip Exp $
|
||||
*/
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*-
|
||||
* Copyright (c) 1991 The Regents of the University of California.
|
||||
* All rights reserved.
|
||||
* 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.
|
||||
@@ -13,10 +13,6 @@
|
||||
* 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.
|
||||
@@ -35,24 +31,33 @@
|
||||
*/
|
||||
|
||||
#ifndef lint
|
||||
static char sccsid[] = "@(#)memalloc.c 5.2 (Berkeley) 3/13/91";
|
||||
#if 0
|
||||
static char sccsid[] = "@(#)memalloc.c 8.3 (Berkeley) 5/4/95";
|
||||
#endif
|
||||
#endif /* not lint */
|
||||
/*
|
||||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD: src/bin/sh/memalloc.c,v 1.26 2004/04/06 20:06:51 markm Exp $");
|
||||
*/
|
||||
|
||||
#include "shell.h"
|
||||
#include "output.h"
|
||||
#include "machdep.h"
|
||||
#include "memalloc.h"
|
||||
#include "error.h"
|
||||
#include "machdep.h"
|
||||
#include "mystring.h"
|
||||
#include "expand.h"
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
|
||||
/*
|
||||
* Like malloc, but returns an error when out of space.
|
||||
*/
|
||||
|
||||
pointer
|
||||
ckmalloc(nbytes) {
|
||||
register pointer p;
|
||||
pointer malloc();
|
||||
ckmalloc(int nbytes)
|
||||
{
|
||||
pointer p;
|
||||
|
||||
if ((p = malloc(nbytes)) == NULL)
|
||||
error("Out of space");
|
||||
@@ -65,11 +70,8 @@ ckmalloc(nbytes) {
|
||||
*/
|
||||
|
||||
pointer
|
||||
ckrealloc(p, nbytes)
|
||||
register pointer p;
|
||||
{
|
||||
pointer realloc();
|
||||
|
||||
ckrealloc(pointer p, int nbytes)
|
||||
{
|
||||
if ((p = realloc(p, nbytes)) == NULL)
|
||||
error("Out of space");
|
||||
return p;
|
||||
@@ -81,10 +83,9 @@ ckrealloc(p, nbytes)
|
||||
*/
|
||||
|
||||
char *
|
||||
savestr(s)
|
||||
char *s;
|
||||
{
|
||||
register char *p;
|
||||
savestr(char *s)
|
||||
{
|
||||
char *p;
|
||||
|
||||
p = ckmalloc(strlen(s) + 1);
|
||||
scopy(s, p);
|
||||
@@ -97,47 +98,56 @@ savestr(s)
|
||||
* 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.
|
||||
* The size 496 was chosen because with 16-byte alignment the total size
|
||||
* for the allocated block is 512.
|
||||
*/
|
||||
|
||||
#define MINSIZE 504 /* minimum size of a block */
|
||||
#define MINSIZE 496 /* minimum size of a block. */
|
||||
|
||||
|
||||
struct stack_block {
|
||||
struct stack_block *prev;
|
||||
char space[MINSIZE];
|
||||
/* Data follows */
|
||||
};
|
||||
#define SPACE(sp) ((char*)(sp) + ALIGN(sizeof(struct stack_block)))
|
||||
|
||||
struct stack_block stackbase;
|
||||
struct stack_block *stackp = &stackbase;
|
||||
char *stacknxt = stackbase.space;
|
||||
int stacknleft = MINSIZE;
|
||||
STATIC struct stack_block *stackp;
|
||||
STATIC struct stackmark *markp;
|
||||
char *stacknxt;
|
||||
int stacknleft;
|
||||
int sstrnleft;
|
||||
int herefd = -1;
|
||||
|
||||
|
||||
static void
|
||||
stnewblock(int nbytes)
|
||||
{
|
||||
struct stack_block *sp;
|
||||
int allocsize;
|
||||
|
||||
if (nbytes < MINSIZE)
|
||||
nbytes = MINSIZE;
|
||||
|
||||
allocsize = ALIGN(sizeof(struct stack_block)) + ALIGN(nbytes);
|
||||
|
||||
INTOFF;
|
||||
sp = ckmalloc(allocsize);
|
||||
sp->prev = stackp;
|
||||
stacknxt = SPACE(sp);
|
||||
stacknleft = allocsize - (stacknxt - (char*)sp);
|
||||
stackp = sp;
|
||||
INTON;
|
||||
}
|
||||
|
||||
|
||||
pointer
|
||||
stalloc(nbytes) {
|
||||
register char *p;
|
||||
stalloc(int nbytes)
|
||||
{
|
||||
char *p;
|
||||
|
||||
nbytes = 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;
|
||||
}
|
||||
if (nbytes > stacknleft)
|
||||
stnewblock(nbytes);
|
||||
p = stacknxt;
|
||||
stacknxt += nbytes;
|
||||
stacknleft -= nbytes;
|
||||
@@ -146,11 +156,10 @@ stalloc(nbytes) {
|
||||
|
||||
|
||||
void
|
||||
stunalloc(p)
|
||||
pointer p;
|
||||
{
|
||||
stunalloc(pointer p)
|
||||
{
|
||||
if (p == NULL) { /*DEBUG */
|
||||
write(2, "stunalloc\n", 10);
|
||||
write(STDERR_FILENO, "stunalloc\n", 10);
|
||||
abort();
|
||||
}
|
||||
stacknleft += stacknxt - (char *)p;
|
||||
@@ -160,22 +169,23 @@ stunalloc(p)
|
||||
|
||||
|
||||
void
|
||||
setstackmark(mark)
|
||||
struct stackmark *mark;
|
||||
{
|
||||
setstackmark(struct stackmark *mark)
|
||||
{
|
||||
mark->stackp = stackp;
|
||||
mark->stacknxt = stacknxt;
|
||||
mark->stacknleft = stacknleft;
|
||||
mark->marknext = markp;
|
||||
markp = mark;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
popstackmark(mark)
|
||||
struct stackmark *mark;
|
||||
{
|
||||
popstackmark(struct stackmark *mark)
|
||||
{
|
||||
struct stack_block *sp;
|
||||
|
||||
INTOFF;
|
||||
markp = mark->marknext;
|
||||
while (stackp != mark->stackp) {
|
||||
sp = stackp;
|
||||
stackp = sp->prev;
|
||||
@@ -198,35 +208,56 @@ popstackmark(mark)
|
||||
*/
|
||||
|
||||
void
|
||||
growstackblock() {
|
||||
growstackblock(void)
|
||||
{
|
||||
char *p;
|
||||
int newlen = stacknleft * 2 + 100;
|
||||
char *oldspace = stacknxt;
|
||||
int oldlen = stacknleft;
|
||||
int newlen;
|
||||
char *oldspace;
|
||||
int oldlen;
|
||||
struct stack_block *sp;
|
||||
struct stack_block *oldstackp;
|
||||
struct stackmark *xmark;
|
||||
|
||||
if (stacknxt == stackp->space && stackp != &stackbase) {
|
||||
newlen = (stacknleft == 0) ? MINSIZE : stacknleft * 2 + 100;
|
||||
newlen = ALIGN(newlen);
|
||||
oldspace = stacknxt;
|
||||
oldlen = stacknleft;
|
||||
|
||||
if (stackp != NULL && stacknxt == SPACE(stackp)) {
|
||||
INTOFF;
|
||||
sp = stackp;
|
||||
stackp = sp->prev;
|
||||
sp = ckrealloc((pointer)sp, sizeof(struct stack_block) - MINSIZE + newlen);
|
||||
oldstackp = stackp;
|
||||
stackp = oldstackp->prev;
|
||||
sp = ckrealloc((pointer)oldstackp, newlen);
|
||||
sp->prev = stackp;
|
||||
stackp = sp;
|
||||
stacknxt = sp->space;
|
||||
stacknleft = newlen;
|
||||
stacknxt = SPACE(sp);
|
||||
stacknleft = newlen - (stacknxt - (char*)sp);
|
||||
|
||||
/*
|
||||
* 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 {
|
||||
p = stalloc(newlen);
|
||||
bcopy(oldspace, p, oldlen);
|
||||
stacknxt = p; /* free the space */
|
||||
stacknleft += newlen; /* we just allocated */
|
||||
if (oldlen != 0)
|
||||
memcpy(p, oldspace, oldlen);
|
||||
stunalloc(p);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
grabstackblock(len) {
|
||||
grabstackblock(int len)
|
||||
{
|
||||
len = ALIGN(len);
|
||||
stacknxt += len;
|
||||
stacknleft -= len;
|
||||
@@ -254,8 +285,11 @@ grabstackblock(len) {
|
||||
|
||||
|
||||
char *
|
||||
growstackstr() {
|
||||
int len = stackblocksize();
|
||||
growstackstr(void)
|
||||
{
|
||||
int len;
|
||||
|
||||
len = stackblocksize();
|
||||
if (herefd >= 0 && len >= 1024) {
|
||||
xwrite(herefd, stackblock(), len);
|
||||
sstrnleft = len - 1;
|
||||
@@ -272,8 +306,11 @@ growstackstr() {
|
||||
*/
|
||||
|
||||
char *
|
||||
makestrspace() {
|
||||
int len = stackblocksize() - sstrnleft;
|
||||
makestrspace(void)
|
||||
{
|
||||
int len;
|
||||
|
||||
len = stackblocksize() - sstrnleft;
|
||||
growstackblock();
|
||||
sstrnleft = stackblocksize() - len;
|
||||
return stackblock() + len;
|
||||
@@ -282,11 +319,13 @@ makestrspace() {
|
||||
|
||||
|
||||
void
|
||||
ungrabstackstr(s, p)
|
||||
char *s;
|
||||
char *p;
|
||||
{
|
||||
ungrabstackstr(char *s, char *p)
|
||||
{
|
||||
stacknleft += stacknxt - s;
|
||||
stacknxt = s;
|
||||
sstrnleft = stacknleft - (p - s);
|
||||
}
|
||||
|
||||
/*
|
||||
* $PchId: memalloc.c,v 1.5 2006/05/22 12:03:26 philip Exp $
|
||||
*/
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*-
|
||||
* Copyright (c) 1991 The Regents of the University of California.
|
||||
* All rights reserved.
|
||||
* 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.
|
||||
@@ -13,10 +13,6 @@
|
||||
* 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.
|
||||
@@ -33,13 +29,15 @@
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)memalloc.h 5.1 (Berkeley) 3/7/91
|
||||
* @(#)memalloc.h 8.2 (Berkeley) 5/4/95
|
||||
* $FreeBSD: src/bin/sh/memalloc.h,v 1.9 2004/04/06 20:06:51 markm Exp $
|
||||
*/
|
||||
|
||||
struct stackmark {
|
||||
struct stack_block *stackp;
|
||||
char *stacknxt;
|
||||
int stacknleft;
|
||||
struct stackmark *marknext;
|
||||
};
|
||||
|
||||
|
||||
@@ -48,10 +46,8 @@ extern int stacknleft;
|
||||
extern int sstrnleft;
|
||||
extern int herefd;
|
||||
|
||||
#ifdef __STDC__
|
||||
pointer ckmalloc(int);
|
||||
pointer ckrealloc(pointer, int);
|
||||
void free(pointer); /* defined in C library */
|
||||
char *savestr(char *);
|
||||
pointer stalloc(int);
|
||||
void stunalloc(pointer);
|
||||
@@ -62,21 +58,6 @@ void grabstackblock(int);
|
||||
char *growstackstr(void);
|
||||
char *makestrspace(void);
|
||||
void ungrabstackstr(char *, char *);
|
||||
#else
|
||||
pointer ckmalloc();
|
||||
pointer ckrealloc();
|
||||
void free(); /* defined in C library */
|
||||
char *savestr();
|
||||
pointer stalloc();
|
||||
void stunalloc();
|
||||
void setstackmark();
|
||||
void popstackmark();
|
||||
void growstackblock();
|
||||
void grabstackblock();
|
||||
char *growstackstr();
|
||||
char *makestrspace();
|
||||
void ungrabstackstr();
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
@@ -84,7 +65,7 @@ void ungrabstackstr();
|
||||
#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(); else
|
||||
#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)
|
||||
@@ -93,3 +74,7 @@ void ungrabstackstr();
|
||||
#define grabstackstr(p) stalloc(stackblocksize() - sstrnleft)
|
||||
|
||||
#define ckfree(p) free((pointer)(p))
|
||||
|
||||
/*
|
||||
* $PchId: memalloc.h,v 1.3 2006/03/30 11:39:41 philip Exp $
|
||||
*/
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*-
|
||||
* Copyright (c) 1991 The Regents of the University of California.
|
||||
* All rights reserved.
|
||||
* 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.
|
||||
@@ -13,10 +13,6 @@
|
||||
* 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.
|
||||
@@ -35,13 +31,32 @@
|
||||
*/
|
||||
|
||||
#ifndef lint
|
||||
static char sccsid[] = "@(#)miscbltin.c 5.2 (Berkeley) 3/13/91";
|
||||
#if 0
|
||||
static char sccsid[] = "@(#)miscbltin.c 8.4 (Berkeley) 5/4/95";
|
||||
#endif
|
||||
#endif /* not lint */
|
||||
/*
|
||||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD: src/bin/sh/miscbltin.c,v 1.30 2004/04/06 20:06:51 markm Exp $");
|
||||
*/
|
||||
|
||||
/*
|
||||
* Miscelaneous builtins.
|
||||
* Miscellaneous builtins.
|
||||
*/
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/select.h>
|
||||
#include <time.h>
|
||||
#include <unistd.h>
|
||||
#include <ctype.h>
|
||||
#include <errno.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <termios.h>
|
||||
|
||||
#include "shell.h"
|
||||
#include "options.h"
|
||||
#include "var.h"
|
||||
@@ -49,38 +64,71 @@ static char sccsid[] = "@(#)miscbltin.c 5.2 (Berkeley) 3/13/91";
|
||||
#include "memalloc.h"
|
||||
#include "error.h"
|
||||
#include "mystring.h"
|
||||
#include "builtins.h"
|
||||
|
||||
#undef eflag
|
||||
|
||||
extern char **argptr; /* argument list for builtin command */
|
||||
|
||||
|
||||
/*
|
||||
* The read builtin. The -e option causes backslashes to escape the
|
||||
* following character.
|
||||
* The read builtin. The -r option causes backslashes to be treated like
|
||||
* ordinary characters.
|
||||
*
|
||||
* This uses unbuffered input, which may be avoidable in some cases.
|
||||
*/
|
||||
|
||||
readcmd(argc, argv) char **argv; {
|
||||
int
|
||||
readcmd(int argc __unused, char **argv __unused)
|
||||
{
|
||||
char **ap;
|
||||
int backslash;
|
||||
char c;
|
||||
int eflag;
|
||||
int rflag;
|
||||
char *prompt;
|
||||
char *ifs;
|
||||
char *p;
|
||||
int startword;
|
||||
int status;
|
||||
int i;
|
||||
struct timeval tv;
|
||||
char *tvptr;
|
||||
#ifndef __minix_vmd
|
||||
fd_set ifds;
|
||||
#endif
|
||||
struct termios told, tnew;
|
||||
int tsaved;
|
||||
|
||||
eflag = 0;
|
||||
rflag = 0;
|
||||
prompt = NULL;
|
||||
while ((i = nextopt("ep:")) != '\0') {
|
||||
if (i == 'p')
|
||||
prompt = optarg;
|
||||
else
|
||||
eflag = 1;
|
||||
tv.tv_sec = -1;
|
||||
tv.tv_usec = 0;
|
||||
while ((i = nextopt("erp:t:")) != '\0') {
|
||||
switch(i) {
|
||||
case 'p':
|
||||
prompt = shoptarg;
|
||||
break;
|
||||
case 'e':
|
||||
break;
|
||||
case 'r':
|
||||
rflag = 1;
|
||||
break;
|
||||
case 't':
|
||||
tv.tv_sec = strtol(shoptarg, &tvptr, 0);
|
||||
if (tvptr == shoptarg)
|
||||
error("timeout value");
|
||||
switch(*tvptr) {
|
||||
case 0:
|
||||
case 's':
|
||||
break;
|
||||
case 'h':
|
||||
tv.tv_sec *= 60;
|
||||
/* FALLTHROUGH */
|
||||
case 'm':
|
||||
tv.tv_sec *= 60;
|
||||
break;
|
||||
default:
|
||||
error("timeout unit");
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (prompt && isatty(0)) {
|
||||
out2str(prompt);
|
||||
@@ -90,12 +138,45 @@ readcmd(argc, argv) char **argv; {
|
||||
error("arg count");
|
||||
if ((ifs = bltinlookup("IFS", 1)) == NULL)
|
||||
ifs = nullstr;
|
||||
|
||||
if (tv.tv_sec >= 0) {
|
||||
#ifdef __minix
|
||||
abort();
|
||||
#else
|
||||
/*
|
||||
* See if we can disable input processing; this will
|
||||
* not give the desired result if we are in a pipeline
|
||||
* and someone upstream is still in line-by-line mode.
|
||||
*/
|
||||
tsaved = 0;
|
||||
if (tcgetattr(0, &told) == 0) {
|
||||
memcpy(&tnew, &told, sizeof(told));
|
||||
cfmakeraw(&tnew);
|
||||
tcsetattr(0, TCSANOW, &tnew);
|
||||
tsaved = 1;
|
||||
}
|
||||
/*
|
||||
* Wait for something to become available.
|
||||
*/
|
||||
FD_ZERO(&ifds);
|
||||
FD_SET(0, &ifds);
|
||||
status = select(1, &ifds, NULL, NULL, &tv);
|
||||
if (tsaved)
|
||||
tcsetattr(0, TCSANOW, &told);
|
||||
/*
|
||||
* If there's nothing ready, return an error.
|
||||
*/
|
||||
if (status <= 0)
|
||||
return(1);
|
||||
#endif
|
||||
}
|
||||
|
||||
status = 0;
|
||||
startword = 1;
|
||||
backslash = 0;
|
||||
STARTSTACKSTR(p);
|
||||
for (;;) {
|
||||
if (read(0, &c, 1) != 1) {
|
||||
if (read(STDIN_FILENO, &c, 1) != 1) {
|
||||
status = 1;
|
||||
break;
|
||||
}
|
||||
@@ -107,7 +188,7 @@ readcmd(argc, argv) char **argv; {
|
||||
STPUTC(c, p);
|
||||
continue;
|
||||
}
|
||||
if (eflag && c == '\\') {
|
||||
if (!rflag && c == '\\') {
|
||||
backslash++;
|
||||
continue;
|
||||
}
|
||||
@@ -118,7 +199,7 @@ readcmd(argc, argv) char **argv; {
|
||||
}
|
||||
startword = 0;
|
||||
if (backslash && c == '\\') {
|
||||
if (read(0, &c, 1) != 1) {
|
||||
if (read(STDIN_FILENO, &c, 1) != 1) {
|
||||
status = 1;
|
||||
break;
|
||||
}
|
||||
@@ -142,25 +223,274 @@ readcmd(argc, argv) char **argv; {
|
||||
|
||||
|
||||
|
||||
umaskcmd(argc, argv) char **argv; {
|
||||
int
|
||||
umaskcmd(int argc __unused, char **argv)
|
||||
{
|
||||
char *ap;
|
||||
int mask;
|
||||
char *p;
|
||||
int i;
|
||||
int symbolic_mode = 0;
|
||||
|
||||
if ((p = argv[1]) == NULL) {
|
||||
INTOFF;
|
||||
mask = umask(0);
|
||||
umask(mask);
|
||||
INTON;
|
||||
out1fmt("%.4o\n", mask); /* %#o might be better */
|
||||
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 {
|
||||
mask = 0;
|
||||
do {
|
||||
if ((unsigned)(i = *p - '0') >= 8)
|
||||
error("Illegal number: %s", argv[1]);
|
||||
mask = (mask << 3) + i;
|
||||
} while (*++p != '\0');
|
||||
umask(mask);
|
||||
if (isdigit(*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 {
|
||||
void *set;
|
||||
if ((set = setmode (ap)) == 0)
|
||||
error("Illegal number: %s", ap);
|
||||
|
||||
mask = getmode (set, ~mask & 0777);
|
||||
umask(~mask & 0777);
|
||||
free(set);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef __minix
|
||||
struct rlimit
|
||||
{
|
||||
unsigned long rlim_cur; /* current (soft) limit */
|
||||
unsigned long rlim_max; /* maximum value for rlim_cur */
|
||||
};
|
||||
#define RLIM_INFINITY (((unsigned long)1 << 31) - 1)
|
||||
|
||||
int getrlimit (int, struct rlimit *);
|
||||
int setrlimit (int, const struct rlimit *);
|
||||
|
||||
int getrlimit(resource, rlp)
|
||||
int resource;
|
||||
struct rlimit *rlp;
|
||||
{
|
||||
errno= ENOSYS;
|
||||
return -1;
|
||||
}
|
||||
int setrlimit(resource, rlp)
|
||||
int resource;
|
||||
const struct rlimit *rlp;
|
||||
{
|
||||
errno= ENOSYS;
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* 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;
|
||||
const char *units;
|
||||
int cmd;
|
||||
int factor; /* multiply by to get rlim_{cur,max} values */
|
||||
char option;
|
||||
};
|
||||
|
||||
static const struct limits limits[] = {
|
||||
#ifdef RLIMIT_CPU
|
||||
{ "cpu time", "seconds", RLIMIT_CPU, 1, 't' },
|
||||
#endif
|
||||
#ifdef RLIMIT_FSIZE
|
||||
{ "file size", "512-blocks", RLIMIT_FSIZE, 512, 'f' },
|
||||
#endif
|
||||
#ifdef RLIMIT_DATA
|
||||
{ "data seg size", "kbytes", RLIMIT_DATA, 1024, 'd' },
|
||||
#endif
|
||||
#ifdef RLIMIT_STACK
|
||||
{ "stack size", "kbytes", RLIMIT_STACK, 1024, 's' },
|
||||
#endif
|
||||
#ifdef RLIMIT_CORE
|
||||
{ "core file size", "512-blocks", RLIMIT_CORE, 512, 'c' },
|
||||
#endif
|
||||
#ifdef RLIMIT_RSS
|
||||
{ "max memory size", "kbytes", RLIMIT_RSS, 1024, 'm' },
|
||||
#endif
|
||||
#ifdef RLIMIT_MEMLOCK
|
||||
{ "locked memory", "kbytes", RLIMIT_MEMLOCK, 1024, 'l' },
|
||||
#endif
|
||||
#ifdef RLIMIT_NPROC
|
||||
{ "max user processes", (char *)0, RLIMIT_NPROC, 1, 'u' },
|
||||
#endif
|
||||
#ifdef RLIMIT_NOFILE
|
||||
{ "open files", (char *)0, RLIMIT_NOFILE, 1, 'n' },
|
||||
#endif
|
||||
#ifdef RLIMIT_VMEM
|
||||
{ "virtual mem size", "kbytes", RLIMIT_VMEM, 1024, 'v' },
|
||||
#endif
|
||||
#ifdef RLIMIT_SWAP
|
||||
{ "swap limit", "kbytes", RLIMIT_SWAP, 1024, 'w' },
|
||||
#endif
|
||||
#ifdef RLIMIT_SBSIZE
|
||||
{ "sbsize", "bytes", RLIMIT_SBSIZE, 1, 'b' },
|
||||
#endif
|
||||
{ (char *) 0, (char *)0, 0, 0, '\0' }
|
||||
};
|
||||
|
||||
int
|
||||
ulimitcmd(int argc __unused, char **argv __unused)
|
||||
{
|
||||
int c;
|
||||
intmax_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("HSatfdsmcnuvlb")) != '\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 = 0;
|
||||
|
||||
while ((c = *p++) >= '0' && c <= '9')
|
||||
{
|
||||
val = (val * 10) + (long)(c - '0');
|
||||
if (val < 0)
|
||||
break;
|
||||
}
|
||||
if (c)
|
||||
error("bad number");
|
||||
val *= l->factor;
|
||||
}
|
||||
}
|
||||
if (all) {
|
||||
for (l = limits; l->name; l++) {
|
||||
char optbuf[40];
|
||||
if (getrlimit(l->cmd, &limit) < 0)
|
||||
error("can't get limit: %s", strerror(errno));
|
||||
if (how & SOFT)
|
||||
val = limit.rlim_cur;
|
||||
else if (how & HARD)
|
||||
val = limit.rlim_max;
|
||||
|
||||
if (l->units)
|
||||
snprintf(optbuf, sizeof(optbuf),
|
||||
"(%s, -%c) ", l->units, l->option);
|
||||
else
|
||||
snprintf(optbuf, sizeof(optbuf),
|
||||
"(-%c) ", l->option);
|
||||
out1fmt("%-18s %18s ", l->name, optbuf);
|
||||
if (val == RLIM_INFINITY)
|
||||
out1fmt("unlimited\n");
|
||||
else
|
||||
{
|
||||
val /= l->factor;
|
||||
out1fmt("%jd\n", (intmax_t)val);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (getrlimit(l->cmd, &limit) < 0)
|
||||
error("can't get limit: %s", strerror(errno));
|
||||
if (set) {
|
||||
if (how & SOFT)
|
||||
limit.rlim_cur = val;
|
||||
if (how & HARD)
|
||||
limit.rlim_max = val;
|
||||
if (setrlimit(l->cmd, &limit) < 0)
|
||||
error("bad 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;
|
||||
out1fmt("%jd\n", (intmax_t)val);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* $PchId: miscbltin.c,v 1.7 2006/05/23 11:59:08 philip Exp $
|
||||
*/
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#!/bin/sh -
|
||||
#
|
||||
# Copyright (c) 1991 The Regents of the University of California.
|
||||
# All rights reserved.
|
||||
# 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.
|
||||
@@ -14,10 +14,6 @@
|
||||
# 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.
|
||||
@@ -34,90 +30,69 @@
|
||||
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
# SUCH DAMAGE.
|
||||
#
|
||||
# @(#)mkbuiltins 5.2 (Berkeley) 3/8/91
|
||||
# @(#)mkbuiltins 8.2 (Berkeley) 5/4/95
|
||||
# $FreeBSD: src/bin/sh/mkbuiltins,v 1.13 2004/04/06 20:06:51 markm Exp $
|
||||
|
||||
# All calls to awk removed, because Minix bawk is deficient. (kjb)
|
||||
|
||||
if [ $# != 2 ]
|
||||
then
|
||||
echo "USAGE: $0 shell.h builtins"
|
||||
exit 1
|
||||
#temp=`/usr/bin/mktemp -t ka`
|
||||
temp=/tmp/mkb$$
|
||||
havehist=1
|
||||
if [ "X$1" = "X-h" ]; then
|
||||
havehist=0
|
||||
shift
|
||||
fi
|
||||
SHL=$1
|
||||
BLTINS=$2
|
||||
|
||||
temp=/tmp/ka$$
|
||||
exec > builtins.c
|
||||
havejobs=0
|
||||
if [ "X$1" = "X-j" ]; then
|
||||
havejobs=0
|
||||
shift
|
||||
elif grep '^#define[ ]*JOBS[ ]*1' $2 > /dev/null
|
||||
then havejobs=1
|
||||
fi
|
||||
objdir=$1
|
||||
exec > ${objdir}/builtins.c
|
||||
cat <<\!
|
||||
/*
|
||||
* This file was generated by the mkbuiltins program.
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include "shell.h"
|
||||
#include "builtins.h"
|
||||
|
||||
!
|
||||
if grep '^#define JOBS[ ]*1' $SHL > /dev/null
|
||||
then
|
||||
# Job control.
|
||||
sed -e '/^#/d
|
||||
s/ / /g
|
||||
s/ #.*//
|
||||
/^ *$/d
|
||||
s/-j//' $BLTINS > $temp
|
||||
else
|
||||
# No job control.
|
||||
sed -e '/^#/d
|
||||
s/ / /g
|
||||
s/ #.*//
|
||||
/^ *$/d
|
||||
/-j/d' $BLTINS > $temp
|
||||
fi
|
||||
sed -e 's/ .*//
|
||||
s/\(.*\)/int \1();/' $temp
|
||||
awk '/^[^#]/ {if(('$havejobs' || $2 != "-j") && ('$havehist' || $2 != "-h")) \
|
||||
print $0}' $3 | sed 's/-[hj]//' > $temp
|
||||
#awk '{ printf "int %s();\n", $1}' $temp
|
||||
echo '
|
||||
int (*const builtinfunc[])() = {'
|
||||
sed -e 's/ .*//
|
||||
s/\(.*\)/ \1,/' $temp
|
||||
int (*const builtinfunc[]) (int, char **) = {'
|
||||
awk '/^[^#]/ { printf "\t%s,\n", $1}' $temp
|
||||
echo '};
|
||||
|
||||
const struct builtincmd builtincmd[] = {'
|
||||
i=0
|
||||
while read line
|
||||
do
|
||||
set -$- $line
|
||||
shift
|
||||
for fun
|
||||
do
|
||||
echo " \"$fun\", $i,"
|
||||
done
|
||||
i=`expr $i + 1`
|
||||
done < $temp
|
||||
echo ' NULL, 0
|
||||
awk '{ for (i = 2 ; i <= NF ; i++) {
|
||||
printf "\t{ \"%s\", %d },\n", $i, NR-1
|
||||
}}' $temp
|
||||
echo ' { NULL, 0 }
|
||||
};'
|
||||
|
||||
exec > builtins.h
|
||||
exec > ${objdir}/builtins.h
|
||||
cat <<\!
|
||||
/*
|
||||
* This file was generated by the mkbuiltins program.
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
!
|
||||
i=0
|
||||
tr abcdefghijklmnopqrstuvwxyz ABCDEFGHIJKLMNOPQRSTUVWXYZ < $temp |
|
||||
while read line
|
||||
do
|
||||
set -$- $line
|
||||
echo "#define $1 $i"
|
||||
i=`expr $i + 1`
|
||||
done
|
||||
awk '{ printf "#define %s %d\n", $1, NR-1}'
|
||||
echo '
|
||||
struct builtincmd {
|
||||
char *name;
|
||||
int code;
|
||||
};
|
||||
|
||||
extern int (*const builtinfunc[])();
|
||||
extern int (*const builtinfunc[]) (int, char **);
|
||||
extern const struct builtincmd builtincmd[];'
|
||||
awk '{ printf "int %s (int, char **);\n", $1 }' < $temp
|
||||
rm -f $temp
|
||||
|
||||
#
|
||||
# $PchId: mkbuiltins,v 1.6 2006/05/22 12:42:58 philip Exp $
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*-
|
||||
* Copyright (c) 1991 The Regents of the University of California.
|
||||
* All rights reserved.
|
||||
* 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.
|
||||
@@ -13,10 +13,6 @@
|
||||
* 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.
|
||||
@@ -35,43 +31,51 @@
|
||||
*/
|
||||
|
||||
#ifndef lint
|
||||
char copyright[] =
|
||||
"@(#) Copyright (c) 1991 The Regents of the University of California.\n\
|
||||
All rights reserved.\n";
|
||||
static char const copyright[] =
|
||||
"@(#) Copyright (c) 1991, 1993\n\
|
||||
The Regents of the University of California. All rights reserved.\n";
|
||||
#endif /* not lint */
|
||||
|
||||
#ifndef lint
|
||||
static char sccsid[] = "@(#)mkinit.c 5.3 (Berkeley) 3/13/91";
|
||||
#if 0
|
||||
static char sccsid[] = "@(#)mkinit.c 8.2 (Berkeley) 5/4/95";
|
||||
#endif
|
||||
#endif /* not lint */
|
||||
/*
|
||||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD: src/bin/sh/mkinit.c,v 1.17 2004/04/06 20:06:51 markm Exp $");
|
||||
*/
|
||||
|
||||
/*
|
||||
* This program scans all the source files for code to handle various
|
||||
* special events and combines this code into one file. This (allegedly)
|
||||
* improves the structure of the program since there is no need for
|
||||
* anyone outside of a module to know that that module performs special
|
||||
* operations on particular events. The command is executed iff init.c
|
||||
* is actually changed.
|
||||
* operations on particular events.
|
||||
*
|
||||
* Usage: mkinit command sourcefile...
|
||||
* Usage: mkinit sourcefile...
|
||||
*/
|
||||
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
|
||||
#ifdef __minix
|
||||
#define __unused
|
||||
#endif
|
||||
|
||||
/*
|
||||
* OUTFILE is the name of the output file. Output is initially written
|
||||
* to the file OUTTEMP, which is then moved to OUTFILE if OUTTEMP and
|
||||
* OUTFILE are different.
|
||||
* to the file OUTTEMP, which is then moved to OUTFILE.
|
||||
*/
|
||||
|
||||
#define OUTFILE "init.c"
|
||||
#define OUTTEMP "init.c.new"
|
||||
#define OUTOBJ "init.o"
|
||||
|
||||
|
||||
/*
|
||||
@@ -89,7 +93,7 @@ struct text {
|
||||
int nleft;
|
||||
struct block *start;
|
||||
struct block *last;
|
||||
};
|
||||
};
|
||||
|
||||
struct block {
|
||||
struct block *next;
|
||||
@@ -105,7 +109,7 @@ struct event {
|
||||
char *name; /* name of event (e.g. INIT) */
|
||||
char *routine; /* name of routine called on event */
|
||||
char *comment; /* comment describing routine */
|
||||
struct text code; /* code for handling event */
|
||||
struct text code; /* code for handling event */
|
||||
};
|
||||
|
||||
|
||||
@@ -148,42 +152,35 @@ struct text decls; /* declarations */
|
||||
int amiddecls; /* for formatting */
|
||||
|
||||
|
||||
void readfile(), doevent(), doinclude(), dodecl(), output();
|
||||
void addstr(), addchar(), writetext();
|
||||
static void readfile(char *);
|
||||
static int match(char *, char *);
|
||||
static int gooddefine(char *);
|
||||
static void doevent(struct event *, FILE *, char *);
|
||||
static void doinclude(char *);
|
||||
static void dodecl(char *, FILE *);
|
||||
static void output(void);
|
||||
static void addstr(char *, struct text *);
|
||||
static void addchar(int, struct text *);
|
||||
static void writetext(struct text *, FILE *);
|
||||
static FILE *ckfopen(char *, char *);
|
||||
static void *ckmalloc(int);
|
||||
static char *savestr(char *);
|
||||
static void error(char *);
|
||||
|
||||
#define equal(s1, s2) (strcmp(s1, s2) == 0)
|
||||
|
||||
FILE *ckfopen();
|
||||
char *savestr();
|
||||
void *ckmalloc __P((int));
|
||||
void error();
|
||||
|
||||
main(argc, argv)
|
||||
char **argv;
|
||||
{
|
||||
int
|
||||
main(int argc __unused, char *argv[])
|
||||
{
|
||||
char **ap;
|
||||
int fd;
|
||||
char c;
|
||||
|
||||
if (argc < 2)
|
||||
error("Usage: mkinit command file...");
|
||||
header_files[0] = "\"shell.h\"";
|
||||
header_files[1] = "\"mystring.h\"";
|
||||
for (ap = argv + 2 ; *ap ; ap++)
|
||||
for (ap = argv + 1 ; *ap ; ap++)
|
||||
readfile(*ap);
|
||||
output();
|
||||
if (file_changed()) {
|
||||
unlink(OUTFILE);
|
||||
link(OUTTEMP, OUTFILE);
|
||||
unlink(OUTTEMP);
|
||||
} else {
|
||||
unlink(OUTTEMP);
|
||||
if (touch(OUTOBJ))
|
||||
exit(0); /* no compilation necessary */
|
||||
}
|
||||
printf("%s\n", argv[1]);
|
||||
execl("/bin/sh", "sh", "-c", argv[1], (char *)0);
|
||||
error("Can't exec shell");
|
||||
rename(OUTTEMP, OUTFILE);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
|
||||
@@ -191,10 +188,9 @@ main(argc, argv)
|
||||
* Parse an input file.
|
||||
*/
|
||||
|
||||
void
|
||||
readfile(fname)
|
||||
char *fname;
|
||||
{
|
||||
static void
|
||||
readfile(char *fname)
|
||||
{
|
||||
FILE *fp;
|
||||
char line[1024];
|
||||
struct event *ep;
|
||||
@@ -215,19 +211,31 @@ readfile(fname)
|
||||
doinclude(line);
|
||||
if (line[0] == 'M' && match("MKINIT", line))
|
||||
dodecl(line, fp);
|
||||
if (line[0] == '#' && gooddefine(line))
|
||||
if (line[0] == '#' && gooddefine(line)) {
|
||||
char *cp;
|
||||
char line2[1024];
|
||||
static const char undef[] = "#undef ";
|
||||
|
||||
strcpy(line2, line);
|
||||
memcpy(line2, undef, sizeof(undef) - 1);
|
||||
cp = line2 + sizeof(undef) - 1;
|
||||
while(*cp && (*cp == ' ' || *cp == '\t'))
|
||||
cp++;
|
||||
while(*cp && *cp != ' ' && *cp != '\t' && *cp != '\n')
|
||||
cp++;
|
||||
*cp++ = '\n'; *cp = '\0';
|
||||
addstr(line2, &defines);
|
||||
addstr(line, &defines);
|
||||
}
|
||||
}
|
||||
fclose(fp);
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
match(name, line)
|
||||
char *name;
|
||||
char *line;
|
||||
{
|
||||
register char *p, *q;
|
||||
static int
|
||||
match(char *name, char *line)
|
||||
{
|
||||
char *p, *q;
|
||||
|
||||
p = name, q = line;
|
||||
while (*p) {
|
||||
@@ -240,11 +248,10 @@ match(name, line)
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
gooddefine(line)
|
||||
char *line;
|
||||
{
|
||||
register char *p;
|
||||
static int
|
||||
gooddefine(char *line)
|
||||
{
|
||||
char *p;
|
||||
|
||||
if (! match("#define", line))
|
||||
return 0; /* not a define */
|
||||
@@ -264,12 +271,9 @@ gooddefine(line)
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
doevent(ep, fp, fname)
|
||||
register struct event *ep;
|
||||
FILE *fp;
|
||||
char *fname;
|
||||
{
|
||||
static void
|
||||
doevent(struct event *ep, FILE *fp, char *fname)
|
||||
{
|
||||
char line[1024];
|
||||
int indent;
|
||||
char *p;
|
||||
@@ -304,13 +308,12 @@ doevent(ep, fp, fname)
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
doinclude(line)
|
||||
char *line;
|
||||
{
|
||||
register char *p;
|
||||
static void
|
||||
doinclude(char *line)
|
||||
{
|
||||
char *p;
|
||||
char *name;
|
||||
register char **pp;
|
||||
char **pp;
|
||||
|
||||
for (p = line ; *p != '"' && *p != '<' && *p != '\0' ; p++);
|
||||
if (*p == '\0')
|
||||
@@ -329,13 +332,11 @@ doinclude(line)
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
dodecl(line1, fp)
|
||||
char *line1;
|
||||
FILE *fp;
|
||||
{
|
||||
static void
|
||||
dodecl(char *line1, FILE *fp)
|
||||
{
|
||||
char line[1024];
|
||||
register char *p, *q;
|
||||
char *p, *q;
|
||||
|
||||
if (strcmp(line1, "MKINIT\n") == 0) { /* start of struct/union decl */
|
||||
addchar('\n', &decls);
|
||||
@@ -350,7 +351,8 @@ dodecl(line1, fp)
|
||||
if (! amiddecls)
|
||||
addchar('\n', &decls);
|
||||
q = NULL;
|
||||
for (p = line1 + 6 ; *p != '=' && *p != '/' ; p++);
|
||||
for (p = line1 + 6 ; *p && strchr("=/\n", *p) == NULL; p++)
|
||||
continue;
|
||||
if (*p == '=') { /* eliminate initialization */
|
||||
for (q = p ; *q && *q != ';' ; q++);
|
||||
if (*q == '\0')
|
||||
@@ -375,8 +377,9 @@ dodecl(line1, fp)
|
||||
* Write the output to the file OUTTEMP.
|
||||
*/
|
||||
|
||||
void
|
||||
output() {
|
||||
static void
|
||||
output(void)
|
||||
{
|
||||
FILE *fp;
|
||||
char **pp;
|
||||
struct event *ep;
|
||||
@@ -392,7 +395,7 @@ output() {
|
||||
for (ep = event ; ep->name ; ep++) {
|
||||
fputs("\n\n\n", fp);
|
||||
fputs(ep->comment, fp);
|
||||
fprintf(fp, "\nvoid\n%s() {\n", ep->routine);
|
||||
fprintf(fp, "\nvoid\n%s(void) {\n", ep->routine);
|
||||
writetext(&ep->code, fp);
|
||||
fprintf(fp, "}\n");
|
||||
}
|
||||
@@ -400,62 +403,15 @@ output() {
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Return true if the new output file is different from the old one.
|
||||
*/
|
||||
|
||||
int
|
||||
file_changed() {
|
||||
register FILE *f1, *f2;
|
||||
register int c;
|
||||
|
||||
if ((f1 = fopen(OUTFILE, "r")) == NULL
|
||||
|| (f2 = fopen(OUTTEMP, "r")) == NULL)
|
||||
return 1;
|
||||
while ((c = getc(f1)) == getc(f2)) {
|
||||
if (c == EOF)
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Touch a file. Returns 0 on failure, 1 on success.
|
||||
*/
|
||||
|
||||
int
|
||||
touch(file)
|
||||
char *file;
|
||||
{
|
||||
int fd;
|
||||
char c;
|
||||
|
||||
if ((fd = open(file, O_RDWR)) < 0)
|
||||
return 0;
|
||||
if (read(fd, &c, 1) != 1) {
|
||||
close(fd);
|
||||
return 0;
|
||||
}
|
||||
lseek(fd, 0L, 0);
|
||||
write(fd, &c, 1);
|
||||
close(fd);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* A text structure is simply a block of text that is kept in memory.
|
||||
* Addstr appends a string to the text struct, and addchar appends a single
|
||||
* character.
|
||||
*/
|
||||
|
||||
void
|
||||
addstr(s, text)
|
||||
register char *s;
|
||||
register struct text *text;
|
||||
{
|
||||
static void
|
||||
addstr(char *s, struct text *text)
|
||||
{
|
||||
while (*s) {
|
||||
if (--text->nleft < 0)
|
||||
addchar(*s++, text);
|
||||
@@ -465,10 +421,9 @@ addstr(s, text)
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
addchar(c, text)
|
||||
register struct text *text;
|
||||
{
|
||||
static void
|
||||
addchar(int c, struct text *text)
|
||||
{
|
||||
struct block *bp;
|
||||
|
||||
if (--text->nleft < 0) {
|
||||
@@ -487,11 +442,9 @@ addchar(c, text)
|
||||
/*
|
||||
* Write the contents of a text structure to a file.
|
||||
*/
|
||||
void
|
||||
writetext(text, fp)
|
||||
struct text *text;
|
||||
FILE *fp;
|
||||
{
|
||||
static void
|
||||
writetext(struct text *text, FILE *fp)
|
||||
{
|
||||
struct block *bp;
|
||||
|
||||
if (text->start != NULL) {
|
||||
@@ -501,47 +454,47 @@ writetext(text, fp)
|
||||
}
|
||||
}
|
||||
|
||||
FILE *
|
||||
ckfopen(file, mode)
|
||||
char *file;
|
||||
char *mode;
|
||||
{
|
||||
static FILE *
|
||||
ckfopen(char *file, char *mode)
|
||||
{
|
||||
FILE *fp;
|
||||
|
||||
if ((fp = fopen(file, mode)) == NULL) {
|
||||
fprintf(stderr, "Can't open %s\n", file);
|
||||
fprintf(stderr, "Can't open %s: %s\n", file, strerror(errno));
|
||||
exit(2);
|
||||
}
|
||||
return fp;
|
||||
}
|
||||
|
||||
void *
|
||||
ckmalloc(nbytes) {
|
||||
register char *p;
|
||||
char *malloc();
|
||||
static void *
|
||||
ckmalloc(int nbytes)
|
||||
{
|
||||
char *p;
|
||||
|
||||
if ((p = malloc(nbytes)) == NULL)
|
||||
error("Out of space");
|
||||
return p;
|
||||
}
|
||||
|
||||
char *
|
||||
savestr(s)
|
||||
char *s;
|
||||
{
|
||||
register char *p;
|
||||
static char *
|
||||
savestr(char *s)
|
||||
{
|
||||
char *p;
|
||||
|
||||
p = ckmalloc(strlen(s) + 1);
|
||||
strcpy(p, s);
|
||||
return p;
|
||||
}
|
||||
|
||||
void
|
||||
error(msg)
|
||||
char *msg;
|
||||
{
|
||||
static void
|
||||
error(char *msg)
|
||||
{
|
||||
if (curfile != NULL)
|
||||
fprintf(stderr, "%s:%d: ", curfile, linno);
|
||||
fprintf(stderr, "%s\n", msg);
|
||||
exit(2);
|
||||
}
|
||||
|
||||
/*
|
||||
* $PchId: mkinit.c,v 1.6 2006/05/22 12:16:50 philip Exp $
|
||||
*/
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*-
|
||||
* Copyright (c) 1991 The Regents of the University of California.
|
||||
* All rights reserved.
|
||||
* 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.
|
||||
@@ -13,10 +13,6 @@
|
||||
* 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.
|
||||
@@ -34,15 +30,20 @@
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#if 0
|
||||
#ifndef lint
|
||||
char copyright[] =
|
||||
"@(#) Copyright (c) 1991 The Regents of the University of California.\n\
|
||||
All rights reserved.\n";
|
||||
static char const copyright[] =
|
||||
"@(#) Copyright (c) 1991, 1993\n\
|
||||
The Regents of the University of California. All rights reserved.\n";
|
||||
#endif /* not lint */
|
||||
|
||||
#ifndef lint
|
||||
static char sccsid[] = "@(#)mknodes.c 5.1 (Berkeley) 3/7/91";
|
||||
static char sccsid[] = "@(#)mknodes.c 8.2 (Berkeley) 5/4/95";
|
||||
#endif /* not lint */
|
||||
#endif
|
||||
/*
|
||||
__FBSDID("$FreeBSD: src/bin/sh/mknodes.c,v 1.17 2004/04/06 20:06:51 markm Exp $");
|
||||
*/
|
||||
|
||||
/*
|
||||
* This program reads the nodetypes file and nodes.c.pat file. It generates
|
||||
@@ -50,7 +51,10 @@ static char sccsid[] = "@(#)mknodes.c 5.1 (Berkeley) 3/7/91";
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
#define MAXTYPES 50 /* max number of node types */
|
||||
#define MAXFIELDS 20 /* max fields in a structure */
|
||||
@@ -80,31 +84,42 @@ struct str { /* struct representing a node structure */
|
||||
};
|
||||
|
||||
|
||||
int ntypes; /* number of node types */
|
||||
char *nodename[MAXTYPES]; /* names of the nodes */
|
||||
struct str *nodestr[MAXTYPES]; /* type of structure used by the node */
|
||||
int nstr; /* number of structures */
|
||||
struct str str[MAXTYPES]; /* the structures */
|
||||
struct str *curstr; /* current structure */
|
||||
static int ntypes; /* number of node types */
|
||||
static char *nodename[MAXTYPES]; /* names of the nodes */
|
||||
static struct str *nodestr[MAXTYPES]; /* type of structure used by the node */
|
||||
static int nstr; /* number of structures */
|
||||
static struct str str[MAXTYPES]; /* the structures */
|
||||
static struct str *curstr; /* current structure */
|
||||
static FILE *infp;
|
||||
static char line[1024];
|
||||
static int linno;
|
||||
static char *linep;
|
||||
|
||||
#ifndef __printf0like
|
||||
#define __printf0like(a,b)
|
||||
#endif
|
||||
|
||||
static void parsenode(void);
|
||||
static void parsefield(void);
|
||||
static void output(char *);
|
||||
static void outsizes(FILE *);
|
||||
static void outfunc(FILE *, int);
|
||||
static void indent(int, FILE *);
|
||||
static int nextfield(char *);
|
||||
static void skipbl(void);
|
||||
static int readline(void);
|
||||
static void error(const char *, ...) __printf0like(1, 2);
|
||||
static char *savestr(const char *);
|
||||
|
||||
|
||||
FILE *infp = stdin;
|
||||
char line[1024];
|
||||
int linno;
|
||||
char *linep;
|
||||
|
||||
|
||||
char *savestr();
|
||||
#define equal(s1, s2) (strcmp(s1, s2) == 0)
|
||||
|
||||
|
||||
main(argc, argv)
|
||||
char **argv;
|
||||
{
|
||||
int
|
||||
main(int argc, char *argv[])
|
||||
{
|
||||
if (argc != 3)
|
||||
error("usage: mknodes file\n");
|
||||
error("usage: mknodes file");
|
||||
infp = stdin;
|
||||
if ((infp = fopen(argv[1], "r")) == NULL)
|
||||
error("Can't open %s", argv[1]);
|
||||
error("Can't open %s: %s", argv[1], strerror(errno));
|
||||
while (readline()) {
|
||||
if (line[0] == ' ' || line[0] == '\t')
|
||||
parsefield();
|
||||
@@ -112,12 +127,14 @@ main(argc, argv)
|
||||
parsenode();
|
||||
}
|
||||
output(argv[2]);
|
||||
return 0;
|
||||
exit(0);
|
||||
}
|
||||
|
||||
|
||||
|
||||
parsenode() {
|
||||
static void
|
||||
parsenode(void)
|
||||
{
|
||||
char name[BUFLEN];
|
||||
char tag[BUFLEN];
|
||||
struct str *sp;
|
||||
@@ -131,7 +148,7 @@ parsenode() {
|
||||
error("Garbage at end of line");
|
||||
nodename[ntypes] = savestr(name);
|
||||
for (sp = str ; sp < str + nstr ; sp++) {
|
||||
if (equal(sp->tag, tag))
|
||||
if (strcmp(sp->tag, tag) == 0)
|
||||
break;
|
||||
}
|
||||
if (sp >= str + nstr) {
|
||||
@@ -145,7 +162,9 @@ parsenode() {
|
||||
}
|
||||
|
||||
|
||||
parsefield() {
|
||||
static void
|
||||
parsefield(void)
|
||||
{
|
||||
char name[BUFLEN];
|
||||
char type[BUFLEN];
|
||||
char decl[2 * BUFLEN];
|
||||
@@ -159,21 +178,21 @@ parsefield() {
|
||||
error("No field type");
|
||||
fp = &curstr->field[curstr->nfields];
|
||||
fp->name = savestr(name);
|
||||
if (equal(type, "nodeptr")) {
|
||||
if (strcmp(type, "nodeptr") == 0) {
|
||||
fp->type = T_NODE;
|
||||
sprintf(decl, "union node *%s", name);
|
||||
} else if (equal(type, "nodelist")) {
|
||||
} else if (strcmp(type, "nodelist") == 0) {
|
||||
fp->type = T_NODELIST;
|
||||
sprintf(decl, "struct nodelist *%s", name);
|
||||
} else if (equal(type, "string")) {
|
||||
} else if (strcmp(type, "string") == 0) {
|
||||
fp->type = T_STRING;
|
||||
sprintf(decl, "char *%s", name);
|
||||
} else if (equal(type, "int")) {
|
||||
} else if (strcmp(type, "int") == 0) {
|
||||
fp->type = T_INT;
|
||||
sprintf(decl, "int %s", name);
|
||||
} else if (equal(type, "other")) {
|
||||
} else if (strcmp(type, "other") == 0) {
|
||||
fp->type = T_OTHER;
|
||||
} else if (equal(type, "temp")) {
|
||||
} else if (strcmp(type, "temp") == 0) {
|
||||
fp->type = T_TEMP;
|
||||
} else {
|
||||
error("Unknown type %s", type);
|
||||
@@ -196,9 +215,9 @@ char writer[] = "\
|
||||
*/\n\
|
||||
\n";
|
||||
|
||||
output(file)
|
||||
char *file;
|
||||
{
|
||||
static void
|
||||
output(char *file)
|
||||
{
|
||||
FILE *hfile;
|
||||
FILE *cfile;
|
||||
FILE *patfile;
|
||||
@@ -208,9 +227,9 @@ output(file)
|
||||
char *p;
|
||||
|
||||
if ((patfile = fopen(file, "r")) == NULL)
|
||||
error("Can't open %s", file);
|
||||
error("Can't open %s: %s", file, strerror(errno));
|
||||
if ((hfile = fopen("nodes.h", "w")) == NULL)
|
||||
error("Can't create nodes.h");
|
||||
error("Can't create nodes.h: %s", strerror(errno));
|
||||
if ((cfile = fopen("nodes.c", "w")) == NULL)
|
||||
error("Can't create nodes.c");
|
||||
fputs(writer, hfile);
|
||||
@@ -234,22 +253,17 @@ output(file)
|
||||
fputs("\tstruct nodelist *next;\n", hfile);
|
||||
fputs("\tunion node *n;\n", hfile);
|
||||
fputs("};\n\n\n", hfile);
|
||||
fputs("#ifdef __STDC__\n", hfile);
|
||||
fputs("union node *copyfunc(union node *);\n", hfile);
|
||||
fputs("void freefunc(union node *);\n", hfile);
|
||||
fputs("#else\n", hfile);
|
||||
fputs("union node *copyfunc();\n", hfile);
|
||||
fputs("void freefunc();\n", hfile);
|
||||
fputs("#endif\n", hfile);
|
||||
|
||||
fputs(writer, cfile);
|
||||
while (fgets(line, sizeof line, patfile) != NULL) {
|
||||
for (p = line ; *p == ' ' || *p == '\t' ; p++);
|
||||
if (equal(p, "%SIZES\n"))
|
||||
if (strcmp(p, "%SIZES\n") == 0)
|
||||
outsizes(cfile);
|
||||
else if (equal(p, "%CALCSIZE\n"))
|
||||
else if (strcmp(p, "%CALCSIZE\n") == 0)
|
||||
outfunc(cfile, 1);
|
||||
else if (equal(p, "%COPY\n"))
|
||||
else if (strcmp(p, "%COPY\n") == 0)
|
||||
outfunc(cfile, 0);
|
||||
else
|
||||
fputs(line, cfile);
|
||||
@@ -258,9 +272,9 @@ output(file)
|
||||
|
||||
|
||||
|
||||
outsizes(cfile)
|
||||
FILE *cfile;
|
||||
{
|
||||
static void
|
||||
outsizes(FILE *cfile)
|
||||
{
|
||||
int i;
|
||||
|
||||
fprintf(cfile, "static const short nodesize[%d] = {\n", ntypes);
|
||||
@@ -271,9 +285,9 @@ outsizes(cfile)
|
||||
}
|
||||
|
||||
|
||||
outfunc(cfile, calcsize)
|
||||
FILE *cfile;
|
||||
{
|
||||
static void
|
||||
outfunc(FILE *cfile, int calcsize)
|
||||
{
|
||||
struct str *sp;
|
||||
struct field *fp;
|
||||
int i;
|
||||
@@ -287,8 +301,7 @@ outfunc(cfile, calcsize)
|
||||
fputs(" funcblocksize += nodesize[n->type];\n", cfile);
|
||||
else {
|
||||
fputs(" new = funcblock;\n", cfile);
|
||||
fputs(" *(char **)&funcblock += nodesize[n->type];\n",
|
||||
cfile);
|
||||
fputs(" funcblock = (char *)funcblock + nodesize[n->type];\n", cfile);
|
||||
}
|
||||
fputs(" switch (n->type) {\n", cfile);
|
||||
for (sp = str ; sp < &str[nstr] ; sp++) {
|
||||
@@ -351,9 +364,9 @@ outfunc(cfile, calcsize)
|
||||
}
|
||||
|
||||
|
||||
indent(amount, fp)
|
||||
FILE *fp;
|
||||
{
|
||||
static void
|
||||
indent(int amount, FILE *fp)
|
||||
{
|
||||
while (amount >= 8) {
|
||||
putc('\t', fp);
|
||||
amount -= 8;
|
||||
@@ -364,11 +377,10 @@ indent(amount, fp)
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
nextfield(buf)
|
||||
char *buf;
|
||||
{
|
||||
register char *p, *q;
|
||||
static int
|
||||
nextfield(char *buf)
|
||||
{
|
||||
char *p, *q;
|
||||
|
||||
p = linep;
|
||||
while (*p == ' ' || *p == '\t')
|
||||
@@ -382,15 +394,18 @@ nextfield(buf)
|
||||
}
|
||||
|
||||
|
||||
skipbl() {
|
||||
static void
|
||||
skipbl(void)
|
||||
{
|
||||
while (*linep == ' ' || *linep == '\t')
|
||||
linep++;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
readline() {
|
||||
register char *p;
|
||||
static int
|
||||
readline(void)
|
||||
{
|
||||
char *p;
|
||||
|
||||
if (fgets(line, 1024, infp) == NULL)
|
||||
return 0;
|
||||
@@ -407,26 +422,34 @@ readline() {
|
||||
|
||||
|
||||
|
||||
error(msg, a1, a2, a3, a4, a5, a6)
|
||||
char *msg;
|
||||
{
|
||||
fprintf(stderr, "line %d: ", linno);
|
||||
fprintf(stderr, msg, a1, a2, a3, a4, a5, a6);
|
||||
putc('\n', stderr);
|
||||
static void
|
||||
error(const char *msg, ...)
|
||||
{
|
||||
va_list va;
|
||||
va_start(va, msg);
|
||||
|
||||
(void) fprintf(stderr, "line %d: ", linno);
|
||||
(void) vfprintf(stderr, msg, va);
|
||||
(void) fputc('\n', stderr);
|
||||
|
||||
va_end(va);
|
||||
|
||||
exit(2);
|
||||
}
|
||||
|
||||
|
||||
|
||||
char *
|
||||
savestr(s)
|
||||
char *s;
|
||||
{
|
||||
register char *p;
|
||||
char *malloc();
|
||||
static char *
|
||||
savestr(const char *s)
|
||||
{
|
||||
char *p;
|
||||
|
||||
if ((p = malloc(strlen(s) + 1)) == NULL)
|
||||
error("Out of space");
|
||||
strcpy(p, s);
|
||||
(void) strcpy(p, s);
|
||||
return p;
|
||||
}
|
||||
|
||||
/*
|
||||
* $PchId: mknodes.c,v 1.6 2006/05/23 12:05:14 philip Exp $
|
||||
*/
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*-
|
||||
* Copyright (c) 1991 The Regents of the University of California.
|
||||
* All rights reserved.
|
||||
* 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.
|
||||
@@ -35,23 +35,23 @@
|
||||
*/
|
||||
|
||||
#ifndef lint
|
||||
char copyright[] =
|
||||
"@(#) Copyright (c) 1991 The Regents of the University of California.\n\
|
||||
All rights reserved.\n";
|
||||
static char copyright[] =
|
||||
"@(#) Copyright (c) 1991, 1993\n\
|
||||
The Regents of the University of California. All rights reserved.\n";
|
||||
#endif /* not lint */
|
||||
|
||||
#ifndef lint
|
||||
static char sccsid[] = "@(#)mksignames.c 5.1 (Berkeley) 3/7/91";
|
||||
static char sccsid[] = "@(#)mksignames.c 8.1 (Berkeley) 5/31/93";
|
||||
#endif /* not lint */
|
||||
|
||||
/*
|
||||
* This program generates the signames.h and signames.c files.
|
||||
*/
|
||||
#include <sys/types.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <signal.h>
|
||||
|
||||
|
||||
int main(int argc, char *argv[]);
|
||||
|
||||
struct sig {
|
||||
int signo; /* signal number */
|
||||
@@ -198,3 +198,7 @@ main(argc, argv) char **argv; {
|
||||
fprintf(cfile, "};\n");
|
||||
exit(0);
|
||||
}
|
||||
|
||||
/*
|
||||
* $PchId: mksignames.c,v 1.2 2001/05/14 19:22:26 philip Exp $
|
||||
*/
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*-
|
||||
* Copyright (c) 1991 The Regents of the University of California.
|
||||
* All rights reserved.
|
||||
* 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.
|
||||
@@ -13,10 +13,6 @@
|
||||
* 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.
|
||||
@@ -34,23 +30,33 @@
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#if 0
|
||||
#ifndef lint
|
||||
char copyright[] =
|
||||
"@(#) Copyright (c) 1991 The Regents of the University of California.\n\
|
||||
All rights reserved.\n";
|
||||
static char const copyright[] =
|
||||
"@(#) Copyright (c) 1991, 1993\n\
|
||||
The Regents of the University of California. All rights reserved.\n";
|
||||
#endif /* not lint */
|
||||
|
||||
#ifndef lint
|
||||
static char sccsid[] = "@(#)mksyntax.c 5.2 (Berkeley) 3/8/91";
|
||||
static char sccsid[] = "@(#)mksyntax.c 8.2 (Berkeley) 5/4/95";
|
||||
#endif /* not lint */
|
||||
#endif
|
||||
/*
|
||||
__FBSDID("$FreeBSD: src/bin/sh/mksyntax.c,v 1.23 2004/04/06 20:06:51 markm Exp $");
|
||||
*/
|
||||
|
||||
/*
|
||||
* This program creates syntax.h and syntax.c.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "parser.h"
|
||||
|
||||
#ifdef __minix
|
||||
#define __unused
|
||||
#endif
|
||||
|
||||
struct synclass {
|
||||
char *name;
|
||||
@@ -59,19 +65,21 @@ struct synclass {
|
||||
|
||||
/* Syntax classes */
|
||||
struct synclass synclass[] = {
|
||||
"CWORD", "character is nothing special",
|
||||
"CNL", "newline character",
|
||||
"CBACK", "a backslash character",
|
||||
"CSQUOTE", "single quote",
|
||||
"CDQUOTE", "double quote",
|
||||
"CENDQUOTE", "a terminating quote",
|
||||
"CBQUOTE", "backwards single quote",
|
||||
"CVAR", "a dollar sign",
|
||||
"CENDVAR", "a '}' character",
|
||||
"CEOF", "end of file",
|
||||
"CCTL", "like CWORD, except it must be escaped",
|
||||
"CSPCL", "these terminate a word",
|
||||
NULL, NULL
|
||||
{ "CWORD", "character is nothing special" },
|
||||
{ "CNL", "newline character" },
|
||||
{ "CBACK", "a backslash character" },
|
||||
{ "CSQUOTE", "single quote" },
|
||||
{ "CDQUOTE", "double quote" },
|
||||
{ "CENDQUOTE", "a terminating quote" },
|
||||
{ "CBQUOTE", "backwards single quote" },
|
||||
{ "CVAR", "a dollar sign" },
|
||||
{ "CENDVAR", "a '}' character" },
|
||||
{ "CLP", "a left paren in arithmetic" },
|
||||
{ "CRP", "a right paren in arithmetic" },
|
||||
{ "CEOF", "end of file" },
|
||||
{ "CCTL", "like CWORD, except it must be escaped" },
|
||||
{ "CSPCL", "these terminate a word" },
|
||||
{ NULL, NULL }
|
||||
};
|
||||
|
||||
|
||||
@@ -80,31 +88,39 @@ struct synclass synclass[] = {
|
||||
* you may have to change the definition of the is_in_name macro.
|
||||
*/
|
||||
struct synclass is_entry[] = {
|
||||
"ISDIGIT", "a digit",
|
||||
"ISUPPER", "an upper case letter",
|
||||
"ISLOWER", "a lower case letter",
|
||||
"ISUNDER", "an underscore",
|
||||
"ISSPECL", "the name of a special parameter",
|
||||
NULL, NULL,
|
||||
{ "ISDIGIT", "a digit" },
|
||||
{ "ISUPPER", "an upper case letter" },
|
||||
{ "ISLOWER", "a lower case letter" },
|
||||
{ "ISUNDER", "an underscore" },
|
||||
{ "ISSPECL", "the name of a special parameter" },
|
||||
{ NULL, NULL }
|
||||
};
|
||||
|
||||
char writer[] = "\
|
||||
static char writer[] = "\
|
||||
/*\n\
|
||||
* This file was generated by the mksyntax program.\n\
|
||||
*/\n\
|
||||
\n";
|
||||
|
||||
|
||||
FILE *cfile;
|
||||
FILE *hfile;
|
||||
char *syntax[513];
|
||||
int base;
|
||||
int size; /* number of values which a char variable can have */
|
||||
int nbits; /* number of bits in a character */
|
||||
int digit_contig; /* true if digits are contiguous */
|
||||
static FILE *cfile;
|
||||
static FILE *hfile;
|
||||
static char *syntax[513];
|
||||
static int base;
|
||||
static int size; /* number of values which a char variable can have */
|
||||
static int nbits; /* number of bits in a character */
|
||||
static int digit_contig;/* true if digits are contiguous */
|
||||
|
||||
static void filltable(char *);
|
||||
static void init(void);
|
||||
static void add(char *, char *);
|
||||
static void print(char *);
|
||||
static void output_type_macros(void);
|
||||
static void digit_convert(void);
|
||||
|
||||
main() {
|
||||
int
|
||||
main(int argc __unused, char **argv __unused)
|
||||
{
|
||||
char c;
|
||||
char d;
|
||||
int sign;
|
||||
@@ -136,7 +152,9 @@ main() {
|
||||
if (d == c)
|
||||
break;
|
||||
}
|
||||
#if 0
|
||||
printf("%s %d bit chars\n", sign? "signed" : "unsigned", nbits);
|
||||
#endif
|
||||
if (nbits > 9) {
|
||||
fputs("Characters can't have more than 9 bits\n", stderr);
|
||||
exit(2);
|
||||
@@ -151,14 +169,14 @@ main() {
|
||||
digit_contig = 0;
|
||||
}
|
||||
|
||||
fputs("#include <sys/cdefs.h>\n", hfile);
|
||||
fputs("#include <ctype.h>\n", hfile);
|
||||
|
||||
/* Generate the #define statements in the header file */
|
||||
fputs("/* Syntax classes */\n", hfile);
|
||||
for (i = 0 ; synclass[i].name ; i++) {
|
||||
sprintf(buf, "#define %s %d", synclass[i].name, i);
|
||||
fputs(buf, hfile);
|
||||
for (pos = strlen(buf) ; pos < 32 ; pos = pos + 8 &~ 07)
|
||||
for (pos = strlen(buf) ; pos < 32 ; pos = (pos + 8) & ~07)
|
||||
putc('\t', hfile);
|
||||
fprintf(hfile, "/* %s */\n", synclass[i].comment);
|
||||
}
|
||||
@@ -167,7 +185,7 @@ main() {
|
||||
for (i = 0 ; is_entry[i].name ; i++) {
|
||||
sprintf(buf, "#define %s %#o", is_entry[i].name, 1 << i);
|
||||
fputs(buf, hfile);
|
||||
for (pos = strlen(buf) ; pos < 32 ; pos = pos + 8 &~ 07)
|
||||
for (pos = strlen(buf) ; pos < 32 ; pos = (pos + 8) & ~07)
|
||||
putc('\t', hfile);
|
||||
fprintf(hfile, "/* %s */\n", is_entry[i].comment);
|
||||
}
|
||||
@@ -178,6 +196,7 @@ main() {
|
||||
fputs("#define BASESYNTAX (basesyntax + SYNBASE)\n", hfile);
|
||||
fputs("#define DQSYNTAX (dqsyntax + SYNBASE)\n", hfile);
|
||||
fputs("#define SQSYNTAX (sqsyntax + SYNBASE)\n", hfile);
|
||||
fputs("#define ARISYNTAX (arisyntax + SYNBASE)\n", hfile);
|
||||
putc('\n', hfile);
|
||||
output_type_macros(); /* is_digit, etc. */
|
||||
putc('\n', hfile);
|
||||
@@ -204,14 +223,28 @@ main() {
|
||||
add("`", "CBQUOTE");
|
||||
add("$", "CVAR");
|
||||
add("}", "CENDVAR");
|
||||
add("!*?[=", "CCTL");
|
||||
/* ':/' for tilde expansion, '-' for [a\-x] pattern ranges */
|
||||
add("!*?[=~:/-", "CCTL");
|
||||
print("dqsyntax");
|
||||
init();
|
||||
fputs("\n/* syntax table used when in single quotes */\n", cfile);
|
||||
add("\n", "CNL");
|
||||
add("'", "CENDQUOTE");
|
||||
add("!*?[=", "CCTL");
|
||||
/* ':/' for tilde expansion, '-' for [a\-x] pattern ranges */
|
||||
add("!*?[=~:/-", "CCTL");
|
||||
print("sqsyntax");
|
||||
init();
|
||||
fputs("\n/* syntax table used when in arithmetic */\n", cfile);
|
||||
add("\n", "CNL");
|
||||
add("\\", "CBACK");
|
||||
add("`", "CBQUOTE");
|
||||
add("'", "CSQUOTE");
|
||||
add("\"", "CDQUOTE");
|
||||
add("$", "CVAR");
|
||||
add("}", "CENDVAR");
|
||||
add("(", "CLP");
|
||||
add(")", "CRP");
|
||||
print("arisyntax");
|
||||
filltable("0");
|
||||
fputs("\n/* character classification table */\n", cfile);
|
||||
add("0123456789", "ISDIGIT");
|
||||
@@ -231,9 +264,9 @@ main() {
|
||||
* Clear the syntax table.
|
||||
*/
|
||||
|
||||
filltable(dftval)
|
||||
char *dftval;
|
||||
{
|
||||
static void
|
||||
filltable(char *dftval)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0 ; i < size ; i++)
|
||||
@@ -245,7 +278,9 @@ filltable(dftval)
|
||||
* Initialize the syntax table with default values.
|
||||
*/
|
||||
|
||||
init() {
|
||||
static void
|
||||
init(void)
|
||||
{
|
||||
filltable("CWORD");
|
||||
syntax[0] = "CEOF";
|
||||
syntax[base + CTLESC] = "CCTL";
|
||||
@@ -253,6 +288,9 @@ init() {
|
||||
syntax[base + CTLENDVAR] = "CCTL";
|
||||
syntax[base + CTLBACKQ] = "CCTL";
|
||||
syntax[base + CTLBACKQ + CTLQUOTE] = "CCTL";
|
||||
syntax[base + CTLARI] = "CCTL";
|
||||
syntax[base + CTLENDARI] = "CCTL";
|
||||
syntax[base + CTLQUOTEMARK] = "CCTL";
|
||||
}
|
||||
|
||||
|
||||
@@ -260,9 +298,9 @@ init() {
|
||||
* Add entries to the syntax table.
|
||||
*/
|
||||
|
||||
add(p, type)
|
||||
char *p, *type;
|
||||
{
|
||||
static void
|
||||
add(char *p, char *type)
|
||||
{
|
||||
while (*p)
|
||||
syntax[*p++ + base] = type;
|
||||
}
|
||||
@@ -273,9 +311,9 @@ add(p, type)
|
||||
* Output the syntax table.
|
||||
*/
|
||||
|
||||
print(name)
|
||||
char *name;
|
||||
{
|
||||
static void
|
||||
print(char *name)
|
||||
{
|
||||
int i;
|
||||
int col;
|
||||
|
||||
@@ -306,16 +344,18 @@ print(name)
|
||||
* contiguous, we can test for them quickly.
|
||||
*/
|
||||
|
||||
char *macro[] = {
|
||||
static char *macro[] = {
|
||||
"#define is_digit(c)\t((is_type+SYNBASE)[c] & ISDIGIT)",
|
||||
"#define is_alpha(c)\t((is_type+SYNBASE)[c] & (ISUPPER|ISLOWER))",
|
||||
"#define is_name(c)\t((is_type+SYNBASE)[c] & (ISUPPER|ISLOWER|ISUNDER))",
|
||||
"#define is_in_name(c)\t((is_type+SYNBASE)[c] & (ISUPPER|ISLOWER|ISUNDER|ISDIGIT))",
|
||||
"#define is_alpha(c)\t((c) != PEOF && ((c) < CTLESC || (c) > CTLQUOTEMARK) && isalpha((unsigned char) (c)))",
|
||||
"#define is_name(c)\t((c) != PEOF && ((c) < CTLESC || (c) > CTLQUOTEMARK) && ((c) == '_' || isalpha((unsigned char) (c))))",
|
||||
"#define is_in_name(c)\t((c) != PEOF && ((c) < CTLESC || (c) > CTLQUOTEMARK) && ((c) == '_' || isalnum((unsigned char) (c))))",
|
||||
"#define is_special(c)\t((is_type+SYNBASE)[c] & (ISSPECL|ISDIGIT))",
|
||||
NULL
|
||||
};
|
||||
|
||||
output_type_macros() {
|
||||
static void
|
||||
output_type_macros(void)
|
||||
{
|
||||
char **pp;
|
||||
|
||||
if (digit_contig)
|
||||
@@ -334,7 +374,9 @@ output_type_macros() {
|
||||
* Output digit conversion table (if digits are not contiguous).
|
||||
*/
|
||||
|
||||
digit_convert() {
|
||||
static void
|
||||
digit_convert(void)
|
||||
{
|
||||
int maxdigit;
|
||||
static char digit[] = "0123456789";
|
||||
char *p;
|
||||
@@ -350,7 +392,11 @@ digit_convert() {
|
||||
for (p = digit ; *p && *p != i ; p++);
|
||||
if (*p == '\0')
|
||||
p = digit;
|
||||
fprintf(cfile, " %d,\n", p - digit);
|
||||
fprintf(cfile, " %d,\n", (int)(p - digit));
|
||||
}
|
||||
fputs("};\n", cfile);
|
||||
}
|
||||
|
||||
/*
|
||||
* $PchId: mksyntax.c,v 1.7 2006/05/23 12:04:27 philip Exp $
|
||||
*/
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#!/bin/sh -
|
||||
#
|
||||
# Copyright (c) 1991 The Regents of the University of California.
|
||||
# All rights reserved.
|
||||
# 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.
|
||||
@@ -14,10 +14,6 @@
|
||||
# 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.
|
||||
@@ -34,7 +30,8 @@
|
||||
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
# SUCH DAMAGE.
|
||||
#
|
||||
# @(#)mktokens 5.1 (Berkeley) 3/7/91
|
||||
# @(#)mktokens 8.1 (Berkeley) 5/31/93
|
||||
# $FreeBSD: src/bin/sh/mktokens,v 1.9 2004/04/06 20:06:51 markm Exp $
|
||||
|
||||
# All calls to awk removed, because Minix bawk is deficient. (kjb)
|
||||
|
||||
@@ -42,7 +39,9 @@
|
||||
# token marks the end of a list. The third column is the name to print in
|
||||
# error messages.
|
||||
|
||||
cat > /tmp/ka$$ <<\!
|
||||
#temp=`/usr/bin/mktemp -t ka`
|
||||
temp=/tmp/mkt$$
|
||||
cat > $temp <<\!
|
||||
TEOF 1 end of file
|
||||
TNL 0 newline
|
||||
TSEMI 0 ";"
|
||||
@@ -70,16 +69,17 @@ TBEGIN 0 "{"
|
||||
TEND 1 "}"
|
||||
TCASE 0 "case"
|
||||
TESAC 1 "esac"
|
||||
TNOT 0 "!"
|
||||
!
|
||||
nl=`wc -l /tmp/ka$$`
|
||||
exec > token.def
|
||||
nl=`wc -l $temp`
|
||||
exec > token.h
|
||||
i=0
|
||||
while read line
|
||||
do
|
||||
set -$- $line
|
||||
echo "#define $1 $i"
|
||||
i=`expr $i + 1`
|
||||
done </tmp/ka$$
|
||||
done <$temp
|
||||
echo '
|
||||
/* Array indicating which tokens mark the end of a list */
|
||||
const char tokendlist[] = {'
|
||||
@@ -87,18 +87,18 @@ while read line
|
||||
do
|
||||
set -$- $line
|
||||
echo " $2,"
|
||||
done </tmp/ka$$
|
||||
done <$temp
|
||||
echo '};
|
||||
|
||||
char *const tokname[] = {'
|
||||
const char *const tokname[] = {'
|
||||
sed -e 's/"/\\"/g' \
|
||||
-e 's/[^ ]*[ ][ ]*[^ ]*[ ][ ]*\(.*\)/ "\1",/' \
|
||||
/tmp/ka$$
|
||||
$temp
|
||||
echo '};
|
||||
'
|
||||
i=0
|
||||
go=
|
||||
sed 's/"//g' /tmp/ka$$ |
|
||||
sed 's/"//g' $temp |
|
||||
while read line
|
||||
do
|
||||
set -$- $line
|
||||
@@ -106,7 +106,7 @@ sed 's/"//g' /tmp/ka$$ |
|
||||
then
|
||||
echo "#define KWDOFFSET $i"
|
||||
echo
|
||||
echo "char *const parsekwd[] = {"
|
||||
echo "const char *const parsekwd[] = {"
|
||||
go=true
|
||||
fi
|
||||
if [ "$go" ]
|
||||
@@ -118,4 +118,7 @@ sed 's/"//g' /tmp/ka$$ |
|
||||
echo ' 0
|
||||
};'
|
||||
|
||||
rm /tmp/ka$$
|
||||
rm $temp
|
||||
|
||||
#
|
||||
# $PchId: mktokens,v 1.5 2006/05/22 12:43:35 philip Exp $
|
||||
|
||||
50
commands/ash/myhistedit.h
Normal file
50
commands/ash/myhistedit.h
Normal file
@@ -0,0 +1,50 @@
|
||||
/*-
|
||||
* 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.
|
||||
* 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.
|
||||
*
|
||||
* @(#)myhistedit.h 8.2 (Berkeley) 5/4/95
|
||||
* $FreeBSD: src/bin/sh/myhistedit.h,v 1.10 2004/04/06 20:06:51 markm Exp $
|
||||
*/
|
||||
|
||||
#include <histedit.h>
|
||||
|
||||
extern History *hist;
|
||||
extern EditLine *el;
|
||||
extern int displayhist;
|
||||
|
||||
void histedit(void);
|
||||
void sethistsize(const char *);
|
||||
int histcmd(int, char **);
|
||||
int bindcmd(int, char **);
|
||||
|
||||
/* From libedit */
|
||||
void re_goto_bottom(EditLine *);
|
||||
|
||||
/*
|
||||
* $PchId: myhistedit.h,v 1.5 2006/03/29 15:55:18 philip Exp $
|
||||
*/
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*-
|
||||
* Copyright (c) 1991 The Regents of the University of California.
|
||||
* All rights reserved.
|
||||
* 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.
|
||||
@@ -13,10 +13,6 @@
|
||||
* 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.
|
||||
@@ -35,8 +31,14 @@
|
||||
*/
|
||||
|
||||
#ifndef lint
|
||||
static char sccsid[] = "@(#)mystring.c 5.1 (Berkeley) 3/7/91";
|
||||
#if 0
|
||||
static char sccsid[] = "@(#)mystring.c 8.2 (Berkeley) 5/4/95";
|
||||
#endif
|
||||
#endif /* not lint */
|
||||
/*
|
||||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD: src/bin/sh/mystring.c,v 1.13 2004/04/06 20:06:51 markm Exp $");
|
||||
*/
|
||||
|
||||
/*
|
||||
* String functions.
|
||||
@@ -44,12 +46,11 @@ static char sccsid[] = "@(#)mystring.c 5.1 (Berkeley) 3/7/91";
|
||||
* 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.
|
||||
* strchr(s, c) Find first occurance of c in s.
|
||||
* bcopy(from, to, n) Copy a block of memory.
|
||||
* 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"
|
||||
@@ -58,6 +59,14 @@ static char sccsid[] = "@(#)mystring.c 5.1 (Berkeley) 3/7/91";
|
||||
|
||||
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
|
||||
@@ -66,11 +75,8 @@ char nullstr[1]; /* zero length string */
|
||||
*/
|
||||
|
||||
void
|
||||
scopyn(from, to, size)
|
||||
register char const *from;
|
||||
register char *to;
|
||||
register int size;
|
||||
{
|
||||
scopyn(const char *from, char *to, int size)
|
||||
{
|
||||
|
||||
while (--size > 0) {
|
||||
if ((*to++ = *from++) == '\0')
|
||||
@@ -80,59 +86,13 @@ scopyn(from, to, size)
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* strchr - find first occurrence of a character in a string.
|
||||
*/
|
||||
|
||||
#ifndef SYS5
|
||||
char *
|
||||
mystrchr(s, charwanted)
|
||||
char const *s;
|
||||
register char charwanted;
|
||||
{
|
||||
register char const *scan;
|
||||
|
||||
/*
|
||||
* The odd placement of the two tests is so NUL is findable.
|
||||
*/
|
||||
for (scan = s ; *scan != charwanted ; ) /* ++ moved down for opt. */
|
||||
if (*scan++ == '\0')
|
||||
return NULL;
|
||||
return (char *)scan;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* bcopy - copy bytes
|
||||
*
|
||||
* This routine was derived from code by Henry Spencer.
|
||||
*/
|
||||
|
||||
void
|
||||
mybcopy(src, dst, length)
|
||||
pointer dst;
|
||||
const pointer src;
|
||||
register int length;
|
||||
{
|
||||
register char *d = dst;
|
||||
register char *s = src;
|
||||
|
||||
while (--length >= 0)
|
||||
*d++ = *s++;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* prefix -- see if pfx is a prefix of string.
|
||||
*/
|
||||
|
||||
int
|
||||
prefix(pfx, string)
|
||||
register char const *pfx;
|
||||
register char const *string;
|
||||
{
|
||||
prefix(const char *pfx, const char *string)
|
||||
{
|
||||
while (*pfx) {
|
||||
if (*pfx++ != *string++)
|
||||
return 0;
|
||||
@@ -147,12 +107,10 @@ prefix(pfx, string)
|
||||
*/
|
||||
|
||||
int
|
||||
number(s)
|
||||
const char *s;
|
||||
{
|
||||
|
||||
number(const char *s)
|
||||
{
|
||||
if (! is_number(s))
|
||||
error2("Illegal number", (char *)s);
|
||||
error("Illegal number: %s", (char *)s);
|
||||
return atoi(s);
|
||||
}
|
||||
|
||||
@@ -163,12 +121,15 @@ number(s)
|
||||
*/
|
||||
|
||||
int
|
||||
is_number(p)
|
||||
register const char *p;
|
||||
{
|
||||
is_number(const char *p)
|
||||
{
|
||||
do {
|
||||
if (! is_digit(*p))
|
||||
return 0;
|
||||
} while (*++p != '\0');
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* $PchId: mystring.c,v 1.4 2006/05/22 12:21:53 philip Exp $
|
||||
*/
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*-
|
||||
* Copyright (c) 1991 The Regents of the University of California.
|
||||
* All rights reserved.
|
||||
* 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.
|
||||
@@ -13,10 +13,6 @@
|
||||
* 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.
|
||||
@@ -33,39 +29,20 @@
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)mystring.h 5.1 (Berkeley) 3/7/91
|
||||
* @(#)mystring.h 8.2 (Berkeley) 5/4/95
|
||||
* $FreeBSD: src/bin/sh/mystring.h,v 1.8 2004/04/06 20:06:51 markm Exp $
|
||||
*/
|
||||
|
||||
#ifndef SYSV
|
||||
#define strchr mystrchr
|
||||
#endif
|
||||
#include <string.h>
|
||||
|
||||
#ifdef __STDC__
|
||||
void scopyn(const char *, char *, int);
|
||||
char *strchr(const char *, int);
|
||||
void mybcopy(const pointer, pointer, int);
|
||||
int prefix(const char *, const char *);
|
||||
int number(const char *);
|
||||
int is_number(const char *);
|
||||
int strcmp(const char *, const char *); /* from C library */
|
||||
char *strcpy(char *, const char *); /* from C library */
|
||||
int strlen(const char *); /* from C library */
|
||||
char *strcat(char *, const char *); /* from C library */
|
||||
char *strerror(int); /* from C library */
|
||||
#else
|
||||
void scopyn();
|
||||
char *strchr();
|
||||
void mybcopy();
|
||||
int prefix();
|
||||
int number();
|
||||
int is_number();
|
||||
int strcmp();
|
||||
char *strcpy();
|
||||
int strlen();
|
||||
char *strcat();
|
||||
char *strerror();
|
||||
#endif
|
||||
|
||||
#define equal(s1, s2) (strcmp(s1, s2) == 0)
|
||||
#define scopy(s1, s2) ((void)strcpy(s2, s1))
|
||||
#define bcopy(src, dst, n) mybcopy((pointer)(src), (pointer)(dst), n)
|
||||
|
||||
/*
|
||||
* $PchId: mystring.h,v 1.3 2006/03/29 15:49:08 philip Exp $
|
||||
*/
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*-
|
||||
* Copyright (c) 1991 The Regents of the University of California.
|
||||
* All rights reserved.
|
||||
* 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.
|
||||
@@ -13,10 +13,6 @@
|
||||
* 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.
|
||||
@@ -33,9 +29,11 @@
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)nodes.c.pat 5.2 (Berkeley) 3/8/91
|
||||
* @(#)nodes.c.pat 8.2 (Berkeley) 5/4/95
|
||||
* $FreeBSD: src/bin/sh/nodes.c.pat,v 1.15 2004/04/06 20:06:51 markm Exp $
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
/*
|
||||
* Routine for dealing with parsed shell commands.
|
||||
*/
|
||||
@@ -43,35 +41,26 @@
|
||||
#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 */
|
||||
#ifdef __STDC__
|
||||
pointer funcblock; /* block to allocate function from */
|
||||
#else
|
||||
char *funcblock; /* block to allocate function from */
|
||||
#ifndef __minix
|
||||
#include <sys/param.h>
|
||||
#endif
|
||||
char *funcstring; /* block to allocate strings from */
|
||||
#include "machdep.h"
|
||||
|
||||
STATIC int funcblocksize; /* size of structures in function */
|
||||
STATIC int funcstringsize; /* size of strings in node */
|
||||
STATIC pointer funcblock; /* block to allocate function from */
|
||||
STATIC char *funcstring; /* block to allocate strings from */
|
||||
|
||||
%SIZES
|
||||
|
||||
|
||||
#ifdef __STDC__
|
||||
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 *);
|
||||
#else
|
||||
STATIC void calcsize();
|
||||
STATIC void sizenodelist();
|
||||
STATIC union node *copynode();
|
||||
STATIC struct nodelist *copynodelist();
|
||||
STATIC char *nodesavestr();
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
@@ -80,86 +69,81 @@ STATIC char *nodesavestr();
|
||||
*/
|
||||
|
||||
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);
|
||||
copyfunc(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
|
||||
calcsize(union node *n)
|
||||
{
|
||||
%CALCSIZE
|
||||
}
|
||||
|
||||
|
||||
|
||||
STATIC void
|
||||
sizenodelist(lp)
|
||||
struct nodelist *lp;
|
||||
{
|
||||
while (lp) {
|
||||
funcblocksize += ALIGN(sizeof (struct nodelist));
|
||||
calcsize(lp->n);
|
||||
lp = lp->next;
|
||||
}
|
||||
sizenodelist(struct nodelist *lp)
|
||||
{
|
||||
while (lp) {
|
||||
funcblocksize += ALIGN(sizeof(struct nodelist));
|
||||
calcsize(lp->n);
|
||||
lp = lp->next;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
STATIC union node *
|
||||
copynode(n)
|
||||
union node *n;
|
||||
{
|
||||
union node *new;
|
||||
copynode(union node *n)
|
||||
{
|
||||
union node *new;
|
||||
|
||||
%COPY
|
||||
return new;
|
||||
%COPY
|
||||
return new;
|
||||
}
|
||||
|
||||
|
||||
STATIC struct nodelist *
|
||||
copynodelist(lp)
|
||||
struct nodelist *lp;
|
||||
{
|
||||
struct nodelist *start;
|
||||
struct nodelist **lpp;
|
||||
copynodelist(struct nodelist *lp)
|
||||
{
|
||||
struct nodelist *start;
|
||||
struct nodelist **lpp;
|
||||
|
||||
lpp = &start;
|
||||
while (lp) {
|
||||
*lpp = funcblock;
|
||||
*(char **)&funcblock += ALIGN(sizeof (struct nodelist));
|
||||
(*lpp)->n = copynode(lp->n);
|
||||
lp = lp->next;
|
||||
lpp = &(*lpp)->next;
|
||||
}
|
||||
*lpp = NULL;
|
||||
return start;
|
||||
lpp = &start;
|
||||
while (lp) {
|
||||
*lpp = funcblock;
|
||||
funcblock = (char *)funcblock + 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;
|
||||
nodesavestr(char *s)
|
||||
{
|
||||
char *p = s;
|
||||
char *q = funcstring;
|
||||
char *rtn = funcstring;
|
||||
|
||||
while (*q++ = *p++);
|
||||
funcstring = q;
|
||||
return rtn;
|
||||
while ((*q++ = *p++) != '\0')
|
||||
continue;
|
||||
funcstring = q;
|
||||
return rtn;
|
||||
}
|
||||
|
||||
|
||||
@@ -169,9 +153,12 @@ nodesavestr(s)
|
||||
*/
|
||||
|
||||
void
|
||||
freefunc(n)
|
||||
union node *n;
|
||||
{
|
||||
if (n)
|
||||
ckfree(n);
|
||||
freefunc(union node *n)
|
||||
{
|
||||
if (n)
|
||||
ckfree(n);
|
||||
}
|
||||
|
||||
/*
|
||||
* $PchId: nodes.c.pat,v 1.5 2006/05/22 12:43:57 philip Exp $
|
||||
*/
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
#!/bin/sh -
|
||||
#
|
||||
# Copyright (c) 1991 The Regents of the University of California.
|
||||
# All rights reserved.
|
||||
# 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.
|
||||
@@ -14,10 +13,6 @@
|
||||
# 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.
|
||||
@@ -34,7 +29,8 @@
|
||||
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
# SUCH DAMAGE.
|
||||
#
|
||||
# @(#)nodetypes 5.1 (Berkeley) 3/7/91
|
||||
# @(#)nodetypes 8.2 (Berkeley) 5/4/95
|
||||
# $FreeBSD: src/bin/sh/nodetypes,v 1.9 2004/04/06 20:06:51 markm Exp $
|
||||
|
||||
# This file describes the nodes used in parse trees. Unindented lines
|
||||
# contain a node type followed by a structure tag. Subsequent indented
|
||||
@@ -118,7 +114,9 @@ NARG narg # represents a word
|
||||
|
||||
NTO nfile # fd> fname
|
||||
NFROM nfile # fd< fname
|
||||
NFROMTO nfile # fd<> fname
|
||||
NAPPEND nfile # fd>> fname
|
||||
NCLOBBER nfile # fd>| fname
|
||||
type int
|
||||
next nodeptr # next redirection in list
|
||||
fd int # file descriptor being redirected
|
||||
@@ -131,6 +129,8 @@ NFROMFD ndup # fd>&dupfd
|
||||
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<<!
|
||||
@@ -138,3 +138,10 @@ NXHERE nhere # fd<<!
|
||||
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
|
||||
|
||||
#
|
||||
# $PchId: nodetypes,v 1.3 2006/03/29 15:43:35 philip Exp $
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*-
|
||||
* Copyright (c) 1991 The Regents of the University of California.
|
||||
* All rights reserved.
|
||||
* 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.
|
||||
@@ -13,10 +13,6 @@
|
||||
* 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.
|
||||
@@ -35,8 +31,18 @@
|
||||
*/
|
||||
|
||||
#ifndef lint
|
||||
static char sccsid[] = "@(#)options.c 5.2 (Berkeley) 3/13/91";
|
||||
#if 0
|
||||
static char sccsid[] = "@(#)options.c 8.2 (Berkeley) 5/4/95";
|
||||
#endif
|
||||
#endif /* not lint */
|
||||
/*
|
||||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD: src/bin/sh/options.c,v 1.21 2004/04/06 20:06:51 markm Exp $");
|
||||
*/
|
||||
|
||||
#include <signal.h>
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "shell.h"
|
||||
#define DEFINE_OPTIONS
|
||||
@@ -52,25 +58,25 @@ static char sccsid[] = "@(#)options.c 5.2 (Berkeley) 3/13/91";
|
||||
#include "memalloc.h"
|
||||
#include "error.h"
|
||||
#include "mystring.h"
|
||||
#include "builtins.h"
|
||||
#if !defined(NO_HISTORY) && !defined(EDITLINE)
|
||||
#include "myhistedit.h"
|
||||
#endif
|
||||
|
||||
char *arg0; /* value of $0 */
|
||||
struct shparam shellparam; /* current positional parameters */
|
||||
char **argptr; /* argument list for builtin commands */
|
||||
char *optarg; /* set by nextopt (like getopt) */
|
||||
char *shoptarg; /* set by nextopt (like getopt) */
|
||||
char *optptr; /* used by nextopt */
|
||||
int editable; /* isatty(0) && isatty(1) */
|
||||
int editable; /* isatty(0) && isatty(1) */
|
||||
|
||||
char *minusc; /* argument to -c option */
|
||||
|
||||
|
||||
#ifdef __STDC__
|
||||
STATIC void options(int);
|
||||
STATIC void minus_o(char *, int);
|
||||
STATIC void setoption(int, int);
|
||||
#else
|
||||
STATIC void options();
|
||||
STATIC void setoption();
|
||||
#endif
|
||||
|
||||
STATIC int getopts(char *, char *, char **, char ***, char **);
|
||||
|
||||
|
||||
/*
|
||||
@@ -78,46 +84,56 @@ STATIC void setoption();
|
||||
*/
|
||||
|
||||
void
|
||||
procargs(argc, argv)
|
||||
char **argv;
|
||||
{
|
||||
char *p;
|
||||
procargs(int argc, char **argv)
|
||||
{
|
||||
int i;
|
||||
|
||||
argptr = argv;
|
||||
if (argc > 0)
|
||||
argptr++;
|
||||
for (p = optval ; p < optval + sizeof optval - 1 ; p++)
|
||||
*p = 2;
|
||||
for (i = 0; i < NOPTS; i++)
|
||||
optlist[i].val = 2;
|
||||
privileged = (getuid() != geteuid() || getgid() != getegid());
|
||||
options(1);
|
||||
if (*argptr == NULL && minusc == NULL)
|
||||
sflag = 1;
|
||||
editable = (isatty(0) && isatty(1));
|
||||
if (iflag == 2 && sflag == 1 && editable)
|
||||
iflag = 1;
|
||||
if (jflag == 2)
|
||||
jflag = iflag;
|
||||
for (p = optval ; p < optval + sizeof optval - 1 ; p++)
|
||||
if (*p == 2)
|
||||
*p = 0;
|
||||
if (mflag == 2)
|
||||
mflag = iflag;
|
||||
for (i = 0; i < NOPTS; i++)
|
||||
if (optlist[i].val == 2)
|
||||
optlist[i].val = 0;
|
||||
arg0 = argv[0];
|
||||
if (sflag == 0) {
|
||||
arg0 = *argptr++;
|
||||
if (minusc == NULL) {
|
||||
commandname = arg0;
|
||||
setinputfile(commandname, 0);
|
||||
}
|
||||
if (sflag == 0 && minusc == NULL) {
|
||||
commandname = arg0 = *argptr++;
|
||||
setinputfile(commandname, 0);
|
||||
}
|
||||
/* POSIX 1003.2: first arg after -c cmd is $0, remainder $1... */
|
||||
if (argptr && minusc && *argptr)
|
||||
arg0 = *argptr++;
|
||||
|
||||
shellparam.p = argptr;
|
||||
shellparam.reset = 1;
|
||||
/* assert(shellparam.malloc == 0 && shellparam.nparam == 0); */
|
||||
while (*argptr) {
|
||||
shellparam.nparam++;
|
||||
argptr++;
|
||||
}
|
||||
setinteractive(iflag);
|
||||
setjobctl(jflag);
|
||||
optschanged();
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
optschanged(void)
|
||||
{
|
||||
setinteractive(iflag);
|
||||
#if !defined(NO_HISTORY) && !defined(EDITLINE)
|
||||
histedit();
|
||||
#endif
|
||||
setjobctl(mflag);
|
||||
}
|
||||
|
||||
/*
|
||||
* Process shell options. The global variable argptr contains a pointer
|
||||
@@ -125,8 +141,9 @@ procargs(argc, argv)
|
||||
*/
|
||||
|
||||
STATIC void
|
||||
options(cmdline) {
|
||||
register char *p;
|
||||
options(int cmdline)
|
||||
{
|
||||
char *p;
|
||||
int val;
|
||||
int c;
|
||||
|
||||
@@ -136,14 +153,14 @@ options(cmdline) {
|
||||
argptr++;
|
||||
if ((c = *p++) == '-') {
|
||||
val = 1;
|
||||
if (p[0] == '\0' || p[0] == '-' && p[1] == '\0') {
|
||||
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);
|
||||
setparam(argptr);
|
||||
}
|
||||
break; /* "-" or "--" terminates options */
|
||||
}
|
||||
@@ -166,26 +183,79 @@ options(cmdline) {
|
||||
#ifdef NOHACK
|
||||
break;
|
||||
#endif
|
||||
} else if (c == 'o') {
|
||||
minus_o(*argptr, val);
|
||||
if (*argptr)
|
||||
argptr++;
|
||||
} else {
|
||||
if (c == 'p' && !val && privileged) {
|
||||
(void) setuid(getuid());
|
||||
(void) setgid(getgid());
|
||||
}
|
||||
setoption(c, val);
|
||||
}
|
||||
}
|
||||
if (! cmdline)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
STATIC void
|
||||
minus_o(char *name, int val)
|
||||
{
|
||||
int doneset, i;
|
||||
|
||||
if (name == NULL) {
|
||||
if (val) {
|
||||
/* "Pretty" output. */
|
||||
out1str("Current option settings\n");
|
||||
for (i = 0; i < NOPTS; i++)
|
||||
out1fmt("%-16s%s\n", optlist[i].name,
|
||||
optlist[i].val ? "on" : "off");
|
||||
} else {
|
||||
/* Output suitable for re-input to shell. */
|
||||
for (doneset = i = 0; i < NOPTS; i++)
|
||||
if (optlist[i].val) {
|
||||
if (!doneset) {
|
||||
out1str("set");
|
||||
doneset = 1;
|
||||
}
|
||||
out1fmt(" -o %s", optlist[i].name);
|
||||
}
|
||||
if (doneset)
|
||||
out1c('\n');
|
||||
}
|
||||
} else {
|
||||
for (i = 0; i < NOPTS; i++)
|
||||
if (equal(name, optlist[i].name)) {
|
||||
if (!val && privileged && equal(name, "privileged")) {
|
||||
(void) setuid(getuid());
|
||||
(void) setgid(getgid());
|
||||
}
|
||||
setoption(optlist[i].letter, val);
|
||||
return;
|
||||
}
|
||||
error("Illegal option -o %s", name);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
STATIC void
|
||||
setoption(flag, val)
|
||||
char flag;
|
||||
int val;
|
||||
{
|
||||
register char *p;
|
||||
setoption(int flag, int val)
|
||||
{
|
||||
int i;
|
||||
|
||||
if ((p = strchr(optchar, flag)) == NULL)
|
||||
error("Illegal option -%c", flag);
|
||||
optval[p - optchar] = val;
|
||||
for (i = 0; i < NOPTS; i++)
|
||||
if (optlist[i].letter == flag) {
|
||||
optlist[i].val = val;
|
||||
if (val) {
|
||||
/* #%$ hack for ksh semantics */
|
||||
if (flag == 'V')
|
||||
Eflag = 0;
|
||||
else if (flag == 'E')
|
||||
Vflag = 0;
|
||||
}
|
||||
return;
|
||||
}
|
||||
error("Illegal option -%c", flag);
|
||||
}
|
||||
|
||||
|
||||
@@ -194,10 +264,12 @@ setoption(flag, val)
|
||||
INCLUDE "options.h"
|
||||
|
||||
SHELLPROC {
|
||||
char *p;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < NOPTS; i++)
|
||||
optlist[i].val = 0;
|
||||
optschanged();
|
||||
|
||||
for (p = optval ; p < optval + sizeof optval ; p++)
|
||||
*p = 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -207,9 +279,8 @@ SHELLPROC {
|
||||
*/
|
||||
|
||||
void
|
||||
setparam(argv)
|
||||
char **argv;
|
||||
{
|
||||
setparam(char **argv)
|
||||
{
|
||||
char **newparam;
|
||||
char **ap;
|
||||
int nparam;
|
||||
@@ -233,9 +304,8 @@ setparam(argv)
|
||||
*/
|
||||
|
||||
void
|
||||
freeparam(param)
|
||||
struct shparam *param;
|
||||
{
|
||||
freeparam(struct shparam *param)
|
||||
{
|
||||
char **ap;
|
||||
|
||||
if (param->malloc) {
|
||||
@@ -251,7 +321,9 @@ freeparam(param)
|
||||
* The shift builtin command.
|
||||
*/
|
||||
|
||||
shiftcmd(argc, argv) char **argv; {
|
||||
int
|
||||
shiftcmd(int argc, char **argv)
|
||||
{
|
||||
int n;
|
||||
char **ap1, **ap2;
|
||||
|
||||
@@ -259,7 +331,7 @@ shiftcmd(argc, argv) char **argv; {
|
||||
if (argc > 1)
|
||||
n = number(argv[1]);
|
||||
if (n > shellparam.nparam)
|
||||
n = shellparam.nparam;
|
||||
error("can't shift that many");
|
||||
INTOFF;
|
||||
shellparam.nparam -= n;
|
||||
for (ap1 = shellparam.p ; --n >= 0 ; ap1++) {
|
||||
@@ -279,13 +351,14 @@ shiftcmd(argc, argv) char **argv; {
|
||||
* The set command builtin.
|
||||
*/
|
||||
|
||||
setcmd(argc, argv) char **argv; {
|
||||
int
|
||||
setcmd(int argc, char **argv)
|
||||
{
|
||||
if (argc == 1)
|
||||
return showvarscmd(argc, argv);
|
||||
INTOFF;
|
||||
options(0);
|
||||
setinteractive(iflag);
|
||||
setjobctl(jflag);
|
||||
optschanged();
|
||||
if (*argptr != NULL) {
|
||||
setparam(argptr);
|
||||
}
|
||||
@@ -294,6 +367,15 @@ setcmd(argc, argv) char **argv; {
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
getoptsreset(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
|
||||
@@ -301,63 +383,127 @@ setcmd(argc, argv) char **argv; {
|
||||
* then it's the first time getopts has been called.
|
||||
*/
|
||||
|
||||
getoptscmd(argc, argv) char **argv; {
|
||||
register char *p, *q;
|
||||
char c;
|
||||
int
|
||||
getoptscmd(int argc, char **argv)
|
||||
{
|
||||
char **optbase = NULL;
|
||||
|
||||
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 **optptr)
|
||||
{
|
||||
char *p, *q;
|
||||
char c = '?';
|
||||
int done = 0;
|
||||
int ind = 0;
|
||||
int err = 0;
|
||||
char s[10];
|
||||
|
||||
if (argc != 3)
|
||||
error("Usage: getopts optstring var");
|
||||
if (shellparam.optnext == NULL) {
|
||||
shellparam.optnext = shellparam.p;
|
||||
shellparam.optptr = NULL;
|
||||
}
|
||||
if ((p = shellparam.optptr) == NULL || *p == '\0') {
|
||||
p = *shellparam.optnext;
|
||||
if ((p = *optptr) == NULL || *p == '\0') {
|
||||
/* Current word is done, advance */
|
||||
if (*optnext == NULL)
|
||||
return 1;
|
||||
p = **optnext;
|
||||
if (p == NULL || *p != '-' || *++p == '\0') {
|
||||
atend:
|
||||
fmtstr(s, 10, "%d", shellparam.optnext - shellparam.p + 1);
|
||||
setvar("OPTIND", s, 0);
|
||||
shellparam.optnext = NULL;
|
||||
return 1;
|
||||
ind = *optnext - optfirst + 1;
|
||||
*optnext = NULL;
|
||||
p = NULL;
|
||||
done = 1;
|
||||
goto out;
|
||||
}
|
||||
shellparam.optnext++;
|
||||
(*optnext)++;
|
||||
if (p[0] == '-' && p[1] == '\0') /* check for "--" */
|
||||
goto atend;
|
||||
}
|
||||
|
||||
c = *p++;
|
||||
for (q = argv[1] ; *q != c ; ) {
|
||||
for (q = optstr; *q != c; ) {
|
||||
if (*q == '\0') {
|
||||
out1fmt("Illegal option -%c\n", c);
|
||||
if (optstr[0] == ':') {
|
||||
s[0] = c;
|
||||
s[1] = '\0';
|
||||
err |= setvarsafe("OPTARG", s, 0);
|
||||
}
|
||||
else {
|
||||
out1fmt("Illegal option -%c\n", c);
|
||||
(void) unsetvar("OPTARG");
|
||||
}
|
||||
c = '?';
|
||||
goto out;
|
||||
goto bad;
|
||||
}
|
||||
if (*++q == ':')
|
||||
q++;
|
||||
}
|
||||
|
||||
if (*++q == ':') {
|
||||
if (*p == '\0') {
|
||||
if ((p = *shellparam.optnext) == NULL) {
|
||||
out1fmt("No arg for -%c option\n", c);
|
||||
c = '?';
|
||||
goto out;
|
||||
if (*p == '\0' && (p = **optnext) == NULL) {
|
||||
if (optstr[0] == ':') {
|
||||
s[0] = c;
|
||||
s[1] = '\0';
|
||||
err |= setvarsafe("OPTARG", s, 0);
|
||||
c = ':';
|
||||
}
|
||||
shellparam.optnext++;
|
||||
else {
|
||||
out1fmt("No arg for -%c option\n", c);
|
||||
(void) unsetvar("OPTARG");
|
||||
c = '?';
|
||||
}
|
||||
goto bad;
|
||||
}
|
||||
setvar("OPTARG", p, 0);
|
||||
p = "";
|
||||
|
||||
if (p == **optnext)
|
||||
(*optnext)++;
|
||||
setvarsafe("OPTARG", p, 0);
|
||||
p = NULL;
|
||||
}
|
||||
else
|
||||
setvarsafe("OPTARG", "", 0);
|
||||
ind = *optnext - optfirst + 1;
|
||||
goto out;
|
||||
|
||||
bad:
|
||||
ind = 1;
|
||||
*optnext = NULL;
|
||||
p = NULL;
|
||||
out:
|
||||
shellparam.optptr = p;
|
||||
*optptr = p;
|
||||
fmtstr(s, sizeof(s), "%d", ind);
|
||||
err |= setvarsafe("OPTIND", s, VNOFUNC);
|
||||
s[0] = c;
|
||||
s[1] = '\0';
|
||||
setvar(argv[2], s, 0);
|
||||
fmtstr(s, 10, "%d", shellparam.optnext - shellparam.p + 1);
|
||||
setvar("OPTIND", s, 0);
|
||||
return 0;
|
||||
err |= setvarsafe(optvar, s, 0);
|
||||
if (err) {
|
||||
*optnext = NULL;
|
||||
*optptr = 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
|
||||
@@ -365,10 +511,9 @@ out:
|
||||
*/
|
||||
|
||||
int
|
||||
nextopt(optstring)
|
||||
char *optstring;
|
||||
{
|
||||
register char *p, *q;
|
||||
nextopt(char *optstring)
|
||||
{
|
||||
char *p, *q;
|
||||
char c;
|
||||
|
||||
if ((p = optptr) == NULL || *p == '\0') {
|
||||
@@ -389,9 +534,13 @@ nextopt(optstring)
|
||||
if (*++q == ':') {
|
||||
if (*p == '\0' && (p = *argptr++) == NULL)
|
||||
error("No arg for -%c option", c);
|
||||
optarg = p;
|
||||
shoptarg = p;
|
||||
p = NULL;
|
||||
}
|
||||
optptr = p;
|
||||
return c;
|
||||
}
|
||||
|
||||
/*
|
||||
* $PchId: options.c,v 1.6 2006/05/29 13:09:12 philip Exp $
|
||||
*/
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*-
|
||||
* Copyright (c) 1991 The Regents of the University of California.
|
||||
* All rights reserved.
|
||||
* 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.
|
||||
@@ -13,10 +13,6 @@
|
||||
* 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.
|
||||
@@ -33,38 +29,71 @@
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)options.h 5.1 (Berkeley) 3/7/91
|
||||
* @(#)options.h 8.2 (Berkeley) 5/4/95
|
||||
* $FreeBSD: src/bin/sh/options.h,v 1.13 2004/04/06 20:06:51 markm Exp $
|
||||
*/
|
||||
|
||||
struct shparam {
|
||||
int nparam; /* number of positional parameters (without $0) */
|
||||
char malloc; /* true if parameter list dynamicly allocated */
|
||||
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 */
|
||||
char **optnext; /* next parameter to be processed by getopts */
|
||||
char *optptr; /* used by getopts */
|
||||
};
|
||||
|
||||
|
||||
|
||||
#define eflag optval[0]
|
||||
#define fflag optval[1]
|
||||
#define Iflag optval[2]
|
||||
#define iflag optval[3]
|
||||
#define jflag optval[4]
|
||||
#define nflag optval[5]
|
||||
#define sflag optval[6]
|
||||
#define xflag optval[7]
|
||||
#define zflag optval[8]
|
||||
#define vflag optval[9]
|
||||
#define eflag optlist[0].val
|
||||
#define fflag optlist[1].val
|
||||
#define Iflag optlist[2].val
|
||||
#define iflag optlist[3].val
|
||||
#define mflag optlist[4].val
|
||||
#define nflag optlist[5].val
|
||||
#define sflag optlist[6].val
|
||||
#define xflag optlist[7].val
|
||||
#define vflag optlist[8].val
|
||||
#define Vflag optlist[9].val
|
||||
#define Eflag optlist[10].val
|
||||
#define Cflag optlist[11].val
|
||||
#define aflag optlist[12].val
|
||||
#define bflag optlist[13].val
|
||||
#define uflag optlist[14].val
|
||||
#define privileged optlist[15].val
|
||||
#define Tflag optlist[16].val
|
||||
#define Pflag optlist[17].val
|
||||
|
||||
#define NOPTS 10
|
||||
#define NOPTS 18
|
||||
|
||||
struct optent {
|
||||
const char *name;
|
||||
const char letter;
|
||||
char val;
|
||||
};
|
||||
|
||||
#ifdef DEFINE_OPTIONS
|
||||
const char optchar[NOPTS+1] = "efIijnsxzv"; /* shell flags */
|
||||
char optval[NOPTS+1]; /* values of option flags */
|
||||
struct optent optlist[NOPTS] = {
|
||||
{ "errexit", 'e', 0 },
|
||||
{ "noglob", 'f', 0 },
|
||||
{ "ignoreeof", 'I', 0 },
|
||||
{ "interactive",'i', 0 },
|
||||
{ "monitor", 'm', 0 },
|
||||
{ "noexec", 'n', 0 },
|
||||
{ "stdin", 's', 0 },
|
||||
{ "xtrace", 'x', 0 },
|
||||
{ "verbose", 'v', 0 },
|
||||
{ "vi", 'V', 0 },
|
||||
{ "emacs", 'E', 0 },
|
||||
{ "noclobber", 'C', 0 },
|
||||
{ "allexport", 'a', 0 },
|
||||
{ "notify", 'b', 0 },
|
||||
{ "nounset", 'u', 0 },
|
||||
{ "privileged", 'p', 0 },
|
||||
{ "trapsasync", 'T', 0 },
|
||||
{ "physical", 'P', 0 },
|
||||
};
|
||||
#else
|
||||
extern const char optchar[NOPTS+1];
|
||||
extern char optval[NOPTS+1];
|
||||
extern struct optent optlist[NOPTS];
|
||||
#endif
|
||||
|
||||
|
||||
@@ -72,19 +101,20 @@ 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 *optarg; /* set by nextopt */
|
||||
extern char *shoptarg; /* set by nextopt */
|
||||
extern char *optptr; /* used by nextopt */
|
||||
extern int editable; /* isatty(0) && isatty(1) */
|
||||
extern int editable; /* isatty(0) && isatty(1) */
|
||||
|
||||
|
||||
#ifdef __STDC__
|
||||
void procargs(int, char **);
|
||||
void optschanged(void);
|
||||
void setparam(char **);
|
||||
void freeparam(struct shparam *);
|
||||
int shiftcmd(int, char **);
|
||||
int setcmd(int, char **);
|
||||
int getoptscmd(int, char **);
|
||||
int nextopt(char *);
|
||||
#else
|
||||
void procargs();
|
||||
void setparam();
|
||||
void freeparam();
|
||||
int nextopt();
|
||||
#endif
|
||||
void getoptsreset(const char *);
|
||||
|
||||
/*
|
||||
* $PchId: options.h,v 1.5 2006/05/29 13:08:45 philip Exp $
|
||||
*/
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*-
|
||||
* Copyright (c) 1991 The Regents of the University of California.
|
||||
* All rights reserved.
|
||||
* 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.
|
||||
@@ -13,10 +13,6 @@
|
||||
* 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.
|
||||
@@ -35,7 +31,7 @@
|
||||
*/
|
||||
|
||||
#ifndef lint
|
||||
static char sccsid[] = "@(#)output.c 5.1 (Berkeley) 3/7/91";
|
||||
static char sccsid[] = "@(#)output.c 8.1 (Berkeley) 5/31/93";
|
||||
#endif /* not lint */
|
||||
|
||||
/*
|
||||
@@ -55,12 +51,16 @@ static char sccsid[] = "@(#)output.c 5.1 (Berkeley) 3/7/91";
|
||||
#include "output.h"
|
||||
#include "memalloc.h"
|
||||
#include "error.h"
|
||||
#include "var.h"
|
||||
#ifdef __STDC__
|
||||
#include "stdarg.h"
|
||||
#else
|
||||
#include <varargs.h>
|
||||
#endif
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
|
||||
|
||||
#define OUTBUFSIZ BUFSIZ
|
||||
@@ -115,27 +115,63 @@ open_mem(block, length, file)
|
||||
|
||||
void
|
||||
out1str(p)
|
||||
char *p;
|
||||
const char *p;
|
||||
{
|
||||
outstr(p, out1);
|
||||
}
|
||||
|
||||
void
|
||||
out1qstr(const char *p)
|
||||
{
|
||||
outqstr(p, out1);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
out2str(p)
|
||||
char *p;
|
||||
{
|
||||
out2str(const char *p)
|
||||
{
|
||||
outstr(p, out2);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
outstr(p, file)
|
||||
register char *p;
|
||||
register const char *p;
|
||||
register struct output *file;
|
||||
{
|
||||
while (*p)
|
||||
outc(*p++, file);
|
||||
if (file == out2)
|
||||
flushout(file);
|
||||
}
|
||||
|
||||
/* Like outstr(), but quote for re-input into the shell. */
|
||||
void
|
||||
outqstr(const char *p, struct output *file)
|
||||
{
|
||||
char ch;
|
||||
|
||||
if (p[strcspn(p, "|&;<>()$`\\\"'")] == '\0' && (!ifsset() ||
|
||||
p[strcspn(p, ifsval())] == '\0')) {
|
||||
outstr(p, file);
|
||||
return;
|
||||
}
|
||||
|
||||
out1c('\'');
|
||||
while ((ch = *p++) != '\0') {
|
||||
switch (ch) {
|
||||
case '\'':
|
||||
/*
|
||||
* Can't quote single quotes inside single quotes;
|
||||
* close them, write escaped single quote, open again.
|
||||
*/
|
||||
outstr("'\\''", file);
|
||||
break;
|
||||
default:
|
||||
outc(ch, file);
|
||||
}
|
||||
}
|
||||
out1c('\'');
|
||||
}
|
||||
|
||||
|
||||
@@ -208,7 +244,8 @@ freestdout() {
|
||||
|
||||
#ifdef __STDC__
|
||||
void
|
||||
outfmt(struct output *file, char *fmt, ...) {
|
||||
outfmt(struct output *file, const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, fmt);
|
||||
@@ -218,7 +255,8 @@ outfmt(struct output *file, char *fmt, ...) {
|
||||
|
||||
|
||||
void
|
||||
out1fmt(char *fmt, ...) {
|
||||
out1fmt(const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, fmt);
|
||||
@@ -226,9 +264,20 @@ out1fmt(char *fmt, ...) {
|
||||
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, int length, char *fmt, ...) {
|
||||
fmtstr(char *outbuf, int length, const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
struct output strout;
|
||||
|
||||
@@ -275,6 +324,19 @@ out1fmt(va_alist)
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
void
|
||||
dprintf(va_alist)
|
||||
va_dcl
|
||||
{
|
||||
va_list ap;
|
||||
char *fmt;
|
||||
|
||||
va_start(ap);
|
||||
fmt = va_arg(ap, char *);
|
||||
doformat(out2, fmt, ap);
|
||||
va_end(ap);
|
||||
flushout(out2);
|
||||
}
|
||||
|
||||
void
|
||||
fmtstr(va_alist)
|
||||
@@ -325,11 +387,8 @@ static const char digit[17] = "0123456789ABCDEF";
|
||||
|
||||
|
||||
void
|
||||
doformat(dest, f, ap)
|
||||
register struct output *dest;
|
||||
register char *f; /* format string */
|
||||
va_list ap;
|
||||
{
|
||||
doformat(struct output *dest, const char *f, va_list ap)
|
||||
{
|
||||
register char c;
|
||||
char temp[TEMPSIZE];
|
||||
int flushleft;
|
||||
@@ -517,15 +576,6 @@ xwrite(fd, buf, nbytes)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Version of ioctl that retries after a signal is caught.
|
||||
* $PchId: output.c,v 1.6 2006/05/22 12:46:03 philip Exp $
|
||||
*/
|
||||
|
||||
int
|
||||
xioctl(fd, request, arg) {
|
||||
int i;
|
||||
|
||||
while ((i = ioctl(fd, request, arg)) == -1 && errno == EINTR);
|
||||
return i;
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*-
|
||||
* Copyright (c) 1991 The Regents of the University of California.
|
||||
* All rights reserved.
|
||||
* 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.
|
||||
@@ -13,10 +13,6 @@
|
||||
* 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.
|
||||
@@ -33,11 +29,14 @@
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)output.h 5.1 (Berkeley) 3/7/91
|
||||
* @(#)output.h 8.2 (Berkeley) 5/4/95
|
||||
* $FreeBSD: src/bin/sh/output.h,v 1.13 2004/04/06 20:06:51 markm Exp $
|
||||
*/
|
||||
|
||||
#ifndef OUTPUT_INCL
|
||||
|
||||
#include <stdarg.h>
|
||||
|
||||
struct output {
|
||||
char *nextc;
|
||||
int nleft;
|
||||
@@ -53,38 +52,27 @@ extern struct output memout;
|
||||
extern struct output *out1;
|
||||
extern struct output *out2;
|
||||
|
||||
#ifndef __printflike
|
||||
#define __printflike(a,b)
|
||||
#endif
|
||||
|
||||
#ifdef __STDC__
|
||||
void outstr(char *, struct output *);
|
||||
void out1str(char *);
|
||||
void out2str(char *);
|
||||
void outfmt(struct output *, char *, ...);
|
||||
void out1fmt(char *, ...);
|
||||
void fmtstr(char *, int, char *, ...);
|
||||
/* void doformat(struct output *, char *, va_list); */
|
||||
void doformat();
|
||||
void open_mem(char *, int, struct output *);
|
||||
void out1str(const char *);
|
||||
void out1qstr(const char *);
|
||||
void out2str(const char *);
|
||||
void out2qstr(const char *);
|
||||
void outstr(const char *, struct output *);
|
||||
void outqstr(const char *, struct output *);
|
||||
void emptyoutbuf(struct output *);
|
||||
void flushall(void);
|
||||
void flushout(struct output *);
|
||||
void freestdout(void);
|
||||
void outfmt(struct output *, const char *, ...) __printflike(2, 3);
|
||||
void out1fmt(const char *, ...) __printflike(1, 2);
|
||||
void dprintf(const char *, ...) __printflike(1, 2);
|
||||
void fmtstr(char *, int, const char *, ...) __printflike(3, 4);
|
||||
void doformat(struct output *, const char *, va_list) __printflike(2, 0);
|
||||
int xwrite(int, char *, int);
|
||||
int xioctl(int, int, int);
|
||||
#else
|
||||
void outstr();
|
||||
void out1str();
|
||||
void out2str();
|
||||
void outfmt();
|
||||
void out1fmt();
|
||||
void fmtstr();
|
||||
/* void doformat(); */
|
||||
void doformat();
|
||||
void emptyoutbuf();
|
||||
void flushall();
|
||||
void flushout();
|
||||
void freestdout();
|
||||
int xwrite();
|
||||
int xioctl();
|
||||
#endif
|
||||
|
||||
#define outc(c, file) (--(file)->nleft < 0? (emptyoutbuf(file), *(file)->nextc++ = (c)) : (*(file)->nextc++ = (c)))
|
||||
#define out1c(c) outc(c, out1);
|
||||
@@ -92,3 +80,7 @@ int xioctl();
|
||||
|
||||
#define OUTPUT_INCL
|
||||
#endif
|
||||
|
||||
/*
|
||||
* $PchId: output.h,v 1.5 2006/05/23 12:04:54 philip Exp $
|
||||
*/
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,6 +1,6 @@
|
||||
/*-
|
||||
* Copyright (c) 1991 The Regents of the University of California.
|
||||
* All rights reserved.
|
||||
* 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.
|
||||
@@ -13,10 +13,6 @@
|
||||
* 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.
|
||||
@@ -33,7 +29,8 @@
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)parser.h 5.1 (Berkeley) 3/7/91
|
||||
* @(#)parser.h 8.3 (Berkeley) 5/4/95
|
||||
* $FreeBSD: src/bin/sh/parser.h,v 1.10 2004/04/06 20:06:51 markm Exp $
|
||||
*/
|
||||
|
||||
/* control characters in argument strings */
|
||||
@@ -42,18 +39,27 @@
|
||||
#define CTLENDVAR '\203'
|
||||
#define CTLBACKQ '\204'
|
||||
#define CTLQUOTE 01 /* ored with CTLBACKQ code if in quotes */
|
||||
/* CTLBACKQ | CTLQUOTE == '\205' */
|
||||
#define CTLARI '\206'
|
||||
#define CTLENDARI '\207'
|
||||
#define CTLQUOTEMARK '\210'
|
||||
|
||||
/* variable substitution byte (follows CTLVAR) */
|
||||
#define VSTYPE 07 /* type of variable substitution */
|
||||
#define VSNUL 040 /* colon--treat the empty string as unset */
|
||||
#define VSQUOTE 0100 /* inside double quotes--suppress splitting */
|
||||
#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 1 /* normal variable: $var or ${var} */
|
||||
#define VSMINUS 2 /* ${var-text} */
|
||||
#define VSPLUS 3 /* ${var+text} */
|
||||
#define VSQUESTION 4 /* ${var?message} */
|
||||
#define VSASSIGN 5 /* ${var=text} */
|
||||
#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} */
|
||||
|
||||
|
||||
/*
|
||||
@@ -63,12 +69,14 @@
|
||||
*/
|
||||
extern int tokpushback;
|
||||
#define NEOF ((union node *)&tokpushback)
|
||||
extern int whichprompt; /* 1 == PS1, 2 == PS2 */
|
||||
|
||||
|
||||
#ifdef __STDC__
|
||||
union node *parsecmd(int);
|
||||
void fixredir(union node *, const char *, int);
|
||||
int goodname(char *);
|
||||
#else
|
||||
union node *parsecmd();
|
||||
int goodname();
|
||||
#endif
|
||||
char *getprompt(void *);
|
||||
|
||||
/*
|
||||
* $PchId: parser.h,v 1.3 2006/03/29 14:33:35 philip Exp $
|
||||
*/
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*-
|
||||
* Copyright (c) 1991 The Regents of the University of California.
|
||||
* All rights reserved.
|
||||
* 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.
|
||||
@@ -13,10 +13,6 @@
|
||||
* 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.
|
||||
@@ -35,8 +31,23 @@
|
||||
*/
|
||||
|
||||
#ifndef lint
|
||||
static char sccsid[] = "@(#)redir.c 5.1 (Berkeley) 3/7/91";
|
||||
#if 0
|
||||
static char sccsid[] = "@(#)redir.c 8.2 (Berkeley) 5/4/95";
|
||||
#endif
|
||||
#endif /* not lint */
|
||||
/*
|
||||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD: src/bin/sh/redir.c,v 1.26 2004/04/06 20:06:51 markm Exp $");
|
||||
*/
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#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.
|
||||
@@ -47,15 +58,10 @@ static char sccsid[] = "@(#)redir.c 5.1 (Berkeley) 3/7/91";
|
||||
#include "jobs.h"
|
||||
#include "expand.h"
|
||||
#include "redir.h"
|
||||
#include "eval.h"
|
||||
#include "output.h"
|
||||
#include "memalloc.h"
|
||||
#include "error.h"
|
||||
#include <sys/types.h>
|
||||
#include <signal.h>
|
||||
#include <fcntl.h>
|
||||
#include <errno.h>
|
||||
#include <limits.h>
|
||||
#include "options.h"
|
||||
|
||||
|
||||
#define EMPTY -2 /* marks an unused slot in redirtab */
|
||||
@@ -65,25 +71,21 @@ static char sccsid[] = "@(#)redir.c 5.1 (Berkeley) 3/7/91";
|
||||
MKINIT
|
||||
struct redirtab {
|
||||
struct redirtab *next;
|
||||
short renamed[10];
|
||||
int 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;
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
STATIC int fd0_redirected = 0;
|
||||
|
||||
#ifdef __STDC__
|
||||
STATIC void openredirect(union node *, char *);
|
||||
STATIC void openredirect(union node *, char[10 ]);
|
||||
STATIC int openhere(union node *);
|
||||
#else
|
||||
STATIC void openredirect();
|
||||
STATIC int openhere();
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
/*
|
||||
@@ -95,15 +97,14 @@ STATIC int openhere();
|
||||
*/
|
||||
|
||||
void
|
||||
redirect(redir, flags)
|
||||
union node *redir;
|
||||
int flags;
|
||||
{
|
||||
redirect(union node *redir, int flags)
|
||||
{
|
||||
union node *n;
|
||||
struct redirtab *sv;
|
||||
struct redirtab *sv = NULL;
|
||||
int i;
|
||||
int fd;
|
||||
char memory[10]; /* file descriptors to write to memory */
|
||||
int try;
|
||||
char memory[10]; /* file descriptors to write to memory */
|
||||
|
||||
for (i = 10 ; --i >= 0 ; )
|
||||
memory[i] = 0;
|
||||
@@ -117,21 +118,38 @@ redirect(redir, flags)
|
||||
}
|
||||
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;
|
||||
if ((i = copyfd(fd, 10)) != EMPTY) {
|
||||
again:
|
||||
if ((i = fcntl(fd, F_DUPFD, 10)) == -1) {
|
||||
switch (errno) {
|
||||
case EBADF:
|
||||
if (!try) {
|
||||
openredirect(n, memory);
|
||||
try++;
|
||||
goto again;
|
||||
}
|
||||
/* FALLTHROUGH*/
|
||||
default:
|
||||
INTON;
|
||||
error("%d: %s", fd, strerror(errno));
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!try) {
|
||||
sv->renamed[fd] = i;
|
||||
close(fd);
|
||||
}
|
||||
INTON;
|
||||
if (i == EMPTY)
|
||||
error("Out of file descriptors");
|
||||
} else {
|
||||
close(fd);
|
||||
}
|
||||
if (fd == 0)
|
||||
fd0_redirected++;
|
||||
openredirect(n, memory);
|
||||
if (!try)
|
||||
openredirect(n, memory);
|
||||
}
|
||||
if (memory[1])
|
||||
out1 = &memout;
|
||||
@@ -141,16 +159,15 @@ redirect(redir, flags)
|
||||
|
||||
|
||||
STATIC void
|
||||
openredirect(redir, memory)
|
||||
union node *redir;
|
||||
char memory[10];
|
||||
{
|
||||
openredirect(union node *redir, char memory[10])
|
||||
{
|
||||
struct stat sb;
|
||||
int fd = redir->nfile.fd;
|
||||
char *fname;
|
||||
int f;
|
||||
|
||||
/* Assume redirection succeeds. */
|
||||
exitstatus = 0;
|
||||
{ extern int exitstatus; exitstatus = 0; }
|
||||
|
||||
/*
|
||||
* We suppress interrupts so that we won't leave open file
|
||||
@@ -163,34 +180,35 @@ openredirect(redir, memory)
|
||||
case NFROM:
|
||||
fname = redir->nfile.expfname;
|
||||
if ((f = open(fname, O_RDONLY)) < 0)
|
||||
error("cannot open %s: %s", fname, errmsg(errno, E_OPEN));
|
||||
error("cannot open %s: %s", fname, strerror(errno));
|
||||
movefd:
|
||||
if (f != fd) {
|
||||
copyfd(f, fd);
|
||||
dup2(f, fd);
|
||||
close(f);
|
||||
}
|
||||
break;
|
||||
case NFROMTO:
|
||||
fname = redir->nfile.expfname;
|
||||
if ((f = open(fname, O_RDWR|O_CREAT, 0666)) < 0)
|
||||
error("cannot create %s: %s", fname, strerror(errno));
|
||||
goto movefd;
|
||||
case NTO:
|
||||
fname = redir->nfile.expfname;
|
||||
#ifdef O_CREAT
|
||||
if (Cflag && stat(fname, &sb) != -1 && S_ISREG(sb.st_mode))
|
||||
error("cannot create %s: %s", fname,
|
||||
strerror(EEXIST));
|
||||
if ((f = open(fname, O_WRONLY|O_CREAT|O_TRUNC, 0666)) < 0)
|
||||
error("cannot create %s: %s", fname, errmsg(errno, E_CREAT));
|
||||
#else
|
||||
if ((f = creat(fname, 0666)) < 0)
|
||||
error("cannot create %s: %s", fname, errmsg(errno, E_CREAT));
|
||||
#endif
|
||||
error("cannot create %s: %s", fname, strerror(errno));
|
||||
goto movefd;
|
||||
case NCLOBBER:
|
||||
fname = redir->nfile.expfname;
|
||||
if ((f = open(fname, O_WRONLY|O_CREAT|O_TRUNC, 0666)) < 0)
|
||||
error("cannot create %s: %s", fname, strerror(errno));
|
||||
goto movefd;
|
||||
case NAPPEND:
|
||||
fname = redir->nfile.expfname;
|
||||
#ifdef O_APPEND
|
||||
if ((f = open(fname, O_WRONLY|O_CREAT|O_APPEND, 0666)) < 0)
|
||||
error("cannot create %s: %s", fname, errmsg(errno, E_CREAT));
|
||||
#else
|
||||
if ((f = open(fname, O_WRONLY)) < 0
|
||||
&& (f = creat(fname, 0666)) < 0)
|
||||
error("cannot create %s: %s", fname, errmsg(errno, E_CREAT));
|
||||
lseek(f, 0L, 2);
|
||||
#endif
|
||||
error("cannot create %s: %s", fname, strerror(errno));
|
||||
goto movefd;
|
||||
case NTOFD:
|
||||
case NFROMFD:
|
||||
@@ -198,7 +216,9 @@ movefd:
|
||||
if (memory[redir->ndup.dupfd])
|
||||
memory[fd] = 1;
|
||||
else
|
||||
copyfd(redir->ndup.dupfd, fd);
|
||||
dup2(redir->ndup.dupfd, fd);
|
||||
} else {
|
||||
close(fd);
|
||||
}
|
||||
break;
|
||||
case NHERE:
|
||||
@@ -219,14 +239,13 @@ movefd:
|
||||
*/
|
||||
|
||||
STATIC int
|
||||
openhere(redir)
|
||||
union node *redir;
|
||||
{
|
||||
openhere(union node *redir)
|
||||
{
|
||||
int pip[2];
|
||||
int len;
|
||||
int len = 0;
|
||||
|
||||
if (pipe(pip) < 0)
|
||||
error("Pipe call failed");
|
||||
error("Pipe call failed: %s", strerror(errno));
|
||||
if (redir->type == NHERE) {
|
||||
len = strlen(redir->nhere.doc->narg.text);
|
||||
if (len <= PIPESIZE) {
|
||||
@@ -239,9 +258,7 @@ openhere(redir)
|
||||
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);
|
||||
@@ -261,18 +278,20 @@ out:
|
||||
*/
|
||||
|
||||
void
|
||||
popredir() {
|
||||
register struct redirtab *rp = redirlist;
|
||||
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 (i == 0)
|
||||
fd0_redirected--;
|
||||
if (rp->renamed[i] >= 0) {
|
||||
copyfd(rp->renamed[i], i);
|
||||
dup2(rp->renamed[i], i);
|
||||
close(rp->renamed[i]);
|
||||
} else {
|
||||
close(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -282,8 +301,6 @@ popredir() {
|
||||
INTON;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Undo all redirections. Called on error or interrupt.
|
||||
*/
|
||||
@@ -303,14 +320,21 @@ SHELLPROC {
|
||||
|
||||
#endif
|
||||
|
||||
/* Return true if fd 0 has already been redirected at least once. */
|
||||
int
|
||||
fd0_redirected_p(void)
|
||||
{
|
||||
return fd0_redirected != 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Discard all saved file descriptors.
|
||||
*/
|
||||
|
||||
void
|
||||
clearredir() {
|
||||
register struct redirtab *rp;
|
||||
clearredir(void)
|
||||
{
|
||||
struct redirtab *rp;
|
||||
int i;
|
||||
|
||||
for (rp = redirlist ; rp ; rp = rp->next) {
|
||||
@@ -323,48 +347,6 @@ clearredir() {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Copy a file descriptor, like the F_DUPFD option of fcntl. Returns -1
|
||||
* if the source file descriptor is closed, EMPTY if there are no unused
|
||||
* file descriptors left.
|
||||
* $PchId: redir.c,v 1.5 2006/05/22 12:27:37 philip Exp $
|
||||
*/
|
||||
|
||||
int
|
||||
copyfd(from, to) {
|
||||
#ifdef F_DUPFD
|
||||
int newfd;
|
||||
|
||||
newfd = fcntl(from, F_DUPFD, to);
|
||||
if (newfd < 0 && errno == EMFILE)
|
||||
return EMPTY;
|
||||
return newfd;
|
||||
#else
|
||||
char toclose[32];
|
||||
int i;
|
||||
int newfd;
|
||||
int e;
|
||||
|
||||
for (i = 0 ; i < to ; i++)
|
||||
toclose[i] = 0;
|
||||
INTOFF;
|
||||
while ((newfd = dup(from)) >= 0 && newfd < to)
|
||||
toclose[newfd] = 1;
|
||||
e = errno;
|
||||
for (i = 0 ; i < to ; i++) {
|
||||
if (toclose[i])
|
||||
close(i);
|
||||
}
|
||||
INTON;
|
||||
if (newfd < 0 && e == EMFILE)
|
||||
return EMPTY;
|
||||
return newfd;
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Return true if fd 0 has already been redirected at least once. */
|
||||
int
|
||||
fd0_redirected_p () {
|
||||
return fd0_redirected != 0;
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*-
|
||||
* Copyright (c) 1991 The Regents of the University of California.
|
||||
* All rights reserved.
|
||||
* 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.
|
||||
@@ -13,10 +13,6 @@
|
||||
* 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.
|
||||
@@ -33,24 +29,21 @@
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)redir.h 5.1 (Berkeley) 3/7/91
|
||||
* @(#)redir.h 8.2 (Berkeley) 5/4/95
|
||||
* $FreeBSD: src/bin/sh/redir.h,v 1.10 2004/04/06 20:06:51 markm Exp $
|
||||
*/
|
||||
|
||||
/* flags passed to redirect */
|
||||
#define REDIR_PUSH 01 /* save previous values of file descriptors */
|
||||
#define REDIR_BACKQ 02 /* save the command output in memory */
|
||||
|
||||
#ifdef __STDC__
|
||||
union node;
|
||||
void redirect(union node *, int);
|
||||
void popredir(void);
|
||||
void clearredir(void);
|
||||
int copyfd(int, int);
|
||||
int fd0_redirected_p(void);
|
||||
#else
|
||||
void redirect();
|
||||
void popredir();
|
||||
void clearredir();
|
||||
int copyfd();
|
||||
int fd0_redirected_p();
|
||||
#endif
|
||||
void clearredir(void);
|
||||
|
||||
|
||||
/*
|
||||
* $PchId: redir.h,v 1.3 2006/03/29 14:13:34 philip Exp $
|
||||
*/
|
||||
|
||||
463
commands/ash/setmode.c
Normal file
463
commands/ash/setmode.c
Normal file
@@ -0,0 +1,463 @@
|
||||
/*
|
||||
* Copyright (c) 1989, 1993, 1994
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to Berkeley by
|
||||
* Dave Borman at Cray Research, Inc.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#if defined(LIBC_SCCS) && !defined(lint)
|
||||
static char sccsid[] = "@(#)setmode.c 8.2 (Berkeley) 3/25/94";
|
||||
#endif /* LIBC_SCCS and not lint */
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include <ctype.h>
|
||||
#include <errno.h>
|
||||
#include <signal.h>
|
||||
#include <stddef.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#ifdef SETMODE_DEBUG
|
||||
#include <stdio.h>
|
||||
#endif
|
||||
|
||||
#include "shell.h"
|
||||
|
||||
#ifndef S_ISTXT
|
||||
#define S_ISTXT S_ISVTX
|
||||
#endif
|
||||
|
||||
#define SET_LEN 6 /* initial # of bitcmd struct to malloc */
|
||||
#define SET_LEN_INCR 4 /* # of bitcmd structs to add as needed */
|
||||
|
||||
typedef struct bitcmd {
|
||||
char cmd;
|
||||
char cmd2;
|
||||
mode_t bits;
|
||||
} BITCMD;
|
||||
|
||||
#define CMD2_CLR 0x01
|
||||
#define CMD2_SET 0x02
|
||||
#define CMD2_GBITS 0x04
|
||||
#define CMD2_OBITS 0x08
|
||||
#define CMD2_UBITS 0x10
|
||||
|
||||
static BITCMD *addcmd (BITCMD *, int, int, int, unsigned int);
|
||||
static int compress_mode (BITCMD *);
|
||||
#ifdef SETMODE_DEBUG
|
||||
static void dumpmode __P((BITCMD *));
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Given the old mode and an array of bitcmd structures, apply the operations
|
||||
* described in the bitcmd structures to the old mode, and return the new mode.
|
||||
* Note that there is no '=' command; a strict assignment is just a '-' (clear
|
||||
* bits) followed by a '+' (set bits).
|
||||
*/
|
||||
mode_t
|
||||
getmode(bbox, omode)
|
||||
void *bbox;
|
||||
mode_t omode;
|
||||
{
|
||||
register BITCMD *set;
|
||||
register mode_t clrval, newmode, value;
|
||||
|
||||
set = (BITCMD *)bbox;
|
||||
newmode = omode;
|
||||
for (value = 0;; set++)
|
||||
switch(set->cmd) {
|
||||
/*
|
||||
* When copying the user, group or other bits around, we "know"
|
||||
* where the bits are in the mode so that we can do shifts to
|
||||
* copy them around. If we don't use shifts, it gets real
|
||||
* grundgy with lots of single bit checks and bit sets.
|
||||
*/
|
||||
case 'u':
|
||||
value = (newmode & S_IRWXU) >> 6;
|
||||
goto common;
|
||||
|
||||
case 'g':
|
||||
value = (newmode & S_IRWXG) >> 3;
|
||||
goto common;
|
||||
|
||||
case 'o':
|
||||
value = newmode & S_IRWXO;
|
||||
common: if (set->cmd2 & CMD2_CLR) {
|
||||
clrval =
|
||||
(set->cmd2 & CMD2_SET) ? S_IRWXO : value;
|
||||
if (set->cmd2 & CMD2_UBITS)
|
||||
newmode &= ~((clrval<<6) & set->bits);
|
||||
if (set->cmd2 & CMD2_GBITS)
|
||||
newmode &= ~((clrval<<3) & set->bits);
|
||||
if (set->cmd2 & CMD2_OBITS)
|
||||
newmode &= ~(clrval & set->bits);
|
||||
}
|
||||
if (set->cmd2 & CMD2_SET) {
|
||||
if (set->cmd2 & CMD2_UBITS)
|
||||
newmode |= (value<<6) & set->bits;
|
||||
if (set->cmd2 & CMD2_GBITS)
|
||||
newmode |= (value<<3) & set->bits;
|
||||
if (set->cmd2 & CMD2_OBITS)
|
||||
newmode |= value & set->bits;
|
||||
}
|
||||
break;
|
||||
|
||||
case '+':
|
||||
newmode |= set->bits;
|
||||
break;
|
||||
|
||||
case '-':
|
||||
newmode &= ~set->bits;
|
||||
break;
|
||||
|
||||
case 'X':
|
||||
if (omode & (S_IFDIR|S_IXUSR|S_IXGRP|S_IXOTH))
|
||||
newmode |= set->bits;
|
||||
break;
|
||||
|
||||
case '\0':
|
||||
default:
|
||||
#ifdef SETMODE_DEBUG
|
||||
(void)printf("getmode:%04o -> %04o\n", omode, newmode);
|
||||
#endif
|
||||
return (newmode);
|
||||
}
|
||||
}
|
||||
|
||||
#define ADDCMD(a, b, c, d) \
|
||||
if (set >= endset) { \
|
||||
register BITCMD *newset; \
|
||||
setlen += SET_LEN_INCR; \
|
||||
newset = realloc(saveset, sizeof(BITCMD) * setlen); \
|
||||
if (!saveset) \
|
||||
return (NULL); \
|
||||
set = newset + (set - saveset); \
|
||||
saveset = newset; \
|
||||
endset = newset + (setlen - 2); \
|
||||
} \
|
||||
set = addcmd(set, (a), (b), (c), (d))
|
||||
|
||||
#define STANDARD_BITS (S_ISUID|S_ISGID|S_IRWXU|S_IRWXG|S_IRWXO)
|
||||
|
||||
void *
|
||||
setmode(p)
|
||||
register char *p;
|
||||
{
|
||||
register int perm, who;
|
||||
register char op;
|
||||
BITCMD *set, *saveset, *endset;
|
||||
sigset_t sigset, sigoset;
|
||||
mode_t mask;
|
||||
int equalopdone, permXbits, setlen;
|
||||
|
||||
if (!*p)
|
||||
return (NULL);
|
||||
|
||||
/*
|
||||
* Get a copy of the mask for the permissions that are mask relative.
|
||||
* Flip the bits, we want what's not set. Since it's possible that
|
||||
* the caller is opening files inside a signal handler, protect them
|
||||
* as best we can.
|
||||
*/
|
||||
sigfillset(&sigset);
|
||||
(void)sigprocmask(SIG_BLOCK, &sigset, &sigoset);
|
||||
(void)umask(mask = umask(0));
|
||||
mask = ~mask;
|
||||
(void)sigprocmask(SIG_SETMASK, &sigoset, NULL);
|
||||
|
||||
setlen = SET_LEN + 2;
|
||||
|
||||
if ((set = malloc((unsigned int)(sizeof(BITCMD) * setlen))) == NULL)
|
||||
return (NULL);
|
||||
saveset = set;
|
||||
endset = set + (setlen - 2);
|
||||
|
||||
/*
|
||||
* If an absolute number, get it and return; disallow non-octal digits
|
||||
* or illegal bits.
|
||||
*/
|
||||
if (isdigit(*p)) {
|
||||
perm = (mode_t)strtol(p, NULL, 8);
|
||||
if (perm & ~(STANDARD_BITS|S_ISTXT)) {
|
||||
free(saveset);
|
||||
return (NULL);
|
||||
}
|
||||
while (*++p)
|
||||
if (*p < '0' || *p > '7') {
|
||||
free(saveset);
|
||||
return (NULL);
|
||||
}
|
||||
ADDCMD('=', (STANDARD_BITS|S_ISTXT), perm, mask);
|
||||
return (saveset);
|
||||
}
|
||||
|
||||
/*
|
||||
* Build list of structures to set/clear/copy bits as described by
|
||||
* each clause of the symbolic mode.
|
||||
*/
|
||||
for (;;) {
|
||||
/* First, find out which bits might be modified. */
|
||||
for (who = 0;; ++p) {
|
||||
switch (*p) {
|
||||
case 'a':
|
||||
who |= STANDARD_BITS;
|
||||
break;
|
||||
case 'u':
|
||||
who |= S_ISUID|S_IRWXU;
|
||||
break;
|
||||
case 'g':
|
||||
who |= S_ISGID|S_IRWXG;
|
||||
break;
|
||||
case 'o':
|
||||
who |= S_IRWXO;
|
||||
break;
|
||||
default:
|
||||
goto getop;
|
||||
}
|
||||
}
|
||||
|
||||
getop: if ((op = *p++) != '+' && op != '-' && op != '=') {
|
||||
free(saveset);
|
||||
return (NULL);
|
||||
}
|
||||
if (op == '=')
|
||||
equalopdone = 0;
|
||||
|
||||
who &= ~S_ISTXT;
|
||||
for (perm = 0, permXbits = 0;; ++p) {
|
||||
switch (*p) {
|
||||
case 'r':
|
||||
perm |= S_IRUSR|S_IRGRP|S_IROTH;
|
||||
break;
|
||||
case 's':
|
||||
/* If only "other" bits ignore set-id. */
|
||||
if (who & ~S_IRWXO)
|
||||
perm |= S_ISUID|S_ISGID;
|
||||
break;
|
||||
case 't':
|
||||
/* If only "other" bits ignore sticky. */
|
||||
if (who & ~S_IRWXO) {
|
||||
who |= S_ISTXT;
|
||||
perm |= S_ISTXT;
|
||||
}
|
||||
break;
|
||||
case 'w':
|
||||
perm |= S_IWUSR|S_IWGRP|S_IWOTH;
|
||||
break;
|
||||
case 'X':
|
||||
permXbits = S_IXUSR|S_IXGRP|S_IXOTH;
|
||||
break;
|
||||
case 'x':
|
||||
perm |= S_IXUSR|S_IXGRP|S_IXOTH;
|
||||
break;
|
||||
case 'u':
|
||||
case 'g':
|
||||
case 'o':
|
||||
/*
|
||||
* When ever we hit 'u', 'g', or 'o', we have
|
||||
* to flush out any partial mode that we have,
|
||||
* and then do the copying of the mode bits.
|
||||
*/
|
||||
if (perm) {
|
||||
ADDCMD(op, who, perm, mask);
|
||||
perm = 0;
|
||||
}
|
||||
if (op == '=')
|
||||
equalopdone = 1;
|
||||
if (op == '+' && permXbits) {
|
||||
ADDCMD('X', who, permXbits, mask);
|
||||
permXbits = 0;
|
||||
}
|
||||
ADDCMD(*p, who, op, mask);
|
||||
break;
|
||||
|
||||
default:
|
||||
/*
|
||||
* Add any permissions that we haven't already
|
||||
* done.
|
||||
*/
|
||||
if (perm || (op == '=' && !equalopdone)) {
|
||||
if (op == '=')
|
||||
equalopdone = 1;
|
||||
ADDCMD(op, who, perm, mask);
|
||||
perm = 0;
|
||||
}
|
||||
if (permXbits) {
|
||||
ADDCMD('X', who, permXbits, mask);
|
||||
permXbits = 0;
|
||||
}
|
||||
goto apply;
|
||||
}
|
||||
}
|
||||
|
||||
apply: if (!*p)
|
||||
break;
|
||||
if (*p != ',')
|
||||
goto getop;
|
||||
++p;
|
||||
}
|
||||
set->cmd = 0;
|
||||
#ifdef SETMODE_DEBUG
|
||||
(void)printf("Before compress_mode()\n");
|
||||
dumpmode(saveset);
|
||||
#endif
|
||||
compress_mode(saveset);
|
||||
#ifdef SETMODE_DEBUG
|
||||
(void)printf("After compress_mode()\n");
|
||||
dumpmode(saveset);
|
||||
#endif
|
||||
return (saveset);
|
||||
}
|
||||
|
||||
static BITCMD *
|
||||
addcmd(set, op, who, oparg, mask)
|
||||
BITCMD *set;
|
||||
register int oparg, who;
|
||||
register int op;
|
||||
unsigned int mask;
|
||||
{
|
||||
switch (op) {
|
||||
case '=':
|
||||
set->cmd = '-';
|
||||
set->bits = who ? who : STANDARD_BITS;
|
||||
set++;
|
||||
|
||||
op = '+';
|
||||
/* FALLTHROUGH */
|
||||
case '+':
|
||||
case '-':
|
||||
case 'X':
|
||||
set->cmd = op;
|
||||
set->bits = (who ? who : mask) & oparg;
|
||||
break;
|
||||
|
||||
case 'u':
|
||||
case 'g':
|
||||
case 'o':
|
||||
set->cmd = op;
|
||||
if (who) {
|
||||
set->cmd2 = ((who & S_IRUSR) ? CMD2_UBITS : 0) |
|
||||
((who & S_IRGRP) ? CMD2_GBITS : 0) |
|
||||
((who & S_IROTH) ? CMD2_OBITS : 0);
|
||||
set->bits = ~0;
|
||||
} else {
|
||||
set->cmd2 = CMD2_UBITS | CMD2_GBITS | CMD2_OBITS;
|
||||
set->bits = mask;
|
||||
}
|
||||
|
||||
if (oparg == '+')
|
||||
set->cmd2 |= CMD2_SET;
|
||||
else if (oparg == '-')
|
||||
set->cmd2 |= CMD2_CLR;
|
||||
else if (oparg == '=')
|
||||
set->cmd2 |= CMD2_SET|CMD2_CLR;
|
||||
break;
|
||||
}
|
||||
return (set + 1);
|
||||
}
|
||||
|
||||
#ifdef SETMODE_DEBUG
|
||||
static void
|
||||
dumpmode(set)
|
||||
register BITCMD *set;
|
||||
{
|
||||
for (; set->cmd; ++set)
|
||||
(void)printf("cmd: '%c' bits %04o%s%s%s%s%s%s\n",
|
||||
set->cmd, set->bits, set->cmd2 ? " cmd2:" : "",
|
||||
set->cmd2 & CMD2_CLR ? " CLR" : "",
|
||||
set->cmd2 & CMD2_SET ? " SET" : "",
|
||||
set->cmd2 & CMD2_UBITS ? " UBITS" : "",
|
||||
set->cmd2 & CMD2_GBITS ? " GBITS" : "",
|
||||
set->cmd2 & CMD2_OBITS ? " OBITS" : "");
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Given an array of bitcmd structures, compress by compacting consecutive
|
||||
* '+', '-' and 'X' commands into at most 3 commands, one of each. The 'u',
|
||||
* 'g' and 'o' commands continue to be separate. They could probably be
|
||||
* compacted, but it's not worth the effort.
|
||||
*/
|
||||
static int
|
||||
compress_mode(set)
|
||||
register BITCMD *set;
|
||||
{
|
||||
register BITCMD *nset;
|
||||
register int setbits, clrbits, Xbits, op;
|
||||
|
||||
for (nset = set;;) {
|
||||
/* Copy over any 'u', 'g' and 'o' commands. */
|
||||
while ((op = nset->cmd) != '+' && op != '-' && op != 'X') {
|
||||
*set++ = *nset++;
|
||||
if (!op)
|
||||
return;
|
||||
}
|
||||
|
||||
for (setbits = clrbits = Xbits = 0;; nset++) {
|
||||
if ((op = nset->cmd) == '-') {
|
||||
clrbits |= nset->bits;
|
||||
setbits &= ~nset->bits;
|
||||
Xbits &= ~nset->bits;
|
||||
} else if (op == '+') {
|
||||
setbits |= nset->bits;
|
||||
clrbits &= ~nset->bits;
|
||||
Xbits &= ~nset->bits;
|
||||
} else if (op == 'X')
|
||||
Xbits |= nset->bits & ~setbits;
|
||||
else
|
||||
break;
|
||||
}
|
||||
if (clrbits) {
|
||||
set->cmd = '-';
|
||||
set->cmd2 = 0;
|
||||
set->bits = clrbits;
|
||||
set++;
|
||||
}
|
||||
if (setbits) {
|
||||
set->cmd = '+';
|
||||
set->cmd2 = 0;
|
||||
set->bits = setbits;
|
||||
set++;
|
||||
}
|
||||
if (Xbits) {
|
||||
set->cmd = 'X';
|
||||
set->cmd2 = 0;
|
||||
set->bits = Xbits;
|
||||
set++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* $PchId: setmode.c,v 1.3 2006/05/23 11:57:34 philip Exp $
|
||||
*/
|
||||
@@ -1,6 +1,6 @@
|
||||
/*-
|
||||
* Copyright (c) 1991 The Regents of the University of California.
|
||||
* All rights reserved.
|
||||
* 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.
|
||||
@@ -13,10 +13,6 @@
|
||||
* 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.
|
||||
@@ -33,19 +29,17 @@
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)shell.h 5.4 (Berkeley) 4/12/91
|
||||
* @(#)shell.h 8.2 (Berkeley) 5/4/95
|
||||
* $FreeBSD: src/bin/sh/shell.h,v 1.17 2004/04/06 20:06:51 markm Exp $
|
||||
*/
|
||||
|
||||
#include <sys/types.h> /* for mode_t */
|
||||
|
||||
/*
|
||||
* The follow should be set to reflect the type of system you have:
|
||||
* JOBS -> 1 if you have Berkeley job control, 0 otherwise.
|
||||
* SYMLINKS -> 1 if your system includes symbolic links, 0 otherwise.
|
||||
* DIRENT -> 1 if your system has the SVR3 directory(3X) routines.
|
||||
* UDIR -> 1 if you want the shell to simulate the /u directory.
|
||||
* TILDE -> 1 if you want the shell to expand ~logname.
|
||||
* USEGETPW -> 1 if getpwnam() must be used to look up a name.
|
||||
* ATTY -> 1 to include code for atty(1).
|
||||
* SHORTNAMES -> 1 if your linker cannot handle long names.
|
||||
* READLINE -> 1 if line editing by readline() should be enabled.
|
||||
* define BSD if you are running 4.2 BSD or later.
|
||||
* define SYSV if you are running under System V.
|
||||
@@ -56,52 +50,47 @@
|
||||
* a quit signal will generate a core dump.
|
||||
*/
|
||||
|
||||
#ifndef JOBS
|
||||
#define JOBS 1
|
||||
#endif
|
||||
#ifndef BSD
|
||||
#define BSD 1
|
||||
#endif
|
||||
#ifndef DEBUG
|
||||
#define DEBUG 0
|
||||
#endif
|
||||
#define POSIX 1
|
||||
|
||||
#define JOBS 0
|
||||
|
||||
/* Set SYMLINKS to 0 by request of Giovanni Falzoni, who wrote the
|
||||
* symlink patches for Minix; email to minix-devel-l of thu 3 nov.
|
||||
/*
|
||||
* Type of used arithmetics. SUSv3 requires us to have at least signed long.
|
||||
*/
|
||||
typedef long arith_t;
|
||||
#define ARITH_FORMAT_STR "%ld"
|
||||
#define atoarith_t(arg) strtol(arg, NULL, 0)
|
||||
#define strtoarith_t(nptr, endptr, base) strtol(nptr, endptr, base)
|
||||
|
||||
#if 0
|
||||
#define SYMLINKS defined(S_ISLNK)
|
||||
#else
|
||||
#define SYMLINKS 0
|
||||
#endif
|
||||
|
||||
#define DIRENT 1
|
||||
#define UDIR 0
|
||||
#define TILDE 1
|
||||
#define USEGETPW 0
|
||||
#define ATTY 0
|
||||
#define READLINE 1
|
||||
#define HASHBANG 0
|
||||
/* #define BSD */
|
||||
#define POSIX 1
|
||||
#define DEBUG 0
|
||||
|
||||
#ifdef __STDC__
|
||||
typedef void *pointer;
|
||||
#ifndef NULL
|
||||
#define NULL (void *)0
|
||||
#endif
|
||||
#else /* not __STDC__ */
|
||||
typedef char *pointer;
|
||||
#ifndef NULL
|
||||
#define NULL 0
|
||||
#endif
|
||||
#endif /* not __STDC__ */
|
||||
#define STATIC /* empty */
|
||||
#define MKINIT /* empty */
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
#include <sys/types.h>
|
||||
#define STATIC static
|
||||
#define MKINIT /* empty */
|
||||
|
||||
extern char nullstr[1]; /* null string */
|
||||
|
||||
|
||||
#if DEBUG
|
||||
#define TRACE(param) trace param
|
||||
#define TRACE(param) sh_trace param
|
||||
#else
|
||||
#define TRACE(param)
|
||||
#endif
|
||||
|
||||
#ifdef __minix
|
||||
#define __unused
|
||||
|
||||
typedef long quad_t; /* XXX */
|
||||
typedef unsigned long u_quad_t; /* XXX */
|
||||
#endif
|
||||
|
||||
mode_t getmode(void *, int /* mode_t */);
|
||||
void *setmode(char *);
|
||||
|
||||
/*
|
||||
* $PchId: shell.h,v 1.7 2006/05/22 12:47:00 philip Exp $
|
||||
*/
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*-
|
||||
* Copyright (c) 1991 The Regents of the University of California.
|
||||
* All rights reserved.
|
||||
* 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.
|
||||
@@ -13,10 +13,6 @@
|
||||
* 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.
|
||||
@@ -35,38 +31,54 @@
|
||||
*/
|
||||
|
||||
#ifndef lint
|
||||
static char sccsid[] = "@(#)show.c 5.2 (Berkeley) 4/12/91";
|
||||
#if 0
|
||||
static char sccsid[] = "@(#)show.c 8.3 (Berkeley) 5/4/95";
|
||||
#endif
|
||||
#endif /* not lint */
|
||||
/*
|
||||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD: src/bin/sh/show.c,v 1.21 2004/04/06 20:06:51 markm Exp $");
|
||||
*/
|
||||
|
||||
#include <fcntl.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdarg.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include "shell.h"
|
||||
#include "parser.h"
|
||||
#include "nodes.h"
|
||||
#include "mystring.h"
|
||||
|
||||
#include "show.h"
|
||||
|
||||
#if DEBUG
|
||||
static shtree(), shcmd(), sharg(), indent();
|
||||
static void trputc(int c);
|
||||
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 *);
|
||||
static void showtree(union node *n);
|
||||
|
||||
|
||||
showtree(n)
|
||||
union node *n;
|
||||
{
|
||||
static void
|
||||
showtree(union node *n)
|
||||
{
|
||||
trputs("showtree called\n");
|
||||
shtree(n, 1, NULL, stdout);
|
||||
}
|
||||
|
||||
|
||||
static
|
||||
shtree(n, ind, pfx, fp)
|
||||
union node *n;
|
||||
char *pfx;
|
||||
FILE *fp;
|
||||
{
|
||||
static void
|
||||
shtree(union node *n, int ind, char *pfx, FILE *fp)
|
||||
{
|
||||
struct nodelist *lp;
|
||||
char *s;
|
||||
|
||||
if (n == NULL)
|
||||
return;
|
||||
|
||||
indent(ind, pfx, fp);
|
||||
switch(n->type) {
|
||||
case NSEMI:
|
||||
@@ -109,11 +121,9 @@ binop:
|
||||
|
||||
|
||||
|
||||
static
|
||||
shcmd(cmd, fp)
|
||||
union node *cmd;
|
||||
FILE *fp;
|
||||
{
|
||||
static void
|
||||
shcmd(union node *cmd, FILE *fp)
|
||||
{
|
||||
union node *np;
|
||||
int first;
|
||||
char *s;
|
||||
@@ -133,14 +143,20 @@ shcmd(cmd, fp)
|
||||
case NTO: s = ">"; dftfd = 1; break;
|
||||
case NAPPEND: s = ">>"; dftfd = 1; break;
|
||||
case NTOFD: s = ">&"; dftfd = 1; break;
|
||||
case NCLOBBER: s = ">|"; dftfd = 1; break;
|
||||
case NFROM: s = "<"; dftfd = 0; break;
|
||||
case NFROMTO: s = "<>"; dftfd = 0; break;
|
||||
case NFROMFD: 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);
|
||||
if (np->ndup.dupfd >= 0)
|
||||
fprintf(fp, "%d", np->ndup.dupfd);
|
||||
else
|
||||
fprintf(fp, "-");
|
||||
} else {
|
||||
sharg(np->nfile.fname, fp);
|
||||
}
|
||||
@@ -150,11 +166,9 @@ shcmd(cmd, fp)
|
||||
|
||||
|
||||
|
||||
static
|
||||
sharg(arg, fp)
|
||||
union node *arg;
|
||||
FILE *fp;
|
||||
{
|
||||
static void
|
||||
sharg(union node *arg, FILE *fp)
|
||||
{
|
||||
char *p;
|
||||
struct nodelist *bqlist;
|
||||
int subtype;
|
||||
@@ -174,10 +188,15 @@ sharg(arg, fp)
|
||||
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);
|
||||
@@ -194,6 +213,22 @@ sharg(arg, fp)
|
||||
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);
|
||||
}
|
||||
@@ -216,11 +251,9 @@ sharg(arg, fp)
|
||||
}
|
||||
|
||||
|
||||
static
|
||||
indent(amount, pfx, fp)
|
||||
char *pfx;
|
||||
FILE *fp;
|
||||
{
|
||||
static void
|
||||
indent(int amount, char *pfx, FILE *fp)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0 ; i < amount ; i++) {
|
||||
@@ -229,8 +262,6 @@ indent(amount, pfx, fp)
|
||||
putc('\t', fp);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
/*
|
||||
@@ -247,52 +278,48 @@ int debug = 0;
|
||||
#endif
|
||||
|
||||
|
||||
trputc(c) {
|
||||
#if DEBUG
|
||||
static void
|
||||
trputc(int c)
|
||||
{
|
||||
if (tracefile == NULL)
|
||||
return;
|
||||
putc(c, tracefile);
|
||||
if (c == '\n')
|
||||
fflush(tracefile);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
trace(fmt, a1, a2, a3, a4, a5, a6, a7, a8)
|
||||
char *fmt;
|
||||
{
|
||||
#if DEBUG
|
||||
int e = errno;
|
||||
if (tracefile == NULL)
|
||||
return;
|
||||
fprintf(tracefile, fmt, a1, a2, a3, a4, a5, a6, a7, a8);
|
||||
if (strchr(fmt, '\n'))
|
||||
fflush(tracefile);
|
||||
errno = e;
|
||||
#endif
|
||||
void
|
||||
sh_trace(const char *fmt, ...)
|
||||
{
|
||||
va_list va;
|
||||
va_start(va, fmt);
|
||||
if (tracefile != NULL) {
|
||||
(void) vfprintf(tracefile, fmt, va);
|
||||
if (strchr(fmt, '\n'))
|
||||
(void) fflush(tracefile);
|
||||
}
|
||||
va_end(va);
|
||||
}
|
||||
|
||||
|
||||
trputs(s)
|
||||
char *s;
|
||||
{
|
||||
#if DEBUG
|
||||
void
|
||||
trputs(char *s)
|
||||
{
|
||||
if (tracefile == NULL)
|
||||
return;
|
||||
fputs(s, tracefile);
|
||||
if (strchr(s, '\n'))
|
||||
fflush(tracefile);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
trstring(s)
|
||||
char *s;
|
||||
{
|
||||
register char *p;
|
||||
static void
|
||||
trstring(char *s)
|
||||
{
|
||||
char *p;
|
||||
char c;
|
||||
|
||||
#if DEBUG
|
||||
if (tracefile == NULL)
|
||||
return;
|
||||
putc('"', tracefile);
|
||||
@@ -324,14 +351,12 @@ backslash: putc('\\', tracefile);
|
||||
}
|
||||
}
|
||||
putc('"', tracefile);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
trargs(ap)
|
||||
char **ap;
|
||||
{
|
||||
#if DEBUG
|
||||
void
|
||||
trargs(char **ap)
|
||||
{
|
||||
if (tracefile == NULL)
|
||||
return;
|
||||
while (*ap) {
|
||||
@@ -342,36 +367,43 @@ trargs(ap)
|
||||
putc('\n', tracefile);
|
||||
}
|
||||
fflush(tracefile);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
opentrace() {
|
||||
void
|
||||
opentrace(void)
|
||||
{
|
||||
char s[100];
|
||||
char *p;
|
||||
char *getenv();
|
||||
int flags;
|
||||
|
||||
#if DEBUG
|
||||
if (!debug)
|
||||
return;
|
||||
if ((p = getenv("HOME")) == NULL) {
|
||||
if (getuid() == 0)
|
||||
p = "/";
|
||||
else
|
||||
p = "/tmp";
|
||||
#ifdef not_this_way
|
||||
{
|
||||
char *p;
|
||||
if ((p = getenv("HOME")) == NULL) {
|
||||
if (geteuid() == 0)
|
||||
p = "/";
|
||||
else
|
||||
p = "/tmp";
|
||||
}
|
||||
scopy(p, s);
|
||||
strcat(s, "/trace");
|
||||
}
|
||||
scopy(p, s);
|
||||
strcat(s, "/trace");
|
||||
#else
|
||||
scopy("./trace", s);
|
||||
#endif /* not_this_way */
|
||||
if ((tracefile = fopen(s, "a")) == NULL) {
|
||||
fprintf(stderr, "Can't open %s\n", s);
|
||||
fprintf(stderr, "Can't open %s: %s\n", s, strerror(errno));
|
||||
return;
|
||||
}
|
||||
#ifdef O_APPEND
|
||||
if ((flags = fcntl(fileno(tracefile), F_GETFL, 0)) >= 0)
|
||||
fcntl(fileno(tracefile), F_SETFL, flags | O_APPEND);
|
||||
#endif
|
||||
fputs("\nTracing started.\n", tracefile);
|
||||
fflush(tracefile);
|
||||
#endif
|
||||
}
|
||||
#endif /* DEBUG */
|
||||
|
||||
/*
|
||||
* $PchId: show.c,v 1.6 2006/05/22 12:27:51 philip Exp $
|
||||
*/
|
||||
|
||||
42
commands/ash/show.h
Normal file
42
commands/ash/show.h
Normal file
@@ -0,0 +1,42 @@
|
||||
/*-
|
||||
* 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.
|
||||
* 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.
|
||||
*
|
||||
* @(#)show.h 1.1 (Berkeley) 5/4/95
|
||||
* $FreeBSD: src/bin/sh/show.h,v 1.11 2004/04/06 20:06:51 markm Exp $
|
||||
*/
|
||||
|
||||
#ifdef DEBUG
|
||||
void sh_trace(const char *, ...);
|
||||
void trargs(char **);
|
||||
void trputs(char *);
|
||||
void opentrace(void);
|
||||
#endif
|
||||
|
||||
/*
|
||||
* $PchId: show.h,v 1.4 2006/03/29 13:28:45 philip Exp $
|
||||
*/
|
||||
@@ -1,15 +0,0 @@
|
||||
/* Replacement for something BSD has in sys/cdefs.h. */
|
||||
|
||||
#ifndef _ASH_SYS_CDEFS
|
||||
#define _ASH_SYS_CDEFS
|
||||
|
||||
#if __STDC__
|
||||
#define __P(params) params
|
||||
#else
|
||||
#define __P(params) ()
|
||||
#endif
|
||||
|
||||
/* Probably in sys/types.h. */
|
||||
typedef void (*sig_t) __P(( int ));
|
||||
|
||||
#endif /* _ASH_SYS_CDEFS */
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,6 +1,6 @@
|
||||
/*-
|
||||
* Copyright (c) 1991 The Regents of the University of California.
|
||||
* All rights reserved.
|
||||
* 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.
|
||||
@@ -13,10 +13,6 @@
|
||||
* 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.
|
||||
@@ -35,25 +31,45 @@
|
||||
*/
|
||||
|
||||
#ifndef lint
|
||||
static char sccsid[] = "@(#)trap.c 5.2 (Berkeley) 4/12/91";
|
||||
#if 0
|
||||
static char sccsid[] = "@(#)trap.c 8.5 (Berkeley) 6/5/95";
|
||||
#endif
|
||||
#endif /* not lint */
|
||||
/*
|
||||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD: src/bin/sh/trap.c,v 1.29 2004/04/06 20:06:51 markm Exp $");
|
||||
*/
|
||||
|
||||
#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 "signames.h"
|
||||
#include "output.h"
|
||||
#include "memalloc.h"
|
||||
#include "error.h"
|
||||
#include "trap.h"
|
||||
#include "mystring.h"
|
||||
#include <sys/types.h>
|
||||
#include <signal.h>
|
||||
#if !defined(NO_HISTORY) && !defined(EDITLINE)
|
||||
#include "myhistedit.h"
|
||||
#endif
|
||||
#include "builtins.h"
|
||||
|
||||
#ifdef __minix
|
||||
#define NO_SIGINTERRUPT
|
||||
#define NO_SYS_SIGNAME
|
||||
#define NO_SYS_SIGLIST
|
||||
|
||||
#endif
|
||||
|
||||
typedef void (*sig_T)(int);
|
||||
|
||||
/*
|
||||
* Sigmode records the current value of the signal handlers for the various
|
||||
@@ -64,40 +80,130 @@ static char sccsid[] = "@(#)trap.c 5.2 (Berkeley) 4/12/91";
|
||||
#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_HARD_IGN 4 /* signal is ignored permanently */
|
||||
#define S_RESET 5 /* temporary - to reset a hard ignored sig */
|
||||
|
||||
|
||||
extern char nullstr[1]; /* null string */
|
||||
MKINIT char sigmode[_NSIG]; /* current value of signal */
|
||||
int pendingsigs; /* indicates some signal received */
|
||||
int is_interactive= -1; /* Shell is interactive */
|
||||
int in_dotrap; /* do we execute in a trap handler? */
|
||||
static char *volatile trap[_NSIG]; /* trap handler commands */
|
||||
static volatile sig_atomic_t gotsig[_NSIG];
|
||||
/* indicates specified signal received */
|
||||
static int ignore_sigchld; /* Used while handling SIGCHLD traps. */
|
||||
volatile sig_atomic_t gotwinch;
|
||||
|
||||
static int sigstring_to_signum (char *);
|
||||
static void printsignals (void);
|
||||
static int getsigaction(int, sig_T *);
|
||||
static void onsig (int);
|
||||
#ifdef NO_SIGINTERRUPT
|
||||
static int siginterrupt (int,int);
|
||||
#endif
|
||||
static char *strsigname (int);
|
||||
|
||||
|
||||
/*
|
||||
* Map a string to a signal number.
|
||||
*/
|
||||
static int
|
||||
sigstring_to_signum(char *sig)
|
||||
{
|
||||
|
||||
if (is_number(sig)) {
|
||||
int signo;
|
||||
|
||||
signo = atoi(sig);
|
||||
return ((signo >= 0 && signo < _NSIG) ? signo : (-1));
|
||||
} else if (strcasecmp(sig, "exit") == 0) {
|
||||
return (0);
|
||||
} else {
|
||||
int n;
|
||||
|
||||
if (strncasecmp(sig, "sig", 3) == 0)
|
||||
sig += 3;
|
||||
for (n = 1; n < _NSIG; n++)
|
||||
if (strcasecmp(strsigname(n), sig) == 0)
|
||||
return (n);
|
||||
}
|
||||
return (-1);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Print a list of valid signal names.
|
||||
*/
|
||||
static void
|
||||
printsignals(void)
|
||||
{
|
||||
int n, outlen;
|
||||
|
||||
outlen = 0;
|
||||
for (n = 1; n < _NSIG; n++) {
|
||||
if (strsigname(n)) {
|
||||
out1fmt("%s", strsigname(n));
|
||||
outlen += strlen(strsigname(n));
|
||||
} else {
|
||||
out1fmt("%d", n);
|
||||
outlen += 3; /* good enough */
|
||||
}
|
||||
++outlen;
|
||||
if (outlen > 70 || n == _NSIG - 1) {
|
||||
out1str("\n");
|
||||
outlen = 0;
|
||||
} else {
|
||||
out1c(' ');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
char *trap[MAXSIG+1]; /* trap handler commands */
|
||||
MKINIT char sigmode[MAXSIG]; /* current value of signal */
|
||||
char gotsig[MAXSIG]; /* indicates specified signal received */
|
||||
int pendingsigs; /* indicates some signal received */
|
||||
|
||||
/*
|
||||
* The trap builtin.
|
||||
*/
|
||||
|
||||
trapcmd(argc, argv) char **argv; {
|
||||
int
|
||||
trapcmd(int argc, char **argv)
|
||||
{
|
||||
char *action;
|
||||
char **ap;
|
||||
int signo;
|
||||
|
||||
if (argc <= 1) {
|
||||
for (signo = 0 ; signo <= MAXSIG ; signo++) {
|
||||
if (trap[signo] != NULL)
|
||||
out1fmt("%d: %s\n", signo, trap[signo]);
|
||||
for (signo = 0 ; signo < _NSIG ; signo++) {
|
||||
if (trap[signo] != NULL) {
|
||||
if (signo == 0) {
|
||||
out1fmt("trap -- '%s' %s\n",
|
||||
trap[signo], "exit");
|
||||
} else if (strsigname(signo)) {
|
||||
out1fmt("trap -- '%s' %s\n",
|
||||
trap[signo], strsigname(signo));
|
||||
} else {
|
||||
out1fmt("trap -- '%s' %d\n",
|
||||
trap[signo], signo);
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
ap = argv + 1;
|
||||
if (is_number(*ap))
|
||||
action = NULL;
|
||||
else
|
||||
action = *ap++;
|
||||
while (*ap) {
|
||||
if ((signo = number(*ap)) < 0 || signo > MAXSIG)
|
||||
error("%s: bad trap", *ap);
|
||||
action = NULL;
|
||||
if (*++argv && strcmp(*argv, "--") == 0)
|
||||
argv++;
|
||||
if (*argv && sigstring_to_signum(*argv) == -1) {
|
||||
if ((*argv)[0] != '-') {
|
||||
action = *argv;
|
||||
argv++;
|
||||
} else if ((*argv)[1] == '\0') {
|
||||
argv++;
|
||||
} else if ((*argv)[1] == 'l' && (*argv)[2] == '\0') {
|
||||
printsignals();
|
||||
return 0;
|
||||
} else {
|
||||
error("bad option %s", *argv);
|
||||
}
|
||||
}
|
||||
while (*argv) {
|
||||
if ((signo = sigstring_to_signum(*argv)) == -1)
|
||||
error("bad signal %s", *argv);
|
||||
INTOFF;
|
||||
if (action)
|
||||
action = savestr(action);
|
||||
@@ -107,22 +213,21 @@ trapcmd(argc, argv) char **argv; {
|
||||
if (signo != 0)
|
||||
setsignal(signo);
|
||||
INTON;
|
||||
ap++;
|
||||
argv++;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Clear traps on a fork.
|
||||
*/
|
||||
|
||||
void
|
||||
clear_traps() {
|
||||
char **tp;
|
||||
clear_traps(void)
|
||||
{
|
||||
char *volatile *tp;
|
||||
|
||||
for (tp = trap ; tp <= &trap[MAXSIG] ; tp++) {
|
||||
for (tp = trap ; tp <= &trap[_NSIG - 1] ; tp++) {
|
||||
if (*tp && **tp) { /* trap not NULL or SIG_IGN */
|
||||
INTOFF;
|
||||
ckfree(*tp);
|
||||
@@ -135,18 +240,16 @@ clear_traps() {
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Set the signal handler for the specified signal. The routine figures
|
||||
* out what it should be set to.
|
||||
*/
|
||||
|
||||
int
|
||||
setsignal(signo) {
|
||||
void
|
||||
setsignal(int signo)
|
||||
{
|
||||
int action;
|
||||
sig_t sigact;
|
||||
sig_T sig, sigact = SIG_DFL;
|
||||
char *t;
|
||||
extern void onsig();
|
||||
|
||||
if ((t = trap[signo]) == NULL)
|
||||
action = S_DFL;
|
||||
@@ -154,11 +257,10 @@ setsignal(signo) {
|
||||
action = S_CATCH;
|
||||
else
|
||||
action = S_IGN;
|
||||
if (rootshell && action == S_DFL) {
|
||||
if (action == S_DFL) {
|
||||
switch (signo) {
|
||||
case SIGINT:
|
||||
if (iflag)
|
||||
action = S_CATCH;
|
||||
action = S_CATCH;
|
||||
break;
|
||||
case SIGQUIT:
|
||||
#if DEBUG
|
||||
@@ -169,68 +271,103 @@ setsignal(signo) {
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
/* FALLTHROUGH */
|
||||
action = S_CATCH;
|
||||
break;
|
||||
case SIGTERM:
|
||||
if (iflag)
|
||||
if (rootshell && iflag)
|
||||
action = S_IGN;
|
||||
break;
|
||||
#if JOBS
|
||||
case SIGTSTP:
|
||||
case SIGTTOU:
|
||||
if (jflag)
|
||||
if (rootshell && mflag)
|
||||
action = S_IGN;
|
||||
break;
|
||||
#endif
|
||||
#ifndef NO_HISTORY
|
||||
case SIGWINCH:
|
||||
if (rootshell && iflag)
|
||||
action = S_CATCH;
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
t = &sigmode[signo - 1];
|
||||
if (*t == 0) { /* current setting unknown */
|
||||
|
||||
t = &sigmode[signo];
|
||||
if (*t == 0) {
|
||||
/*
|
||||
* There is a race condition here if action is not S_IGN.
|
||||
* A signal can be ignored that shouldn't be.
|
||||
* current setting unknown
|
||||
*/
|
||||
if ((int)(sigact = signal(signo, SIG_IGN)) == -1)
|
||||
error("Signal system call failed");
|
||||
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;
|
||||
}
|
||||
if (sigact == SIG_IGN) {
|
||||
*t = S_HARD_IGN;
|
||||
if (mflag && (signo == SIGTSTP ||
|
||||
signo == SIGTTIN || signo == SIGTTOU)) {
|
||||
*t = S_IGN; /* don't hard ignore these */
|
||||
} else
|
||||
*t = S_HARD_IGN;
|
||||
} else {
|
||||
*t = S_IGN;
|
||||
*t = S_RESET; /* force to be set */
|
||||
}
|
||||
}
|
||||
if (*t == S_HARD_IGN || *t == action)
|
||||
return 0;
|
||||
return;
|
||||
switch (action) {
|
||||
case S_DFL: sigact = SIG_DFL; break;
|
||||
case S_CATCH: sigact = onsig; break;
|
||||
case S_IGN: sigact = SIG_IGN; break;
|
||||
}
|
||||
*t = action;
|
||||
return (int)signal(signo, sigact);
|
||||
sig = signal(signo, sigact);
|
||||
if (sig != SIG_ERR && action == S_CATCH)
|
||||
siginterrupt(signo, 1);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* 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(signo) {
|
||||
if (sigmode[signo - 1] != S_IGN && sigmode[signo - 1] != S_HARD_IGN) {
|
||||
ignoresig(int signo)
|
||||
{
|
||||
|
||||
if (sigmode[signo] != S_IGN && sigmode[signo] != S_HARD_IGN) {
|
||||
signal(signo, SIG_IGN);
|
||||
}
|
||||
sigmode[signo - 1] = S_HARD_IGN;
|
||||
sigmode[signo] = S_HARD_IGN;
|
||||
}
|
||||
|
||||
|
||||
#ifdef mkinit
|
||||
INCLUDE "signames.h"
|
||||
INCLUDE <signal.h>
|
||||
INCLUDE "trap.h"
|
||||
|
||||
SHELLPROC {
|
||||
char *sm;
|
||||
|
||||
clear_traps();
|
||||
for (sm = sigmode ; sm < sigmode + MAXSIG ; sm++) {
|
||||
for (sm = sigmode ; sm < sigmode + _NSIG ; sm++) {
|
||||
if (*sm == S_IGN)
|
||||
*sm = S_HARD_IGN;
|
||||
}
|
||||
@@ -238,82 +375,119 @@ SHELLPROC {
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Signal handler.
|
||||
*/
|
||||
static void
|
||||
onsig(int signo)
|
||||
{
|
||||
|
||||
void
|
||||
onsig(signo) {
|
||||
#ifndef BSD
|
||||
signal(signo, onsig);
|
||||
#endif
|
||||
if (signo == SIGINT && trap[SIGINT] == NULL) {
|
||||
onint();
|
||||
return;
|
||||
}
|
||||
gotsig[signo - 1] = 1;
|
||||
pendingsigs++;
|
||||
}
|
||||
|
||||
if (signo != SIGCHLD || !ignore_sigchld)
|
||||
gotsig[signo] = 1;
|
||||
pendingsigs++;
|
||||
|
||||
/* If we are currently in a wait builtin, prepare to break it */
|
||||
if ((signo == SIGINT || signo == SIGQUIT) && in_waitcmd != 0)
|
||||
breakwaitcmd = 1;
|
||||
/*
|
||||
* If a trap is set, not ignored and not the null command, we need
|
||||
* to make sure traps are executed even when a child blocks signals.
|
||||
*/
|
||||
if (Tflag &&
|
||||
trap[signo] != NULL &&
|
||||
! trap[signo][0] == '\0' &&
|
||||
! (trap[signo][0] == ':' && trap[signo][1] == '\0'))
|
||||
breakwaitcmd = 1;
|
||||
|
||||
#ifndef NO_HISTORY
|
||||
if (signo == SIGWINCH)
|
||||
gotwinch = 1;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Called to execute a trap. Perhaps we should avoid entering new trap
|
||||
* handlers while we are executing a trap handler.
|
||||
*/
|
||||
|
||||
void
|
||||
dotrap() {
|
||||
dotrap(void)
|
||||
{
|
||||
int i;
|
||||
int savestatus;
|
||||
|
||||
in_dotrap++;
|
||||
for (;;) {
|
||||
for (i = 1 ; ; i++) {
|
||||
if (gotsig[i - 1])
|
||||
for (i = 1; i < _NSIG; i++) {
|
||||
if (gotsig[i]) {
|
||||
gotsig[i] = 0;
|
||||
if (trap[i]) {
|
||||
/*
|
||||
* Ignore SIGCHLD to avoid infinite
|
||||
* recursion if the trap action does
|
||||
* a fork.
|
||||
*/
|
||||
if (i == SIGCHLD)
|
||||
ignore_sigchld++;
|
||||
savestatus = exitstatus;
|
||||
evalstring(trap[i]);
|
||||
exitstatus = savestatus;
|
||||
if (i == SIGCHLD)
|
||||
ignore_sigchld--;
|
||||
}
|
||||
break;
|
||||
if (i >= MAXSIG)
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
gotsig[i - 1] = 0;
|
||||
savestatus=exitstatus;
|
||||
evalstring(trap[i]);
|
||||
exitstatus=savestatus;
|
||||
if (i >= _NSIG)
|
||||
break;
|
||||
}
|
||||
done:
|
||||
in_dotrap--;
|
||||
pendingsigs = 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Controls whether the shell is interactive or not.
|
||||
*/
|
||||
|
||||
int is_interactive;
|
||||
|
||||
void
|
||||
setinteractive(on) {
|
||||
setinteractive(int on)
|
||||
{
|
||||
if (on == is_interactive)
|
||||
return;
|
||||
setsignal(SIGINT);
|
||||
setsignal(SIGQUIT);
|
||||
setsignal(SIGTERM);
|
||||
#ifndef NO_HISTORY
|
||||
setsignal(SIGWINCH);
|
||||
#endif
|
||||
is_interactive = on;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Called to exit the shell.
|
||||
*/
|
||||
|
||||
void
|
||||
exitshell(status) {
|
||||
exitshell(int status)
|
||||
{
|
||||
struct jmploc loc1, loc2;
|
||||
char *p;
|
||||
|
||||
TRACE(("exitshell(%d) pid=%d\n", status, getpid()));
|
||||
if (setjmp(loc1.loc)) goto l1;
|
||||
if (setjmp(loc2.loc)) goto l2;
|
||||
if (setjmp(loc1.loc)) {
|
||||
goto l1;
|
||||
}
|
||||
if (setjmp(loc2.loc)) {
|
||||
goto l2;
|
||||
}
|
||||
handler = &loc1;
|
||||
if ((p = trap[0]) != NULL && *p != '\0') {
|
||||
trap[0] = NULL;
|
||||
@@ -326,3 +500,85 @@ l1: handler = &loc2; /* probably unnecessary */
|
||||
#endif
|
||||
l2: _exit(status);
|
||||
}
|
||||
|
||||
#ifdef NO_SIGINTERRUPT
|
||||
static int siginterrupt(sig, flag)
|
||||
int sig;
|
||||
int flag;
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef NO_SYS_SIGNAME
|
||||
static char *strsigname(sig)
|
||||
int sig;
|
||||
{
|
||||
switch(sig)
|
||||
{
|
||||
case 0: return "Signal 0"; /* 0 */
|
||||
case SIGHUP: return "hup"; /* 1 */
|
||||
case SIGINT: return "int"; /* 2 */
|
||||
case SIGQUIT: return "quit"; /* 3 */
|
||||
case SIGILL: return "ill"; /* 4 */
|
||||
case SIGTRAP: return "trap"; /* 5 */
|
||||
case SIGABRT: return "abrt"; /* 6 */
|
||||
#ifdef __minix_vmd
|
||||
case SIGEMT: return "emt"; /* 7 */
|
||||
#else
|
||||
case SIGBUS: return "bus"; /* 7 */
|
||||
#endif
|
||||
case SIGFPE: return "fpe"; /* 8 */
|
||||
case SIGKILL: return "kill"; /* 9 */
|
||||
case SIGUSR1: return "usr1"; /* 10 */
|
||||
case SIGSEGV: return "segv"; /* 11 */
|
||||
case SIGUSR2: return "usr2"; /* 12 */
|
||||
case SIGPIPE: return "pipe"; /* 13 */
|
||||
case SIGALRM: return "alrm"; /* 14 */
|
||||
case SIGTERM: return "term"; /* 15 */
|
||||
#ifdef __minix_vmd
|
||||
case 16: return "Signal 16"; /* 16 */
|
||||
#else
|
||||
case SIGEMT: return "emt"; /* 16 */
|
||||
#endif
|
||||
case SIGCHLD: return "chld"; /* 17 */
|
||||
case SIGCONT: return "cont"; /* 18 */
|
||||
case SIGSTOP: return "stop"; /* 19 */
|
||||
case SIGTSTP: return "tstp"; /* 20 */
|
||||
case SIGTTIN: return "ttin"; /* 21 */
|
||||
case SIGTTOU: return "ttou"; /* 22 */
|
||||
case SIGWINCH: return "winch"; /* 23 */
|
||||
#ifdef __minix_vmd
|
||||
case SIGFPEMU: return "fpemu"; /* 30 */
|
||||
#endif
|
||||
default: return "Signal n";
|
||||
}
|
||||
}
|
||||
#else
|
||||
static char *strsigname(sig)
|
||||
int sig;
|
||||
{
|
||||
return sys_signame[sig];
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef NO_SYS_SIGLIST
|
||||
#include "signames.h"
|
||||
char *strsiglist(sig)
|
||||
int sig;
|
||||
{
|
||||
if (sig > MAXSIG)
|
||||
return NULL;
|
||||
return sigmesg[sig];
|
||||
}
|
||||
#else
|
||||
char *strsiglist(sig)
|
||||
int sig;
|
||||
{
|
||||
return sys_siglist[sig];
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* $PchId: trap.c,v 1.7 2006/05/23 11:56:21 philip Exp $
|
||||
*/
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*-
|
||||
* Copyright (c) 1991 The Regents of the University of California.
|
||||
* All rights reserved.
|
||||
* 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.
|
||||
@@ -13,10 +13,6 @@
|
||||
* 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.
|
||||
@@ -33,23 +29,24 @@
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)trap.h 5.1 (Berkeley) 3/7/91
|
||||
* @(#)trap.h 8.3 (Berkeley) 6/5/95
|
||||
* $FreeBSD: src/bin/sh/trap.h,v 1.12 2004/04/06 20:06:51 markm Exp $
|
||||
*/
|
||||
|
||||
extern int pendingsigs;
|
||||
extern int in_dotrap;
|
||||
extern int is_interactive;
|
||||
extern volatile sig_atomic_t gotwinch;
|
||||
|
||||
#ifdef __STDC__
|
||||
int trapcmd(int, char **);
|
||||
void clear_traps(void);
|
||||
int setsignal(int);
|
||||
void setsignal(int);
|
||||
void ignoresig(int);
|
||||
void dotrap(void);
|
||||
void setinteractive(int);
|
||||
void exitshell(int);
|
||||
#else
|
||||
void clear_traps();
|
||||
int setsignal();
|
||||
void ignoresig();
|
||||
void dotrap();
|
||||
void setinteractive();
|
||||
void exitshell();
|
||||
#endif
|
||||
char *strsiglist(int);
|
||||
|
||||
/*
|
||||
* $PchId: trap.h,v 1.6 2006/05/22 12:48:30 philip Exp $
|
||||
*/
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*-
|
||||
* Copyright (c) 1991 The Regents of the University of California.
|
||||
* All rights reserved.
|
||||
* 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.
|
||||
@@ -13,10 +13,6 @@
|
||||
* 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.
|
||||
@@ -35,13 +31,27 @@
|
||||
*/
|
||||
|
||||
#ifndef lint
|
||||
static char sccsid[] = "@(#)var.c 5.3 (Berkeley) 4/12/91";
|
||||
#if 0
|
||||
static char sccsid[] = "@(#)var.c 8.3 (Berkeley) 5/4/95";
|
||||
#endif
|
||||
#endif /* not lint */
|
||||
/*
|
||||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD: src/bin/sh/var.c,v 1.26.2.1 2004/09/30 04:41:55 des Exp $");
|
||||
*/
|
||||
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
#ifndef NO_PATHS_H
|
||||
#include <paths.h>
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Shell variables.
|
||||
*/
|
||||
|
||||
#include <locale.h>
|
||||
|
||||
#include "shell.h"
|
||||
#include "output.h"
|
||||
#include "expand.h"
|
||||
@@ -55,7 +65,16 @@ static char sccsid[] = "@(#)var.c 5.3 (Berkeley) 4/12/91";
|
||||
#include "memalloc.h"
|
||||
#include "error.h"
|
||||
#include "mystring.h"
|
||||
#include "parser.h"
|
||||
#if !defined(NO_HISTORY) && !defined(EDITLINE)
|
||||
#include "myhistedit.h"
|
||||
#endif
|
||||
|
||||
#include "builtins.h"
|
||||
|
||||
#ifndef _PATH_DEFPATH
|
||||
#define _PATH_DEFPATH "/usr/bin:/bin"
|
||||
#endif
|
||||
|
||||
#define VTABSIZE 39
|
||||
|
||||
@@ -64,48 +83,57 @@ struct varinit {
|
||||
struct var *var;
|
||||
int flags;
|
||||
char *text;
|
||||
void (*func)(const char *);
|
||||
};
|
||||
|
||||
|
||||
#if ATTY
|
||||
struct var vatty;
|
||||
#ifndef NO_HISTORY
|
||||
struct var vhistsize;
|
||||
#endif
|
||||
struct var vifs;
|
||||
struct var vmail;
|
||||
struct var vmpath;
|
||||
struct var vpath;
|
||||
struct var vppid;
|
||||
struct var vps1;
|
||||
struct var vps2;
|
||||
struct var vpse;
|
||||
struct var vvers;
|
||||
#if ATTY
|
||||
struct var vterm;
|
||||
#endif
|
||||
STATIC struct var voptind;
|
||||
|
||||
const struct varinit varinit[] = {
|
||||
#if ATTY
|
||||
{&vatty, VSTRFIXED|VTEXTFIXED|VUNSET, "ATTY="},
|
||||
STATIC const struct varinit varinit[] = {
|
||||
#if !defined(NO_HISTORY) && !defined(EDITLINE)
|
||||
{ &vhistsize, VSTRFIXED|VTEXTFIXED|VUNSET, "HISTSIZE=",
|
||||
sethistsize },
|
||||
#endif
|
||||
{&vifs, VSTRFIXED|VTEXTFIXED, "IFS= \t\n"},
|
||||
{&vmail, VSTRFIXED|VTEXTFIXED|VUNSET, "MAIL="},
|
||||
{&vmpath, VSTRFIXED|VTEXTFIXED|VUNSET, "MAILPATH="},
|
||||
{&vpath, VSTRFIXED|VTEXTFIXED, "PATH=:/bin:/usr/bin"},
|
||||
/*
|
||||
{ &vifs, VSTRFIXED|VTEXTFIXED, "IFS= \t\n",
|
||||
NULL },
|
||||
{ &vmail, VSTRFIXED|VTEXTFIXED|VUNSET, "MAIL=",
|
||||
NULL },
|
||||
{ &vmpath, VSTRFIXED|VTEXTFIXED|VUNSET, "MAILPATH=",
|
||||
NULL },
|
||||
{ &vpath, VSTRFIXED|VTEXTFIXED, "PATH=" _PATH_DEFPATH,
|
||||
changepath },
|
||||
{ &vppid, VSTRFIXED|VTEXTFIXED|VUNSET, "PPID=",
|
||||
NULL },
|
||||
/*
|
||||
* vps1 depends on uid
|
||||
*/
|
||||
{&vps2, VSTRFIXED|VTEXTFIXED, "PS2=> "},
|
||||
{&vpse, VSTRFIXED|VTEXTFIXED, "PSE=* "},
|
||||
#if ATTY
|
||||
{&vterm, VSTRFIXED|VTEXTFIXED|VUNSET, "TERM="},
|
||||
#endif
|
||||
{NULL, 0, NULL}
|
||||
{ &vps2, VSTRFIXED|VTEXTFIXED, "PS2=> ",
|
||||
NULL },
|
||||
{ &vpse, VSTRFIXED|VTEXTFIXED|VUNSET, "PSE=",
|
||||
NULL },
|
||||
{ &voptind, VSTRFIXED|VTEXTFIXED, "OPTIND=1",
|
||||
getoptsreset },
|
||||
{ NULL, 0, NULL,
|
||||
NULL }
|
||||
};
|
||||
|
||||
struct var *vartab[VTABSIZE];
|
||||
STATIC struct var *vartab[VTABSIZE];
|
||||
|
||||
STATIC void unsetvar __P((char *));
|
||||
STATIC struct var **hashvar __P((char *));
|
||||
STATIC int varequal __P((char *, char *));
|
||||
STATIC struct var **hashvar(char *);
|
||||
STATIC int varequal(char *, char *);
|
||||
STATIC int localevar(char *);
|
||||
|
||||
/*
|
||||
* Initialize the varable symbol tables and import the environment
|
||||
@@ -133,7 +161,9 @@ INIT {
|
||||
*/
|
||||
|
||||
void
|
||||
initvar() {
|
||||
initvar(void)
|
||||
{
|
||||
char ppid[20];
|
||||
const struct varinit *ip;
|
||||
struct var *vp;
|
||||
struct var **vpp;
|
||||
@@ -145,6 +175,7 @@ initvar() {
|
||||
*vpp = vp;
|
||||
vp->text = ip->text;
|
||||
vp->flags = ip->flags;
|
||||
vp->func = ip->func;
|
||||
}
|
||||
}
|
||||
/*
|
||||
@@ -154,20 +185,48 @@ initvar() {
|
||||
vpp = hashvar("PS1=");
|
||||
vps1.next = *vpp;
|
||||
*vpp = &vps1;
|
||||
vps1.text = getuid() ? "PS1=$ " : "PS1=# ";
|
||||
vps1.text = geteuid() ? "PS1=$ " : "PS1=# ";
|
||||
vps1.flags = VSTRFIXED|VTEXTFIXED;
|
||||
}
|
||||
if ((vppid.flags & VEXPORT) == 0) {
|
||||
fmtstr(ppid, sizeof(ppid), "%d", (int)getppid());
|
||||
setvarsafe("PPID", ppid, 0);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Set the value of a variable. The flags argument is ored with the
|
||||
* Safe version of setvar, returns 1 on success 0 on failure.
|
||||
*/
|
||||
|
||||
int
|
||||
setvarsafe(char *name, char *val, int flags)
|
||||
{
|
||||
struct jmploc jmploc;
|
||||
struct jmploc *volatile savehandler = handler;
|
||||
int err = 0;
|
||||
#if __GNUC__
|
||||
/* Avoid longjmp clobbering */
|
||||
(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 tored with the
|
||||
* flags of the variable. If val is NULL, the variable is unset.
|
||||
*/
|
||||
|
||||
void
|
||||
setvar(name, val, flags)
|
||||
char *name, *val;
|
||||
{
|
||||
setvar(char *name, char *val, int flags)
|
||||
{
|
||||
char *p, *q;
|
||||
int len;
|
||||
int namelen;
|
||||
@@ -176,8 +235,9 @@ setvar(name, val, flags)
|
||||
|
||||
isbad = 0;
|
||||
p = name;
|
||||
if (! is_name(*p++))
|
||||
if (! is_name(*p))
|
||||
isbad = 1;
|
||||
p++;
|
||||
for (;;) {
|
||||
if (! is_in_name(*p)) {
|
||||
if (*p == '\0' || *p == '=')
|
||||
@@ -188,7 +248,7 @@ setvar(name, val, flags)
|
||||
}
|
||||
namelen = p - name;
|
||||
if (isbad)
|
||||
error("%.*s: is read only", namelen, name);
|
||||
error("%.*s: bad variable name", namelen, name);
|
||||
len = namelen + 2; /* 2 is space for '=' and '\0' */
|
||||
if (val == NULL) {
|
||||
flags |= VUNSET;
|
||||
@@ -206,7 +266,26 @@ setvar(name, val, flags)
|
||||
setvareq(nameeq, flags);
|
||||
}
|
||||
|
||||
STATIC int
|
||||
localevar(char *s)
|
||||
{
|
||||
static char *lnames[7] = {
|
||||
"ALL", "COLLATE", "CTYPE", "MONETARY",
|
||||
"NUMERIC", "TIME", NULL
|
||||
};
|
||||
char **ss;
|
||||
|
||||
if (*s != 'L')
|
||||
return 0;
|
||||
if (varequal(s + 1, "ANG"))
|
||||
return 1;
|
||||
if (strncmp(s + 1, "C_", 2) != 0)
|
||||
return 0;
|
||||
for (ss = lnames; *ss ; ss++)
|
||||
if (varequal(s + 3, *ss))
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Same as setvar except that the variable and value are passed in
|
||||
@@ -216,28 +295,42 @@ setvar(name, val, flags)
|
||||
*/
|
||||
|
||||
void
|
||||
setvareq(s, flags)
|
||||
char *s;
|
||||
{
|
||||
setvareq(char *s, int flags)
|
||||
{
|
||||
struct var *vp, **vpp;
|
||||
int len;
|
||||
|
||||
if (aflag)
|
||||
flags |= VEXPORT;
|
||||
vpp = hashvar(s);
|
||||
for (vp = *vpp ; vp ; vp = vp->next) {
|
||||
if (varequal(s, vp->text)) {
|
||||
if (vp->flags & VREADONLY) {
|
||||
int len = strchr(s, '=') - s;
|
||||
len = strchr(s, '=') - s;
|
||||
error("%.*s: is read only", len, s);
|
||||
}
|
||||
INTOFF;
|
||||
if (vp == &vpath)
|
||||
changepath(s + 5); /* 5 = strlen("PATH=") */
|
||||
|
||||
if (vp->func && (flags & VNOFUNC) == 0)
|
||||
(*vp->func)(strchr(s, '=') + 1);
|
||||
|
||||
if ((vp->flags & (VTEXTFIXED|VSTACK)) == 0)
|
||||
ckfree(vp->text);
|
||||
vp->flags &=~ (VTEXTFIXED|VSTACK|VUNSET);
|
||||
|
||||
vp->flags &= ~(VTEXTFIXED|VSTACK|VUNSET);
|
||||
vp->flags |= flags;
|
||||
vp->text = s;
|
||||
|
||||
/*
|
||||
* We could roll this to a function, to handle it as
|
||||
* a regular variable function callback, but why bother?
|
||||
*/
|
||||
if (vp == &vmpath || (vp == &vmail && ! mpathset()))
|
||||
chkmail(1);
|
||||
if ((vp->flags & VEXPORT) && localevar(s)) {
|
||||
putenv(s);
|
||||
(void) setlocale(LC_ALL, "");
|
||||
}
|
||||
INTON;
|
||||
return;
|
||||
}
|
||||
@@ -247,7 +340,14 @@ setvareq(s, flags)
|
||||
vp->flags = flags;
|
||||
vp->text = s;
|
||||
vp->next = *vpp;
|
||||
vp->func = NULL;
|
||||
INTOFF;
|
||||
*vpp = vp;
|
||||
if ((vp->flags & VEXPORT) && localevar(s)) {
|
||||
putenv(s);
|
||||
(void) setlocale(LC_ALL, "");
|
||||
}
|
||||
INTON;
|
||||
}
|
||||
|
||||
|
||||
@@ -257,9 +357,8 @@ setvareq(s, flags)
|
||||
*/
|
||||
|
||||
void
|
||||
listsetvar(list)
|
||||
struct strlist *list;
|
||||
{
|
||||
listsetvar(struct strlist *list)
|
||||
{
|
||||
struct strlist *lp;
|
||||
|
||||
INTOFF;
|
||||
@@ -276,9 +375,8 @@ listsetvar(list)
|
||||
*/
|
||||
|
||||
char *
|
||||
lookupvar(name)
|
||||
char *name;
|
||||
{
|
||||
lookupvar(char *name)
|
||||
{
|
||||
struct var *v;
|
||||
|
||||
for (v = *hashvar(name) ; v ; v = v->next) {
|
||||
@@ -300,9 +398,8 @@ lookupvar(name)
|
||||
*/
|
||||
|
||||
char *
|
||||
bltinlookup(name, doall)
|
||||
char *name;
|
||||
{
|
||||
bltinlookup(char *name, int doall)
|
||||
{
|
||||
struct strlist *sp;
|
||||
struct var *v;
|
||||
|
||||
@@ -312,8 +409,8 @@ bltinlookup(name, doall)
|
||||
}
|
||||
for (v = *hashvar(name) ; v ; v = v->next) {
|
||||
if (varequal(v->text, name)) {
|
||||
if (v->flags & VUNSET
|
||||
|| ! doall && (v->flags & VEXPORT) == 0)
|
||||
if ((v->flags & VUNSET)
|
||||
|| (!doall && (v->flags & VEXPORT) == 0))
|
||||
return NULL;
|
||||
return strchr(v->text, '=') + 1;
|
||||
}
|
||||
@@ -329,7 +426,8 @@ bltinlookup(name, doall)
|
||||
*/
|
||||
|
||||
char **
|
||||
environment() {
|
||||
environment(void)
|
||||
{
|
||||
int nenv;
|
||||
struct var **vpp;
|
||||
struct var *vp;
|
||||
@@ -359,15 +457,14 @@ environment() {
|
||||
*/
|
||||
|
||||
#ifdef mkinit
|
||||
MKINIT void shprocvar();
|
||||
|
||||
SHELLPROC {
|
||||
shprocvar();
|
||||
}
|
||||
#endif
|
||||
|
||||
void
|
||||
shprocvar() {
|
||||
shprocvar(void)
|
||||
{
|
||||
struct var **vpp;
|
||||
struct var *vp, **prev;
|
||||
|
||||
@@ -400,14 +497,21 @@ shprocvar() {
|
||||
*/
|
||||
|
||||
int
|
||||
showvarscmd(argc, argv) char **argv; {
|
||||
showvarscmd(int argc __unused, char **argv __unused)
|
||||
{
|
||||
struct var **vpp;
|
||||
struct var *vp;
|
||||
const char *s;
|
||||
|
||||
for (vpp = vartab ; vpp < vartab + VTABSIZE ; vpp++) {
|
||||
for (vp = *vpp ; vp ; vp = vp->next) {
|
||||
if ((vp->flags & VUNSET) == 0)
|
||||
out1fmt("%s\n", vp->text);
|
||||
if (vp->flags & VUNSET)
|
||||
continue;
|
||||
for (s = vp->text; *s != '='; s++)
|
||||
out1c(*s);
|
||||
out1c('=');
|
||||
out1qstr(s + 1);
|
||||
out1c('\n');
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
@@ -420,15 +524,35 @@ showvarscmd(argc, argv) char **argv; {
|
||||
*/
|
||||
|
||||
int
|
||||
exportcmd(argc, argv) char **argv; {
|
||||
exportcmd(int argc, char **argv)
|
||||
{
|
||||
struct var **vpp;
|
||||
struct var *vp;
|
||||
char *name;
|
||||
char *p;
|
||||
char *cmdname;
|
||||
int ch, values;
|
||||
int flag = argv[0][0] == 'r'? VREADONLY : VEXPORT;
|
||||
|
||||
cmdname = argv[0];
|
||||
optreset = optind = 1;
|
||||
opterr = 0;
|
||||
values = 0;
|
||||
while ((ch = getopt(argc, argv, "p")) != -1) {
|
||||
switch (ch) {
|
||||
case 'p':
|
||||
values = 1;
|
||||
break;
|
||||
case '?':
|
||||
default:
|
||||
error("unknown option: -%c", optopt);
|
||||
}
|
||||
}
|
||||
argc -= optind;
|
||||
argv += optind;
|
||||
|
||||
listsetvar(cmdenviron);
|
||||
if (argc > 1) {
|
||||
if (argc != 0) {
|
||||
while ((name = *argptr++) != NULL) {
|
||||
if ((p = strchr(name, '=')) != NULL) {
|
||||
p++;
|
||||
@@ -436,7 +560,12 @@ exportcmd(argc, argv) char **argv; {
|
||||
vpp = hashvar(name);
|
||||
for (vp = *vpp ; vp ; vp = vp->next) {
|
||||
if (varequal(vp->text, name)) {
|
||||
|
||||
vp->flags |= flag;
|
||||
if ((vp->flags & VEXPORT) && localevar(vp->text)) {
|
||||
putenv(vp->text);
|
||||
(void) setlocale(LC_ALL, "");
|
||||
}
|
||||
goto found;
|
||||
}
|
||||
}
|
||||
@@ -448,8 +577,16 @@ found:;
|
||||
for (vpp = vartab ; vpp < vartab + VTABSIZE ; vpp++) {
|
||||
for (vp = *vpp ; vp ; vp = vp->next) {
|
||||
if (vp->flags & flag) {
|
||||
if (values) {
|
||||
out1str(cmdname);
|
||||
out1c(' ');
|
||||
}
|
||||
for (p = vp->text ; *p != '=' ; p++)
|
||||
out1c(*p);
|
||||
if (values && !(vp->flags & VUNSET)) {
|
||||
out1c('=');
|
||||
out1qstr(p + 1);
|
||||
}
|
||||
out1c('\n');
|
||||
}
|
||||
}
|
||||
@@ -463,7 +600,9 @@ found:;
|
||||
* The "local" command.
|
||||
*/
|
||||
|
||||
localcmd(argc, argv) char **argv; {
|
||||
int
|
||||
localcmd(int argc __unused, char **argv __unused)
|
||||
{
|
||||
char *name;
|
||||
|
||||
if (! in_function())
|
||||
@@ -483,9 +622,8 @@ localcmd(argc, argv) char **argv; {
|
||||
*/
|
||||
|
||||
void
|
||||
mklocal(name)
|
||||
char *name;
|
||||
{
|
||||
mklocal(char *name)
|
||||
{
|
||||
struct localvar *lvp;
|
||||
struct var **vpp;
|
||||
struct var *vp;
|
||||
@@ -493,8 +631,8 @@ mklocal(name)
|
||||
INTOFF;
|
||||
lvp = ckmalloc(sizeof (struct localvar));
|
||||
if (name[0] == '-' && name[1] == '\0') {
|
||||
lvp->text = ckmalloc(sizeof optval);
|
||||
bcopy(optval, lvp->text, sizeof optval);
|
||||
lvp->text = ckmalloc(sizeof optlist);
|
||||
memcpy(lvp->text, optlist, sizeof optlist);
|
||||
vp = NULL;
|
||||
} else {
|
||||
vpp = hashvar(name);
|
||||
@@ -527,7 +665,8 @@ mklocal(name)
|
||||
*/
|
||||
|
||||
void
|
||||
poplocalvars() {
|
||||
poplocalvars(void)
|
||||
{
|
||||
struct localvar *lvp;
|
||||
struct var *vp;
|
||||
|
||||
@@ -535,10 +674,10 @@ poplocalvars() {
|
||||
localvars = lvp->next;
|
||||
vp = lvp->vp;
|
||||
if (vp == NULL) { /* $- saved */
|
||||
bcopy(lvp->text, optval, sizeof optval);
|
||||
memcpy(optlist, lvp->text, sizeof optlist);
|
||||
ckfree(lvp->text);
|
||||
} else if ((lvp->flags & (VUNSET|VSTRFIXED)) == VUNSET) {
|
||||
unsetvar(vp->text);
|
||||
(void)unsetvar(vp->text);
|
||||
} else {
|
||||
if ((vp->flags & VTEXTFIXED) == 0)
|
||||
ckfree(vp->text);
|
||||
@@ -550,7 +689,9 @@ poplocalvars() {
|
||||
}
|
||||
|
||||
|
||||
setvarcmd(argc, argv) char **argv; {
|
||||
int
|
||||
setvarcmd(int argc, char **argv)
|
||||
{
|
||||
if (argc <= 2)
|
||||
return unsetcmd(argc, argv);
|
||||
else if (argc == 3)
|
||||
@@ -567,14 +708,31 @@ setvarcmd(argc, argv) char **argv; {
|
||||
* with the same name.
|
||||
*/
|
||||
|
||||
unsetcmd(argc, argv) char **argv; {
|
||||
int
|
||||
unsetcmd(int argc __unused, char **argv __unused)
|
||||
{
|
||||
char **ap;
|
||||
int i;
|
||||
int flg_func = 0;
|
||||
int flg_var = 0;
|
||||
int ret = 0;
|
||||
|
||||
for (ap = argv + 1 ; *ap ; ap++) {
|
||||
unsetfunc(*ap);
|
||||
unsetvar(*ap);
|
||||
while ((i = nextopt("vf")) != '\0') {
|
||||
if (i == 'f')
|
||||
flg_func = 1;
|
||||
else
|
||||
flg_var = 1;
|
||||
}
|
||||
return 0;
|
||||
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);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
@@ -582,22 +740,25 @@ unsetcmd(argc, argv) char **argv; {
|
||||
* Unset the specified variable.
|
||||
*/
|
||||
|
||||
STATIC void
|
||||
unsetvar(s)
|
||||
char *s;
|
||||
{
|
||||
int
|
||||
unsetvar(char *s)
|
||||
{
|
||||
struct var **vpp;
|
||||
struct var *vp;
|
||||
|
||||
vpp = hashvar(s);
|
||||
for (vp = *vpp ; vp ; vpp = &vp->next, vp = *vpp) {
|
||||
if (varequal(vp->text, s)) {
|
||||
if (vp->flags & VREADONLY)
|
||||
return (1);
|
||||
INTOFF;
|
||||
if (*(strchr(vp->text, '=') + 1) != '\0'
|
||||
|| vp->flags & VREADONLY) {
|
||||
if (*(strchr(vp->text, '=') + 1) != '\0')
|
||||
setvar(s, nullstr, 0);
|
||||
if ((vp->flags & VEXPORT) && localevar(vp->text)) {
|
||||
unsetenv(s);
|
||||
setlocale(LC_ALL, "");
|
||||
}
|
||||
vp->flags &=~ VEXPORT;
|
||||
vp->flags &= ~VEXPORT;
|
||||
vp->flags |= VUNSET;
|
||||
if ((vp->flags & VSTRFIXED) == 0) {
|
||||
if ((vp->flags & VTEXTFIXED) == 0)
|
||||
@@ -606,9 +767,11 @@ unsetvar(s)
|
||||
ckfree(vp);
|
||||
}
|
||||
INTON;
|
||||
return;
|
||||
return (0);
|
||||
}
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
|
||||
@@ -618,14 +781,13 @@ unsetvar(s)
|
||||
*/
|
||||
|
||||
STATIC struct var **
|
||||
hashvar(p)
|
||||
register char *p;
|
||||
{
|
||||
hashvar(char *p)
|
||||
{
|
||||
unsigned int hashval;
|
||||
|
||||
hashval = *p << 4;
|
||||
hashval = ((unsigned char) *p) << 4;
|
||||
while (*p && *p != '=')
|
||||
hashval += *p++;
|
||||
hashval += (unsigned char) *p++;
|
||||
return &vartab[hashval % VTABSIZE];
|
||||
}
|
||||
|
||||
@@ -638,9 +800,8 @@ hashvar(p)
|
||||
*/
|
||||
|
||||
STATIC int
|
||||
varequal(p, q)
|
||||
register char *p, *q;
|
||||
{
|
||||
varequal(char *p, char *q)
|
||||
{
|
||||
while (*p == *q++) {
|
||||
if (*p++ == '=')
|
||||
return 1;
|
||||
@@ -649,3 +810,7 @@ varequal(p, q)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* $PchId: var.c,v 1.5 2006/05/22 12:28:49 philip Exp $
|
||||
*/
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*-
|
||||
* Copyright (c) 1991 The Regents of the University of California.
|
||||
* All rights reserved.
|
||||
* 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.
|
||||
@@ -13,10 +13,6 @@
|
||||
* 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.
|
||||
@@ -33,7 +29,8 @@
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)var.h 5.1 (Berkeley) 3/7/91
|
||||
* @(#)var.h 8.2 (Berkeley) 5/4/95
|
||||
* $FreeBSD: src/bin/sh/var.h,v 1.12 2004/04/06 20:06:51 markm Exp $
|
||||
*/
|
||||
|
||||
/*
|
||||
@@ -41,43 +38,45 @@
|
||||
*/
|
||||
|
||||
/* flags */
|
||||
#define VEXPORT 01 /* variable is exported */
|
||||
#define VREADONLY 02 /* variable cannot be modified */
|
||||
#define VSTRFIXED 04 /* variable struct is staticly allocated */
|
||||
#define VTEXTFIXED 010 /* text is staticly allocated */
|
||||
#define VSTACK 020 /* text is allocated on the stack */
|
||||
#define VUNSET 040 /* the variable is not set */
|
||||
#define VEXPORT 0x01 /* variable is exported */
|
||||
#define VREADONLY 0x02 /* variable cannot be modified */
|
||||
#define VSTRFIXED 0x04 /* variable struct is staticly allocated */
|
||||
#define VTEXTFIXED 0x08 /* text is staticly 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 */
|
||||
|
||||
|
||||
struct var {
|
||||
struct var *next; /* next entry in hash list */
|
||||
int flags; /* flags are defined above */
|
||||
char *text; /* name=value */
|
||||
int flags; /* flags are defined above */
|
||||
char *text; /* name=value */
|
||||
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 *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 vmail;
|
||||
extern struct var vmpath;
|
||||
extern struct var vpath;
|
||||
extern struct var vppid;
|
||||
extern struct var vps1;
|
||||
extern struct var vps2;
|
||||
extern struct var vpse;
|
||||
#if ATTY
|
||||
extern struct var vterm;
|
||||
#ifndef NO_HISTORY
|
||||
extern struct var vhistsize;
|
||||
#endif
|
||||
|
||||
/*
|
||||
@@ -87,43 +86,39 @@ extern struct var vterm;
|
||||
*/
|
||||
|
||||
#define ifsval() (vifs.text + 4)
|
||||
#define ifsset() ((vifs.flags & VUNSET) == 0)
|
||||
#define mailval() (vmail.text + 5)
|
||||
#define mpathval() (vmpath.text + 9)
|
||||
#define pathval() (vpath.text + 5)
|
||||
#define ps1val() (vps1.text + 4)
|
||||
#define ps2val() (vps2.text + 4)
|
||||
#define pseval() (vpse.text + 4)
|
||||
#if ATTY
|
||||
#define termval() (vterm.text + 5)
|
||||
#define optindval() (voptind.text + 7)
|
||||
#ifndef NO_HISTORY
|
||||
#define histsizeval() (vhistsize.text + 9)
|
||||
#endif
|
||||
|
||||
#if ATTY
|
||||
#define attyset() ((vatty.flags & VUNSET) == 0)
|
||||
#endif
|
||||
#define mpathset() ((vmpath.flags & VUNSET) == 0)
|
||||
|
||||
|
||||
#ifdef __STDC__
|
||||
void initvar();
|
||||
void initvar(void);
|
||||
void setvar(char *, char *, int);
|
||||
void setvareq(char *, int);
|
||||
struct strlist;
|
||||
void listsetvar(struct strlist *);
|
||||
char *lookupvar(char *);
|
||||
char *bltinlookup(char *, int);
|
||||
char **environment();
|
||||
char **environment(void);
|
||||
void shprocvar(void);
|
||||
int showvarscmd(int, char **);
|
||||
int exportcmd(int, char **);
|
||||
int localcmd(int, char **);
|
||||
void mklocal(char *);
|
||||
void poplocalvars(void);
|
||||
#else
|
||||
void initvar();
|
||||
void setvar();
|
||||
void setvareq();
|
||||
void listsetvar();
|
||||
char *lookupvar();
|
||||
char *bltinlookup();
|
||||
char **environment();
|
||||
int showvarscmd();
|
||||
void mklocal();
|
||||
void poplocalvars();
|
||||
#endif
|
||||
int setvarcmd(int, char **);
|
||||
int unsetcmd(int, char **);
|
||||
int unsetvar(char *);
|
||||
int setvarsafe(char *, char *, int);
|
||||
|
||||
/*
|
||||
* $PchId: var.h,v 1.4 2006/03/29 12:04:45 philip Exp $
|
||||
*/
|
||||
|
||||
@@ -1,38 +0,0 @@
|
||||
a small AWK clone
|
||||
|
||||
このプログラムは、Minix 1.2 用に書いたものです。浮動小数点演算を使い
|
||||
ますから、Minix 1.5 以前の ACK-C ではコンパイルできません。そのため makefile
|
||||
では、Peter S. Houselさんの浮動小数点パッケージを使うようになっています。
|
||||
CFLAGS の -f が、その指示です。この浮動小数点パッケージは、非常によくできて
|
||||
いますが、atan(x, y) の引き数の順序が逆になっていますので、修正しておいてく
|
||||
ださい。他にも何かあったような記憶がありますが、忘れてしまいました。もし、何
|
||||
か問題があるようでしたら、ご連絡いただければ、私が自分で使っているものを公表
|
||||
するようにします。
|
||||
|
||||
このプログラムは、Shift-JIS の漢字コードを扱うようになっています。
|
||||
|
||||
EUC に対応させる場合は、正規表現の扱い等、漢字コードに関係する部分の書換が必
|
||||
要ですが、大した手間ではありません。どなたか変更された場合は、パッチを用意し
|
||||
ていただけると嬉しいです。
|
||||
|
||||
当初は、昔の awk の仕様になっていましたが、「AWK Programming Language」
|
||||
が出版され、POSIX 1003.2 の draft でも nawk 仕様が採用されたのを機会に、nawk
|
||||
の仕様に書き換えました。オリジナルの awk と違って、parser も lexical analizer
|
||||
も hand maid ですから、64K+64K のメモリに収まっています。
|
||||
|
||||
本来は、Minix らしい、教材的なプログラムにすべきですし、そうしたかっ
|
||||
たのですが、もともと、自分たちが使うために、メモもとらずにスクリーンを見なが
|
||||
ら書いてしまったため、きれいなコーディングになっていません。しかし、64K+64K
|
||||
のメモリで使える awk が他にありませんので、とりあえず現行の状態で公開しておく
|
||||
ことにしました。
|
||||
|
||||
プログラムそのものは、正規表現の評価順序に依存するものを除いて、「AWK
|
||||
Programming Language」に掲載されているテストプログラムに通ることを確認してあ
|
||||
ります。
|
||||
|
||||
|
||||
32-bit Minix の場合は、AT&T オジナルの awk とか gawk, mawk といった
|
||||
プログラムが使えますが、浮動小数点をサポートした、c386 でこのプログラムをコ
|
||||
ンパイルすることもできます。
|
||||
|
||||
平林 浩一 (kh@hiraide.mogami-wire.co.jp) 1995-01-29
|
||||
@@ -12,7 +12,7 @@ BIGFILES=#-D_FILE_OFFSET_BITS=64
|
||||
CFLAGS=-Wall -Winline -O -g $(BIGFILES) -Dlstat=stat -D_POSIX_SOURCE=1
|
||||
|
||||
# Where you want it installed when you do 'make install'
|
||||
PREFIX=/usr/local
|
||||
PREFIX=/usr
|
||||
PREFIX_BIN=$(PREFIX)/bin
|
||||
PREFIX_LIB=$(PREFIX)/lib
|
||||
PREFIX_MAN=$(PREFIX)/man
|
||||
|
||||
@@ -27,9 +27,9 @@
|
||||
|
||||
#include <minix/const.h>
|
||||
#include <minix/type.h>
|
||||
#include "../../servers/fs/const.h"
|
||||
#include "../../servers/fs/type.h"
|
||||
#include "../../servers/fs/inode.h"
|
||||
#include "../../servers/mfs/const.h"
|
||||
#include "../../servers/mfs/type.h"
|
||||
#include "../../servers/mfs/inode.h"
|
||||
|
||||
#include "de.h"
|
||||
|
||||
|
||||
@@ -18,10 +18,10 @@
|
||||
|
||||
#include <minix/const.h>
|
||||
#include <minix/type.h>
|
||||
#include "../../servers/fs/const.h"
|
||||
#include "../../servers/fs/type.h"
|
||||
#include "../../servers/fs/super.h"
|
||||
#include "../../servers/fs/inode.h"
|
||||
#include "../../servers/mfs/const.h"
|
||||
#include "../../servers/mfs/type.h"
|
||||
#include "../../servers/mfs/super.h"
|
||||
#include "../../servers/mfs/inode.h"
|
||||
#include <minix/fslib.h>
|
||||
|
||||
#include "de.h"
|
||||
|
||||
@@ -23,9 +23,9 @@
|
||||
|
||||
#include <minix/const.h>
|
||||
#include <minix/type.h>
|
||||
#include "../../servers/fs/const.h"
|
||||
#include "../../servers/fs/type.h"
|
||||
#include "../../servers/fs/inode.h"
|
||||
#include "../../servers/mfs/const.h"
|
||||
#include "../../servers/mfs/type.h"
|
||||
#include "../../servers/mfs/inode.h"
|
||||
#include <minix/fslib.h>
|
||||
|
||||
#include "de.h"
|
||||
|
||||
@@ -17,8 +17,8 @@
|
||||
|
||||
#include <minix/config.h>
|
||||
#include <minix/const.h>
|
||||
#include "../../servers/fs/const.h"
|
||||
#include "../../servers/fs/inode.h"
|
||||
#include "../../servers/mfs/const.h"
|
||||
#include "../../servers/mfs/inode.h"
|
||||
|
||||
#include "de.h"
|
||||
|
||||
|
||||
@@ -25,9 +25,9 @@
|
||||
|
||||
#include <minix/const.h>
|
||||
#include <minix/type.h>
|
||||
#include "../../servers/fs/const.h"
|
||||
#include "../../servers/fs/type.h"
|
||||
#include "../../servers/fs/inode.h"
|
||||
#include "../../servers/mfs/const.h"
|
||||
#include "../../servers/mfs/type.h"
|
||||
#include "../../servers/mfs/inode.h"
|
||||
#include <minix/fslib.h>
|
||||
|
||||
#include "de.h"
|
||||
|
||||
@@ -173,12 +173,14 @@ int opendev(network_t *np, fdtype_t fdtype, int compete)
|
||||
|
||||
switch (fdtype) {
|
||||
case FT_ETHERNET:
|
||||
/* Set NONBLOCK to avoid waiting for a device driver to become ready */
|
||||
fcntl(np->fdp->fd, F_SETFL, fcntl(np->fdp->fd, F_GETFL) | O_NONBLOCK);
|
||||
if (ioctl(np->fdp->fd, NWIOGETHSTAT, ðstat) < 0) {
|
||||
/* Not an Ethernet. */
|
||||
close(fdp->fd);
|
||||
return 0;
|
||||
}
|
||||
fcntl(np->fdp->fd, F_SETFL, fcntl(np->fdp->fd, F_GETFL) & ~O_NONBLOCK);
|
||||
np->eth= ethstat.nwes_addr;
|
||||
ethopt.nweo_flags= NWEO_COPY | NWEO_EN_LOC | NWEO_EN_BROAD
|
||||
| NWEO_REMANY | NWEO_TYPEANY | NWEO_RWDATALL;
|
||||
|
||||
@@ -8,6 +8,8 @@
|
||||
* routine is TS_INP for detection of TTY input.
|
||||
*/
|
||||
|
||||
#define _MINIX 1
|
||||
|
||||
#include "elle.h"
|
||||
|
||||
#if !(V6)
|
||||
@@ -21,6 +23,7 @@ int tsf_pause = 0; /* Set if ts_pause works. Ref'd by equit in e_main */
|
||||
#if !(SYSV || BBN) /* SYSV and BBN have weird tty calls */
|
||||
|
||||
#if MINIX
|
||||
#include <sys/ioctl.h>
|
||||
#include <termios.h>
|
||||
struct termios origterm, newterm;
|
||||
#else
|
||||
|
||||
@@ -3,7 +3,9 @@
|
||||
#endif
|
||||
|
||||
/* sbbcpy.c */
|
||||
#ifndef _MINIX
|
||||
_PROTOTYPE( int bcopy, (SBMA from, SBMA to, unsigned cnt) );
|
||||
#endif
|
||||
_PROTOTYPE( int sbm_wcpy, (int *from, int *to, unsigned cnt) );
|
||||
|
||||
/* sberr.c */
|
||||
|
||||
@@ -61,6 +61,7 @@ elvprsv: elvprsv.c
|
||||
|
||||
install: /usr/bin/elvis \
|
||||
/bin/elvis \
|
||||
/usr/bin/vi \
|
||||
/usr/bin/ctags /usr/bin/ref /usr/bin/fmt \
|
||||
/usr/bin/elvrec /usr/bin/elvprsv
|
||||
|
||||
@@ -70,6 +71,11 @@ install: /usr/bin/elvis \
|
||||
/bin/elvis: elvis
|
||||
install -cs -o bin elvis $@
|
||||
|
||||
/usr/bin/vi: /usr/bin/elvis
|
||||
if [ ! -x $@ ]; \
|
||||
then install -l $? $@ ; \
|
||||
fi
|
||||
|
||||
/usr/bin/ctags: ctags
|
||||
install -cs -o bin ctags $@
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user