xref: /inferno-os/emu/Unixware/os.c (revision b43c1ca5eb5fc65b93ae935a568432712797b049)
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 int
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 	return(thread);
143 }
144 
145 /* to get pc on trap use siginfo.si_pc field and define all trap handlers
146 	as printILL - have to set sa_sigaction, sa_flags not sa_handler
147 */
148 
149 static void
150 trapUSR1(void)
151 {
152 	int intwait;
153 
154 	intwait = up->intwait;
155 	up->intwait = 0;	/* clear it to let proc continue in osleave */
156 
157 	if(up->type != Interp)		/* Used to unblock pending I/O */
158 		return;
159 
160 	if(intwait == 0)		/* Not posted so it's a sync error */
161 		disfault(nil, Eintr);	/* Should never happen */
162 }
163 
164 static void
165 trapILL(void)
166 {
167 	disfault(nil, "Illegal instruction");
168 }
169 
170 static void
171 printILL(int sig, siginfo_t *siginfo, void *v)
172 {
173 	panic("Illegal instruction with code=%d at address=%x, opcode=%x.\n",
174 		siginfo->si_code, siginfo->si_addr,*(char*)siginfo->si_addr);
175 }
176 
177 static void
178 trapBUS(void)
179 {
180 	disfault(nil, "Bus error");
181 }
182 
183 static void
184 trapSEGV(void)
185 {
186 	disfault(nil, "Segmentation violation");
187 }
188 
189 static void
190 trapFPE(void)
191 {
192 	disfault(nil, "Floating point exception");
193 }
194 
195 void
196 oshostintr(Proc *p)
197 {
198 	thr_kill(p->sigid, SIGUSR1);
199 }
200 
201 void
202 osblock(void)
203 {
204 	while(sema_wait(up->os))
205 		;	/* retry on signals */
206 }
207 
208 void
209 osready(Proc *p)
210 {
211 	sema_post(p->os);
212 }
213 
214 void
215 oslongjmp(void *regs, osjmpbuf env, int val)
216 {
217 	USED(regs);
218 	siglongjmp(env, val);
219 }
220 
221 static struct termios tinit;
222 
223 static void
224 termset(void)
225 {
226 	struct termios t;
227 
228 	tcgetattr(0, &t);
229 	tinit = t;
230 	t.c_lflag &= ~(ICANON|ECHO|ISIG);
231 	t.c_cc[VMIN] = 1;
232 	t.c_cc[VTIME] = 0;
233 	tcsetattr(0, TCSANOW, &t);
234 }
235 
236 static void
237 termrestore(void)
238 {
239 	tcsetattr(0, TCSANOW, &tinit);
240 }
241 
242 void
243 cleanexit(int x)
244 {
245 	USED(x);
246 
247 	if(up->intwait) {
248 		up->intwait = 0;
249 		return;
250 	}
251 
252 	if(dflag == 0)
253 		termrestore();
254 	exit(0);
255 }
256 
257 int gidnobody= -1, uidnobody= -1;
258 
259 void
260 getnobody(void)
261 {
262 	struct passwd *pwd;
263 
264 	if (pwd=getpwnam("nobody")) {
265 		uidnobody = pwd->pw_uid;
266 		gidnobody = pwd->pw_gid;
267 	}
268 }
269 
270 void
271 osreboot(char *file, char **argv)
272 {
273 	if(dflag == 0)
274 		termrestore();
275 	execvp(file, argv);
276 	panic("reboot failure");
277 }
278 
279 void
280 libinit(char *imod)
281 {
282 	struct Proc *Up;
283 	struct sigaction act;
284 	struct passwd *pw;
285 	char sys[64];
286 
287 	setsid();
288 
289 	if(dflag == 0)
290 		termset();
291 
292 	gethostname(sys, sizeof(sys));
293 	kstrdup(&ossysname, sys);
294 	getnobody();
295 
296 	memset(&act, 0 , sizeof(act));
297 	act.sa_handler=trapUSR1;
298 	sigaction(SIGUSR1, &act, nil);
299 	/*
300 	 * For the correct functioning of devcmd in the
301 	 * face of exiting slaves
302 	 */
303 	signal(SIGPIPE, SIG_IGN);
304 	if(signal(SIGTERM, SIG_IGN) != SIG_IGN)
305 		signal(SIGTERM, cleanexit);
306 	if(sflag == 0) {
307 		act.sa_handler = trapBUS;
308 		sigaction(SIGBUS, &act, nil);
309 		act.sa_handler = trapILL;
310 		sigaction(SIGILL, &act, nil);
311 		act.sa_handler = trapSEGV;
312 		sigaction(SIGSEGV, &act, nil);
313 		act.sa_handler = trapFPE;
314 		sigaction(SIGFPE, &act, nil);
315 		if(signal(SIGINT, SIG_IGN) != SIG_IGN)
316 			signal(SIGINT, cleanexit);
317 	} else{
318 		act.sa_sigaction = printILL;
319 		act.sa_flags=SA_SIGINFO;
320 		sigaction(SIGILL, &act, nil);
321 	}
322 
323 	if(thr_keycreate(&prdakey,NULL))
324 		print("keycreate failed\n");
325 
326 	Up = newproc();
327 	if(thr_setspecific(prdakey,Up))
328 		panic("set specific thread data failed\n");
329 
330 	pw = getpwuid(getuid());
331 	if(pw != nil)
332 		kstrdup(&eve, pw->pw_name);
333 	else
334 		print("cannot getpwuid\n");
335 
336 	up->env->uid = getuid();
337 	up->env->gid = getgid();
338 	emuinit(imod);
339 }
340 
341 int
342 readkbd(void)
343 {
344 	int n;
345 	char buf[1];
346 
347 	n = read(0, buf, sizeof(buf));
348 	if(n < 0)
349 		fprint(2, "keyboard read: %s\n", strerror(errno));
350 	if(n <= 0)
351 		pexit("keyboard thread", 0);
352 
353 	switch(buf[0]) {
354 	case '\r':
355 		buf[0] = '\n';
356 		break;
357 	case DELETE:
358 		cleanexit(0);
359 		break;
360 	}
361 	return buf[0];
362 }
363 
364 /*
365  * Return an abitrary millisecond clock time
366  */
367 long
368 osmillisec(void)
369 {
370 	static long sec0 = 0, usec0;
371 	struct timeval t;
372 
373 	if(gettimeofday(&t, NULL)<0)
374 		return(0);
375 	if(sec0==0){
376 		sec0 = t.tv_sec;
377 		usec0 = t.tv_usec;
378 	}
379 	return((t.tv_sec-sec0)*1000+(t.tv_usec-usec0+500)/1000);
380 }
381 
382 /*
383  * Return the time since the epoch in microseconds
384  * The epoch is defined at 1 Jan 1970
385  */
386 vlong
387 osnsec(void)
388 {
389 	struct timeval t;
390 
391 	gettimeofday(&t, nil);
392 	return (vlong)t.tv_sec*1000000000L + t.tv_usec*1000;
393 }
394 
395 vlong
396 osusectime(void)
397 {
398 	struct timeval t;
399 
400 	gettimeofday(&t, nil);
401 	return (vlong)t.tv_sec * 1000000 + t.tv_usec;
402 }
403 
404 int
405 osmillisleep(ulong milsec)
406 {
407 	struct  timespec time;
408 
409 	time.tv_sec = milsec/1000;
410 	time.tv_nsec= (milsec%1000)*1000000;
411 	nanosleep(&time,nil);
412 	return 0;
413 }
414 
415 int
416 limbosleep(ulong milsec)
417 {
418 	return osmillisleep(milsec);
419 }
420 
421 void
422 osyield(void)
423 {
424 	thr_yield();
425 }
426 
427 void
428 ospause(void)
429 {
430 	for(;;)
431 		pause();
432 }
433 
434 void
435 oslopri(void)
436 {
437 	setpriority(PRIO_PROCESS, 0, getpriority(PRIO_PROCESS,0)+4);
438 }
439