xref: /inferno-os/emu/Unixware/os.c (revision 46439007cf417cbd9ac8049bb4122c890097a0fa)
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