add linux_emul base, reorganize docs
[openbsd_emul.git] / linux_emul_base / main.c
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 }