1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
|
/* vi: set sw=4 ts=4:
*
* toysh - toybox shell
*
* Copyright 2006 Rob Landley <rob@landley.net>
*
* The spec for this is at:
* http://www.opengroup.org/onlinepubs/009695399/utilities/xcu_chap02.html
*
* Although things like the bash man page are good to read too.
*/
// Handle embedded NUL bytes in the command line.
#include "toys.h"
static int handle(char *command)
{
int argc = 0, status;
char *argv[10], *start = command;
pid_t pid;
struct toy_list *tl;
// Parse command into argv[]
for (;;) {
char *end;
// Skip leading whitespace and detect EOL.
while(isspace(*start)) start++;
if (!*start || *start=='#') break;
// Grab next word. (Add dequote and envvar logic here)
end = start;
while (*end && !isspace(*end)) end++;
argv[argc++] = xstrndup(start, end-start);
start=end;
}
argv[argc]=0;
if (!argc) return 0;
tl = toy_find(argv[0]);
// This is a bit awkward, next design cycle should clean it up.
// Should vfork(), move to tryspawn()?
pid = 0;
if (tl && (tl->flags & TOYFLAG_NOFORK))
status = tl->toy_main();
else {
pid=fork();
if(!pid) {
toy_exec(argv);
xexec(argv);
} else waitpid(pid, &status, 0);
}
while(argc) free(argv[--argc]);
return 0;
}
int cd_main(void)
{
char *dest = toys.argc>1 ? toys.argv[1] : getenv("HOME");
if (chdir(dest)) error_exit("chdir %s",dest);
return 0;
}
int exit_main(void)
{
exit(toys.argc>1 ? atoi(toys.argv[1]) : 0);
}
int toysh_main(void)
{
char *command=NULL;
FILE *f;
// TODO get_optflags(argv, "c:", &command);
f = toys.argv[1] ? xfopen(toys.argv[1], "r") : NULL;
if (command) handle(command);
else {
unsigned cmdlen=0;
for (;;) {
if (!f) putchar('$');
if (1 > getline(&command, &cmdlen, f ? : stdin)) break;
handle(command);
}
if (CFG_TOYS_FREE) free(command);
}
return 1;
}
|