xref: /inferno-os/emu/Unixware/os.c (revision fd7058f9a883832e948d667b63c56178e37b1e15)
1 #include	"dat.h"
2 #include	"fns.h"
3 #include	"error.h"
4 #undef _POSIX_C_SOURCE
5 #undef getwd
6 #include	<unistd.h>
7 #include	<thread.h>
8 #include	<time.h>
9 #include	<termios.h>
10 #include	<signal.h>
11 #include 	<pwd.h>
12 #include	<sys/resource.h>
13 #include	<sys/time.h>
14 
15 enum
16 {
17 	DELETE  = 0x7F
18 };
19 char *hosttype = "Unixware";
20 
21 static thread_key_t	prdakey;
22 
23 static siginfo_t siginfo;
24 
25 extern int dflag;
26 
27 Proc*
28 getup(void)
29 {
30 	void *vp;
31 
32 	if (thr_getspecific(prdakey, &vp))
33 		return nil;
34 	return vp;
35 }
36 
37 void
38 pexit(char *msg, int t)
39 {
40 	Osenv *e;
41 
42 	lock(&procs.l);
43 	if(up->prev)
44 		up->prev->next = up->next;
45 	else
46 		procs.head = up->next;
47 
48 	if(up->next)
49 		up->next->prev = up->prev;
50 	else
51 		procs.tail = up->prev;
52 	unlock(&procs.l);
53 
54 	/*print("pexit: %s: %s\n", up->text, msg);*/
55 	e = up->env;
56 	if(e != nil) {
57 		closefgrp(e->fgrp);
58 		closepgrp(e->pgrp);
59 		closeegrp(e->egrp);
60 		closesigs(e->sigs);
61 	}
62 	free(up->prog);
63 	sema_destroy(up->os);
64 	free(up->os);
65 	free(up);
66 	thr_exit(0);
67 }
68 
69 static void *
70 tramp(void *v)
71 {
72 	struct Proc *Up;
73 
74 	if(thr_setspecific(prdakey, v)) {
75 		print("set specific data failed in tramp\n");
76 		thr_exit(0);
77 	}
78 	Up = v;
79 	Up->sigid = thr_self();
80 	Up->func(Up->arg);
81 	pexit("", 0);
82 }
83 
84 void
85 kproc(char *name, void (*func)(void*), void *arg, int flags)
86 {
87 	thread_t thread;
88 	Proc *p;
89 	Pgrp *pg;
90 	Fgrp *fg;
91 	Egrp *eg;
92 	sema_t *sem;
93 
94 	p = newproc();
95 
96 	sem = malloc(sizeof(*sem));
97 	if(sem == nil)
98 		panic("can't allocate semaphore");
99 	sema_init(sem, 0, USYNC_THREAD, 0);
100 	p->os = sem;
101 
102 	if(flags & KPDUPPG) {
103 		pg = up->env->pgrp;
104 		incref(&pg->r);
105 		p->env->pgrp = pg;
106 	}
107 	if(flags & KPDUPFDG) {
108 		fg = up->env->fgrp;
109 		incref(&fg->r);
110 		p->env->fgrp = fg;
111 	}
112 	if(flags & KPDUPENVG) {
113 		eg = up->env->egrp;
114 		incref(&eg->r);
115 		p->env->egrp = eg;
116 	}
117 
118 	p->env->uid = up->env->uid;
119 	p->env->gid = up->env->gid;
120 	kstrdup(&p->env->user, up->env->user);
121 
122 	strcpy(p->text, name);
123 
124 	p->func = func;
125 	p->arg = arg;
126 
127 	lock(&procs.l);
128 	if(procs.tail != nil) {
129 		p->prev = procs.tail;
130 		procs.tail->next = p;
131 	}
132 	else {
133 		procs.head = p;
134 		p->prev = nil;
135 	}
136 	procs.tail = p;
137 	unlock(&procs.l);
138 
139 	if(thr_create(0, 0, &tramp, p, THR_BOUND|THR_DETACHED, &thread))
140 		panic("thr_create failed\n");
141 	thr_yield();
142 }
143 
144 /* to get pc on trap use siginfo.si_pc field and define all trap handlers
145 	as printILL - have to set sa_sigaction, sa_flags not sa_handler
146 */
147 
148 static void
149 trapUSR1(void)
150 {
151 	int intwait;
152 
153 	intwait = up->intwait;
154 	up->intwait = 0;	/* clear it to let proc continue in osleave */
155 
156 	if(up->type != Interp)		/* Used to unblock pending I/O */
157 		return;
158 
159 	if(intwait == 0)		/* Not posted so it's a sync error */
160 		disfault(nil, Eintr);	/* Should never happen */
161 }
162 
163 static void
164 trapILL(void)
165 {
166 	disfault(nil, "Illegal instruction");
167 }
168 
169 static void
170 printILL(int sig, siginfo_t *siginfo, void *v)
171 {
172 	panic("Illegal instruction with code=%d at address=%x, opcode=%x.\n",
173 		siginfo->si_code, siginfo->si_addr,*(char*)siginfo->si_addr);
174 }
175 
176 static void
177 trapBUS(void)
178 {
179 	disfault(nil, "Bus error");
180 }
181 
182 static void
183 trapSEGV(void)
184 {
185 	disfault(nil, "Segmentation violation");
186 }
187 
188 static void
189 trapFPE(void)
190 {
191 	disfault(nil, "Floating point exception");
192 }
193 
194 void
195 oshostintr(Proc *p)
196 {
197 	thr_kill(p->sigid, SIGUSR1);
198 }
199 
200 void
201 osblock(void)
202 {
203 	while(sema_wait(up->os))
204 		;	/* retry on signals */
205 }
206 
207 void
208 osready(Proc *p)
209 {
210 	sema_post(p->os);
211 }
212 
213 void
214 oslongjmp(void *regs, osjmpbuf env, int val)
215 {
216 	USED(regs);
217 	siglongjmp(env, val);
218 }
219 
220 static struct termios tinit;
221 
222 static void
223 termset(void)
224 {
225 	struct termios t;
226 
227 	tcgetattr(0, &t);
228 	tinit = t;
229 	t.c_lflag &= ~(ICANON|ECHO|ISIG);
230 	t.c_cc[VMIN] = 1;
231 	t.c_cc[VTIME] = 0;
232 	tcsetattr(0, TCSANOW, &t);
233 }
234 
235 static void
236 termrestore(void)
237 {
238 	tcsetattr(0, TCSANOW, &tinit);
239 }
240 
241 void
242 cleanexit(int x)
243 {
244 	USED(x);
245 
246 	if(up->intwait) {
247 		up->intwait = 0;
248 		return;
249 	}
250 
251 	if(dflag == 0)
252 		termrestore();
253 	exit(0);
254 }
255 
256 int gidnobody= -1, uidnobody= -1;
257 
258 void
259 getnobody(void)
260 {
261 	struct passwd *pwd;
262 
263 	if (pwd=getpwnam("nobody")) {
264 		uidnobody = pwd->pw_uid;
265 		gidnobody = pwd->pw_gid;
266 	}
267 }
268 
269 void
270 osreboot(char *file, char **argv)
271 {
272 	if(dflag == 0)
273 		termrestore();
274 	execvp(file, argv);
275 	panic("reboot failure");
276 }
277 
278 void
279 libinit(char *imod)
280 {
281 	struct Proc *Up;
282 	struct sigaction act;
283 	struct passwd *pw;
284 	char sys[64];
285 
286 	setsid();
287 
288 	if(dflag == 0)
289 		termset();
290 
291 	gethostname(sys, sizeof(sys));
292 	kstrdup(&ossysname, sys);
293 	getnobody();
294 
295 	memset(&act, 0 , sizeof(act));
296 	act.sa_handler=trapUSR1;
297 	sigaction(SIGUSR1, &act, nil);
298 	/*
299 	 * For the correct functioning of devcmd in the
300 	 * face of exiting slaves
301 	 */
302 	signal(SIGPIPE, SIG_IGN);
303 	if(signal(SIGTERM, SIG_IGN) != SIG_IGN)
304 		signal(SIGTERM, cleanexit);
305 	if(sflag == 0) {
306 		act.sa_handler = trapBUS;
307 		sigaction(SIGBUS, &act, nil);
308 		act.sa_handler = trapILL;
309 		sigaction(SIGILL, &act, nil);
310 		act.sa_handler = trapSEGV;
311 		sigaction(SIGSEGV, &act, nil);
312 		act.sa_handler = trapFPE;
313 		sigaction(SIGFPE, &act, nil);
314 		if(signal(SIGINT, SIG_IGN) != SIG_IGN)
315 			signal(SIGINT, cleanexit);
316 	} else{
317 		act.sa_sigaction = printILL;
318 		act.sa_flags=SA_SIGINFO;
319 		sigaction(SIGILL, &act, nil);
320 	}
321 
322 	if(thr_keycreate(&prdakey,NULL))
323 		print("keycreate failed\n");
324 
325 	Up = newproc();
326 	if(thr_setspecific(prdakey,Up))
327 		panic("set specific thread data failed\n");
328 
329 	pw = getpwuid(getuid());
330 	if(pw != nil)
331 		kstrdup(&eve, pw->pw_name);
332 	else
333 		print("cannot getpwuid\n");
334 
335 	up->env->uid = getuid();
336 	up->env->gid = getgid();
337 	emuinit(imod);
338 }
339 
340 int
341 readkbd(void)
342 {
343 	int n;
344 	char buf[1];
345 
346 	n = read(0, buf, sizeof(buf));
347 	if(n < 0)
348 		fprint(2, "keyboard read: %s\n", strerror(errno));
349 	if(n <= 0)
350 		pexit("keyboard thread", 0);
351 
352 	switch(buf[0]) {
353 	case '\r':
354 		buf[0] = '\n';
355 		break;
356 	case DELETE:
357 		cleanexit(0);
358 		break;
359 	}
360 	return buf[0];
361 }
362 
363 /*
364  * Return an abitrary millisecond clock time
365  */
366 long
367 osmillisec(void)
368 {
369 	static long sec0 = 0, usec0;
370 	struct timeval t;
371 
372 	if(gettimeofday(&t, NULL)<0)
373 		return(0);
374 	if(sec0==0){
375 		sec0 = t.tv_sec;
376 		usec0 = t.tv_usec;
377 	}
378 	return((t.tv_sec-sec0)*1000+(t.tv_usec-usec0+500)/1000);
379 }
380 
381 /*
382  * Return the time since the epoch in microseconds
383  * The epoch is defined at 1 Jan 1970
384  */
385 vlong
386 osnsec(void)
387 {
388 	struct timeval t;
389 
390 	gettimeofday(&t, nil);
391 	return (vlong)t.tv_sec*1000000000L + t.tv_usec*1000;
392 }
393 
394 vlong
395 osusectime(void)
396 {
397 	struct timeval t;
398 
399 	gettimeofday(&t, nil);
400 	return (vlong)t.tv_sec * 1000000 + t.tv_usec;
401 }
402 
403 int
404 osmillisleep(ulong milsec)
405 {
406 	struct  timespec time;
407 
408 	time.tv_sec = milsec/1000;
409 	time.tv_nsec= (milsec%1000)*1000000;
410 	nanosleep(&time,nil);
411 	return 0;
412 }
413 
414 int
415 limbosleep(ulong milsec)
416 {
417 	return osmillisleep(milsec);
418 }
419 
420 void
421 osyield(void)
422 {
423 	thr_yield();
424 }
425 
426 void
427 ospause(void)
428 {
429 	for(;;)
430 		pause();
431 }
432 
433 void
434 oslopri(void)
435 {
436 	setpriority(PRIO_PROCESS, 0, getpriority(PRIO_PROCESS,0)+4);
437 }
438