cae36a52 |
1 | #include <u.h> |
2 | #include <libc.h> |
3 | #include <tos.h> |
4 | #include <ureg.h> |
5 | #include "dat.h" |
6 | #include "fns.h" |
7 | #include "linux.h" |
8 | |
9 | static void |
10 | die(void) |
11 | { |
12 | exits(nil); |
13 | } |
14 | |
15 | static char** |
16 | readenv(void) |
17 | { |
18 | char **env; |
19 | int fd, n, i, c; |
20 | Dir *d; |
21 | |
22 | if((fd = open("/env", OREAD)) < 0) |
23 | return nil; |
24 | n = dirreadall(fd, &d); |
25 | close(fd); |
26 | env = kmalloc(sizeof(env[0]) * (n + 1)); |
27 | c = 0; |
28 | for(i=0; i<n; i++){ |
29 | char *v; |
30 | char *k; |
31 | |
32 | k = d[i].name; |
33 | |
34 | // filter out some stuff... |
35 | if(strncmp(k, "fn#", 3) == 0) |
36 | continue; |
37 | if(strcmp(k, "timezone") == 0) |
38 | continue; |
39 | if(strcmp(k, "0")==0) |
40 | continue; |
41 | |
42 | if((v = getenv(d[i].name)) == nil) |
43 | continue; |
44 | if((env[c] = ksmprint("%s=%s", k, v)) == nil) |
45 | continue; |
46 | free(v); |
47 | |
48 | c++; |
49 | } |
50 | env[c] = 0; |
51 | |
52 | free(d); |
53 | |
54 | return env; |
55 | } |
56 | |
57 | struct onstackargs |
58 | { |
59 | long *stk; |
60 | void *arg; |
61 | int (*func)(void *); |
62 | int ret; |
63 | jmp_buf jmp; |
64 | }; |
65 | |
66 | int |
67 | onstack(long *stk, int (*func)(void *), void *arg) |
68 | { |
69 | struct onstackargs a, *args; |
70 | jmp_buf jmp; |
71 | long *sp; |
72 | |
73 | sp = (long*)&a; |
74 | if((long*)sp >= stk && (long*)sp < stk+(KSTACK / sizeof(long))) |
75 | return func(arg); |
76 | |
77 | if(args = (struct onstackargs*)setjmp(jmp)){ |
78 | args->ret = onstack(args->stk, args->func, args->arg); |
79 | longjmp(args->jmp, 1); |
80 | } |
81 | |
82 | sp = &stk[(KSTACK / sizeof(long))-16]; |
83 | jmp[JMPBUFSP] = (long)sp; |
84 | |
85 | memset(stk, 0, KSTACK); |
86 | |
87 | args = &a; |
88 | args->stk = stk; |
89 | args->func = func; |
90 | args->arg = arg; |
91 | |
92 | if(!setjmp(args->jmp)) |
93 | longjmp(jmp, (int)args); |
94 | |
95 | return args->ret; |
96 | } |
97 | |
98 | #pragma profile off |
99 | |
100 | static void |
101 | proff(void (*fn)(void*), void *arg) |
102 | { |
103 | if(_tos->prof.what == 0){ |
104 | fn(arg); |
105 | }else{ |
106 | prof(fn, arg, 2000, _tos->prof.what); |
107 | } |
108 | } |
109 | |
110 | static void |
111 | profexitjmpfn(void *arg) |
112 | { |
113 | /* |
114 | * we are now called by the profiling function on the profstack. |
115 | * save the current continuation so we can return here on exit. |
116 | */ |
117 | if(!setjmp(exitjmp)) |
118 | longjmp((long*)arg, 1); /* return from profme() */ |
119 | } |
120 | |
121 | static int |
122 | profmeprofstack(void *arg) |
123 | { |
124 | proff(profexitjmpfn, arg); |
125 | for(;;) die(); |
126 | } |
127 | |
128 | #pragma profile on |
129 | |
130 | static long *profstack; |
131 | |
132 | void |
133 | profme(void) |
134 | { |
135 | jmp_buf j; |
136 | |
137 | if(!setjmp(j)) |
138 | onstack(profstack, profmeprofstack, j); |
139 | } |
140 | |
141 | |
142 | static void |
143 | vpanic(char *msg, va_list arg) |
144 | { |
145 | char buf[32]; |
146 | int fd; |
147 | |
148 | fprint(2, "PANIC: "); |
149 | vfprint(2, msg, arg); |
150 | fprint(2, "\n"); |
151 | |
152 | if(debug) |
153 | abort(); |
154 | |
155 | snprint(buf, sizeof(buf), "/proc/%d/notepg", getpid()); |
156 | if((fd = open(buf, OWRITE)) >= 0){ |
157 | write(fd, "kill", 4); |
158 | close(fd); |
159 | } |
160 | exits("panic"); |
161 | } |
162 | |
163 | void |
164 | panic(char *msg, ...) |
165 | { |
166 | va_list arg; |
167 | |
168 | va_start(arg, msg); |
169 | vpanic(msg, arg); |
170 | va_end(arg); |
171 | } |
172 | |
173 | void usage(void) |
174 | { |
175 | fprint(2, "usage: linuxemu [-d] [-u uid] [-g gid] cmd [args]\n"); |
176 | exits("usage"); |
177 | } |
178 | |
179 | struct mainstack |
180 | { |
181 | long profstack[KSTACK / sizeof(long)]; |
182 | long kstack[KSTACK / sizeof(long)]; |
183 | Uproc *proc; |
184 | jmp_buf exitjmp; |
185 | }; |
186 | |
187 | void main(int argc, char *argv[]) |
188 | { |
189 | struct mainstack ms; |
190 | int err; |
191 | int uid, gid; |
192 | int fd; |
193 | |
194 | fmtinstall('E', Efmt); |
195 | fmtinstall('S', Sfmt); |
196 | |
197 | uid = 0; |
198 | gid = 0; |
199 | debug = 0; |
200 | |
201 | ARGBEGIN { |
202 | case 'd': |
203 | debug++; |
204 | break; |
205 | case 'u': |
206 | uid = atoi(EARGF(usage())); |
207 | break; |
208 | case 'g': |
209 | gid = atoi(EARGF(usage())); |
210 | break; |
211 | default: |
212 | usage(); |
213 | } ARGEND |
214 | |
215 | if(argc < 1) |
216 | usage(); |
217 | |
218 | rootdevinit(); |
219 | procdevinit(); |
220 | ptydevinit(); |
221 | consdevinit(); |
222 | dspdevinit(); |
223 | miscdevinit(); |
224 | sockdevinit(); |
225 | pipedevinit(); |
226 | |
227 | kstack = ms.kstack; |
228 | profstack = ms.profstack; |
229 | exitjmp = ms.exitjmp; |
230 | pcurrent = &ms.proc; |
231 | current = nil; |
232 | |
233 | if(setjmp(exitjmp)) |
234 | die(); |
235 | |
236 | initproc(); |
237 | current->uid = uid; |
238 | current->gid = gid; |
239 | |
240 | /* emulated console */ |
241 | sys_close(0); |
242 | if((fd = sys_open("/dev/cons", O_RDWR, 0)) != 0) |
243 | fprint(2, "cant open console for stdin\n"); |
244 | sys_close(1); |
245 | if(sys_dup(fd) != 1) |
246 | fprint(2, "cant dup stdout\n"); |
247 | sys_close(2); |
248 | if(sys_dup(fd) != 2) |
249 | fprint(2, "cant dup stderr\n"); |
250 | |
251 | sys_fcntl(0, F_SETFD, 0); |
252 | sys_fcntl(1, F_SETFD, 0); |
253 | sys_fcntl(2, F_SETFD, 0); |
254 | |
255 | err = sys_execve(*argv, argv, readenv()); |
256 | |
257 | fprint(2, "%s: %E\n", *argv, err); |
258 | longjmp(exitjmp, 1); |
259 | } |