aboutsummaryrefslogtreecommitdiff
path: root/toys/toysh.c
blob: 77db82db8073b01aa3bc63fe9bdcbe053aad9ea0 (plain)
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;
}