|
|
1.1 root 1: /* (lgl-
2: * The information contained herein is a trade secret of Mark Williams
3: * Company, and is confidential information. It is provided under a
4: * license agreement, and may be copied or disclosed only under the
5: * terms of that agreement. Any reproduction or disclosure of this
6: * material without the express written authorization of Mark Williams
7: * Company or persuant to the license agreement is unlawful.
8: *
9: * COHERENT Version 2.3.37
10: * Copyright (c) 1982, 1983, 1984.
11: * An unpublished work by Mark Williams Company, Chicago.
12: * All rights reserved.
13: -lgl) */
14: /*
15: * coh.386/sys1.c
16: *
17: * Coherent.
18: * General system calls.
19: *
20: * Revised: Tue May 11 11:12:03 1993 CDT
21: */
22: #include <sys/coherent.h>
23: #include <sys/acct.h>
24: #include <sys/con.h>
25: #include <sys/wait.h>
26: #include <errno.h>
27: #include <sys/proc.h>
28: #include <sys/sched.h>
29: #include <sys/seg.h>
30: #include <sys/stat.h>
31: #include <signal.h>
32: #include <sys/times.h>
33:
34: /*
35: * Send alarm signal to specified process - function timed by ualarm()
36: */
37: sigalrm(pp)
38: register PROC * pp;
39: {
40: sendsig(SIGALRM, pp);
41: }
42:
43: /*
44: * Send a SIGALARM signal in `n' seconds.
45: */
46: ualarm(n)
47: unsigned n;
48: {
49: register PROC * pp = SELF;
50: register unsigned s;
51:
52: /*
53: * Calculate time left before current alarm timeout.
54: */
55: s = 0;
56: if (pp->p_alrmtim.t_last != NULL)
57: s = (pp->p_alrmtim.t_lbolt - lbolt + HZ - 1) / HZ;
58:
59: /*
60: * Cancel previous alarm [if any], start new alarm [if n != 0].
61: */
62: timeout2(&pp->p_alrmtim, (long) n * HZ, sigalrm, pp);
63:
64: /*
65: * Return time left before previous alarm timeout.
66: */
67: return(s);
68: }
69:
70:
71: /*
72: * Change the size of our data segment.
73: */
74: char *
75: ubrk(cp)
76: caddr_t cp;
77: {
78: register SEG *sp;
79: register caddr_t sb;
80: register SR *stack_sr;
81: caddr_t top_of_stack;
82:
83: T_HAL(0x8000, printf("%s:ubrk(%x) ", u.u_comm, cp));
84:
85: /*
86: * Pick up the segment handle for our data segment.
87: */
88: sp = SELF->p_segp[SIPDATA];
89:
90: /*
91: * Extract the starting virtual address for our data segment,
92: * as it is currently mapped into the memory space.
93: */
94: sb = u.u_segl[SIPDATA].sr_base;
95:
96: /*
97: * We can not move the top of the data segment below the
98: * start of the data segment.
99: */
100: if (cp < sb) {
101: SET_U_ERROR(ENOMEM,
102: "Requested brk address is below start of data segment.");
103: return 0;
104: }
105:
106: /*
107: * Would the request cause a collision with the stack segment?
108: *
109: * Since the stack grows downward, its top is below its base :-).
110: */
111: stack_sr = &u.u_segl[SISTACK];
112: top_of_stack = (stack_sr->sr_base) - (stack_sr->sr_size);
113:
114: if (btoc(cp) >= btoc(top_of_stack)) {
115: SET_U_ERROR(ENOMEM,
116: "Requested brk address would collide with stack segment.");
117: return 0;
118: }
119:
120: /*
121: * Attempt to establish the segment with the newly requested size.
122: */
123: segsize(sp, (cp - sb));
124:
125: /*
126: * Be sure to return the true new top of data segment.
127: */
128: sb += sp->s_size;
129:
130: T_HAL(0x8000, printf("=%x ", sb));
131: return sb;
132: }
133:
134: /*
135: * Execute a l.out.
136: */
137: uexece(np, argp, envp)
138: char *np;
139: char *argp[];
140: char *envp[];
141: {
142: pexece(np, argp, envp);
143: }
144:
145: /*
146: * Exit.
147: */
148: uexit(s)
149: {
150: pexit(s<<8);
151: }
152:
153: /*
154: * Fork.
155: */
156: ufork()
157: {
158: return (pfork());
159: }
160:
161: /*
162: * Get group id.
163: * Get effective group id.
164: */
165: ugetgid()
166: {
167: u.u_rval2 = u.u_gid;
168: return u.u_rgid;
169: }
170:
171: /*
172: * Get user id.
173: * Get effective user id.
174: */
175: ugetuid()
176: {
177: u.u_rval2 = u.u_uid;
178: return u.u_ruid;
179: }
180:
181: /*
182: * Get process group.
183: * Set the process group.
184: *
185: * This is System V type setpgrp().
186: * Set process group equal to process id (make process its own group leader).
187: * If process was NOT already a group leader, lose its controlling terminal.
188: */
189: upgrp(fl)
190: {
191: register PROC * pp = SELF;
192:
193: if (fl) {
194: if (pp->p_group != pp->p_pid)
195: pp->p_ttdev = NODEV;
196: pp->p_group = pp->p_pid;
197: }
198: return pp->p_group;
199: }
200:
201: /*
202: * Get process id.
203: */
204: ugetpid()
205: {
206: register PROC *pp = SELF;
207:
208: u.u_rval2 = pp->p_ppid;
209: return pp->p_pid;
210: }
211:
212: /*
213: * Send the signal `sig' to the process with id `pid'.
214: */
215: ukill(pid, sig)
216: int pid;
217: register unsigned sig;
218: {
219: register PROC *pp;
220: register int sigflag;
221:
222: if (sig > NSIG) {
223: u.u_error = EINVAL;
224: return;
225: }
226: sigflag = 0;
227: lock(pnxgate);
228: if (pid > 0) { /* send to matching process */
229: for (pp=procq.p_nforw; pp != &procq; pp=pp->p_nforw) {
230: if (pp->p_state == PSDEAD)
231: continue;
232: if (pp->p_pid == pid) {
233: sigflag = 1;
234: if (sig) {
235: if (sigperm(sig, pp))
236: sendsig(sig, pp);
237: else
238: u.u_error = EPERM;
239: }
240: break;
241: }
242: }
243: }
244: else if (pid < -1) {
245: pid = -pid;
246: for (pp=procq.p_nforw; pp != &procq; pp=pp->p_nforw) {
247: if (pp->p_state == PSDEAD)
248: continue;
249: if (pp->p_group == pid) {
250: sigflag = 1;
251: if (sig) {
252: if (sigperm(sig, pp))
253: sendsig(sig,pp);
254: else
255: u.u_error = EPERM;
256: }
257: }
258: }
259: }
260: else if (pid == 0) {
261: for (pp=procq.p_nforw; pp != &procq; pp=pp->p_nforw) {
262: if (pp->p_state == PSDEAD)
263: continue;
264: if (pp->p_group == SELF->p_group) {
265: sigflag = 1;
266: if (sig && sigperm(sig, pp))
267: sendsig(sig, pp);
268: }
269: }
270: }
271: else if (pid == -1) {
272: for (pp=procq.p_nforw; pp != &procq; pp=pp->p_nforw) {
273: if (pp->p_state == PSDEAD)
274: continue;
275: if (pp->p_pid == 0)
276: continue;
277: if (pp->p_pid == 1)
278: continue;
279: if (pp->p_flags & PFKERN)
280: continue;
281: sigflag = 1;
282: if (sig && super())
283: sendsig(sig, pp);
284: }
285: }
286: unlock(pnxgate);
287: if (sigflag == 0)
288: u.u_error = ESRCH;
289: return 0;
290: }
291:
292: /*
293: * See if we have permission to send the signal, `sig' to the process, `pp'.
294: */
295: sigperm(sig, pp)
296: register PROC *pp;
297: {
298: if (u.u_uid == pp->p_uid)
299: return (1);
300: if (u.u_ruid == pp->p_ruid) {
301: if (sig == SIGHUP
302: || sig == SIGINT
303: || sig == SIGQUIT
304: || sig == SIGTERM)
305: return (1);
306: }
307: if (u.u_uid == 0) {
308: u.u_flag |= ASU;
309: return (1);
310: }
311: return 0;
312: }
313:
314: /*
315: * Lock a process in core.
316: */
317: ulock(f)
318: {
319: if (super() == 0)
320: return;
321: if (f)
322: SELF->p_flags |= PFLOCK;
323: else
324: SELF->p_flags &= ~PFLOCK;
325: return 0;
326: }
327:
328: /*
329: * Change priority by the given increment.
330: */
331: unice(n)
332: register int n;
333: {
334: n += SELF->p_nice;
335: if (n < MINNICE)
336: n = MINNICE;
337: if (n > MAXNICE)
338: n = MAXNICE;
339: if (n<SELF->p_nice && super()==0)
340: return;
341: SELF->p_nice = n;
342: return 0;
343: }
344:
345: /*
346: * Non existant system call.
347: */
348: unone()
349: {
350: u.u_error = EFAULT;
351: }
352:
353: /*
354: * Null system call.
355: */
356: unull()
357: {
358: }
359:
360: /*
361: * Pause. Go to sleep on a channel that nobody will wakeup so that only
362: * signals will wake us up.
363: */
364: upause()
365: {
366: x_sleep((char *)&u, prilo, slpriSigLjmp, "pause");
367: }
368:
369: /*
370: * Start/stop profiling.
371: *
372: * buff: address in user data of an array of shorts
373: * bufsiz: number of bytes in the area at buff
374: * offset: address in user text of start of profiling area
375: * scale: 0 or 1 - turn off profiling
376: * other - treat as 16 bit scale factor
377: *
378: * For purposes of compatibility with System 5, scale values work as follows:
379: * 0xFFFF profile buffer is same length as text being profiled.
380: * 0x7FFF profile buffer is half as long as text being profiled.
381: * 0x4000 profile buffer is one fourth as long as text profiled.
382: * (each short in the buffer covers 8 bytes of text)
383: * ... ...
384: * 0x0002 each short in the buffer covers 64K bytes of text.
385: *
386: * Values 0xFFFF and 0x7FFF are used, for historical reasons, when 0x10000
387: * and 0x8000, respectively, should be used. To clean up the ensuing
388: * arithmetic, there is an upward rounding kluge below.
389: *
390: * Each clock interrupt, take (pc - offset) * scale * (2**-16) as a byte
391: * offset into pbase. Add 1 to the short at or below the given address
392: * when profiling.
393: */
394: uprofil(buff, bufsiz, offset, scale)
395: short * buff;
396: int bufsiz, offset, scale;
397: {
398: u.u_pbase = buff;
399: u.u_pbend = buff + bufsiz;
400: u.u_pofft = offset;
401: u.u_pscale = scale & 0xffff; /* scale is really unsigned short */
402:
403: /* round up kluge - see above */
404: if ((scale & 0xfff) == 0xfff)
405: u.u_pscale++;
406: }
407:
408: /*
409: * Process trace.
410: */
411: uptrace(req, pid, add, data)
412: int *add;
413: {
414: int ret;
415:
416: #ifdef TRACER
417: int readChild = 0; /* for debug, true if reading child memory */
418:
419: if (t_hal & 0x10000) {
420: switch(req) {
421: case 0: /* init called by child */
422: printf("PSetup: child=%d ", SELF->p_pid);
423: break;
424: case 1: /* parent reads child text */
425: printf("PRdT: add=%x ", add);
426: readChild = 1;
427: break;
428: case 2: /* parent reads child data */
429: printf("PRdD: add=%x ", add);
430: readChild = 1;
431: break;
432: case 3: /* parent reads child u area */
433: printf("PRdU: add=%x ", add);
434: readChild = 1;
435: break;
436: case 4: /* parent writes child text */
437: printf("PWrT: add=%x data=%x ", add, data);
438: break;
439: case 5: /* parent writes child data */
440: printf("PWrD: add=%x data=%x ", add, data);
441: break;
442: case 6: /* parent writes child u area */
443: printf("PWrU: add=%x data=%x ", add, data);
444: break;
445: case 7: /* resume child, maybe fake signal to child */
446: printf("PResume: sig=%d ", data);
447: break;
448: case 8: /* terminate child */
449: printf("PTerm: pid=%d ", pid);
450: break;
451: case 9: /* single-step child, maybe fake signal to child */
452: printf("PSStp: sig=%d ", data);
453: break;
454: }
455: }
456: #endif
457:
458: if (req == 0) {
459: SELF->p_flags |= PFTRAC;
460: ret = 0;
461: } else
462: ret = ptset(req, pid, add, data);
463:
464: #ifdef TRACER
465: if (t_hal & 0x10000) {
466: if (readChild)
467: printf("data=%x ", ret);
468: }
469: #endif
470:
471: return ret;
472: }
473:
474: /*
475: * Set group id.
476: *
477: * As in SVID issue 2:
478: *
479: * if effective gid is superuser
480: * set real, effective, and saved effective gid to argument "gid"
481: * else if real gid is same as "gid"
482: * set effective gid to "gid"
483: * else if saved effective gid is same as "gid"
484: * set effective gid to "gid"
485: */
486: usetgid(gid)
487: register int gid;
488: {
489: if (super()) {
490: u.u_gid = u.u_rgid = u.u_egid = gid;
491: SELF->p_rgid = gid;
492: } else {
493: u.u_error = 0; /* super() sets u_error when it fails */
494: if (u.u_rgid == gid || u.u_egid == gid) {
495: u.u_gid = gid;
496: } else {
497: SET_U_ERROR(EPERM, "Illegal gid");
498: }
499: }
500: return 0;
501: }
502:
503: /*
504: * Set user id.
505: *
506: * As in SVID issue 2:
507: *
508: * if effective uid is superuser
509: * set real, effective, and saved effective uid to argument "uid"
510: * else if real uid is same as "uid"
511: * set effective uid to "uid"
512: * else if saved effective uid is same as "uid"
513: * set effective uid to "uid"
514: */
515: usetuid(uid)
516: register int uid;
517: {
518: if (super()) {
519: u.u_uid = u.u_ruid = u.u_euid = uid;
520: SELF->p_uid = SELF->p_ruid = uid;
521: } else {
522: u.u_error = 0; /* super() sets u_error when it fails */
523: if (u.u_ruid == uid || u.u_euid == uid) {
524: SELF->p_uid = u.u_uid = uid;
525: } else {
526: SET_U_ERROR(EPERM, "Illegal uid");
527: }
528: }
529: return 0;
530: }
531:
532: /*
533: * Load a device driver.
534: */
535: usload(np)
536: char *np;
537: {
538: return pload(np);
539: }
540:
541: /*
542: * Set time and date.
543: *
544: * Unlike the libc interface, this routine expects a time_t value
545: * as an arg, not a time_t pointer.
546: */
547: ustime(tp)
548: time_t tp;
549: {
550: register int s;
551:
552: if (super() == 0) {
553: return;
554: }
555: s = sphi();
556: ukcopy(&tp, &timer.t_time, sizeof(tp));
557: spl(s);
558: return 0;
559: }
560:
561: /*
562: * Return process times.
563: */
564: utimes(tp)
565: struct tms *tp;
566: {
567: register PROC *pp;
568: struct tms tbuffer;
569:
570: if (tp) {
571: pp = SELF;
572: tbuffer.tms_utime = pp->p_utime;
573: tbuffer.tms_stime = pp->p_stime;
574: tbuffer.tms_cutime = pp->p_cutime;
575: tbuffer.tms_cstime = pp->p_cstime;
576: kucopyS(&tbuffer, tp, sizeof(tbuffer));
577: }
578: return lbolt;
579: }
580:
581: /*
582: * Unload a device driver.
583: */
584: usuload(m)
585: register int m;
586: {
587: if (super() == 0)
588: return;
589: puload(m);
590: return 0;
591: }
592:
593: /*
594: * Wait for a child to terminate.
595: *
596: * iBCS2 says the same system call number is wait() and waitpid(), the
597: * distinction being in how the psw is set on entry.
598: *
599: * iBCS2 fails to mention that when wait() or waitpid() report status
600: * by writing into the pointer supplied, the status is put into %edx by
601: * the kernel, and moved from there into user space by the function in
602: * libc.a. uwait() and uwaitpid() specify a value for %edx by writing
603: * to u.u_rval2.
604: *
605: * Do wait() unless (ZF|PF|SF|OF) (=WPMASK) are set in psw.
606: */
607: #define WPMASK 0x8C4
608:
609: uwait(arg1, arg2, arg3)
610: {
611: register PROC *pp;
612: register PROC *ppp;
613: register PROC *cpp;
614: register int pid;
615:
616: if ((u.u_regl[EFL] & WPMASK) == WPMASK)
617: return uwaitpid(arg1, arg2, arg3);
618:
619: /* Wait for a child to stop or die. */
620: T_HAL(8, printf("[%d]waits ", SELF->p_pid));
621: ppp = SELF;
622: for (;;) {
623: int x_s;
624:
625: /* Look at all processes. */
626: lock(pnxgate);
627: cpp = NULL;
628: pp = &procq;
629: while ((pp=pp->p_nforw) != &procq) {
630:
631: /* Ignore the current process. */
632: if (pp == ppp)
633: continue;
634: /*
635: * Ignore processes that aren't children of the
636: * current one.
637: */
638: if (pp->p_ppid != ppp->p_pid)
639: continue;
640: if (pp->p_flags&PFSTOP)
641: continue;
642:
643: /* Here is a child that hit a breakpoint. */
644: if (pp->p_flags&PFWAIT) {
645: int work; /* virtual click number */
646: int childUseg; /* system global addr */
647: UPROC * uprc;
648: SEG * sp;
649:
650: pp->p_flags &= ~PFWAIT;
651: pp->p_flags |= PFSTOP;
652:
653: /* fetch u.u_signo from the child */
654:
655: /* Find u area for child process pp */
656: sp = pp->p_segp[SIUSERP];
657: childUseg = MAPIO(sp->s_vmem, U_OFFSET);
658: work = workAlloc();
659: ptable1_v[work] =
660: sysmem.u.pbase[btocrd(childUseg)] | SEG_RW;
661: mmuupd();
662: uprc = (UPROC *) (ctob(work) + U_OFFSET);
663: u.u_rval2 = ((uprc->u_signo)<<8) | 0177;
664: workFree(work);
665:
666: unlock(pnxgate);
667: T_HAL(8, printf("[%d]ends waiting, %d stopped ",
668: SELF->p_pid, pid));
669: return pp->p_pid;
670: }
671: if (pp->p_state == PSDEAD) {
672: ppp->p_cutime += pp->p_utime + pp->p_cutime;
673: ppp->p_cstime += pp->p_stime + pp->p_cstime;
674: u.u_rval2 = pp->p_exit;
675: pid = pp->p_pid;
676: unlock(pnxgate);
677: relproc(pp);
678: if (SIG_BIT(SIGCLD) & ppp->p_isig)
679: continue;
680: else {
681: T_HAL(8, printf("[%d]ends waiting,"
682: " %d died ", SELF->p_pid, pid));
683: return pid;
684: }
685: }
686: cpp = pp;
687: }
688: unlock(pnxgate);
689: if (cpp == NULL) {
690: T_HAL(8, printf("[%d]ends waiting, no children ",
691: SELF->p_pid));
692: u.u_error = ECHILD;
693: return;
694: }
695: x_s = x_sleep((char *)ppp, prilo, slpriSigLjmp, "wait");
696: /* Wait for a child to terminate. */
697: }
698: }
699:
700: /*
701: * waitpid() and wait() share the same system call number under BCS.
702: *
703: * pid argument:
704: * > 0 wait for child whose process matches pid
705: * = 0 wait for any child in current process group
706: * = -1 wait for any child - same as wait()
707: * < -1 wait for any child in group given by -pid
708: *
709: * The only waitpid() options supported are WNOHANG and WUNTRACED.
710: *
711: */
712: int
713: uwaitpid(opid, stat_loc, options)
714: register pid_t opid;
715: int *stat_loc, options;
716: {
717: register PROC *pp;
718: register PROC *ppp;
719: register PROC *cpp;
720: register int pid;
721:
722: if (options & WUNTRACED) {
723: printf("waitpid(%d,%d, WUNTRACED): unsupported\n", opid,
724: stat_loc);
725: u.u_error = EINVAL;
726: return;
727: }
728:
729: /* Wait for a child to stop or die. */
730: ppp = SELF;
731: for (;;) {
732: int x_s;
733:
734: /* Look at all processes. */
735: lock(pnxgate);
736: cpp = NULL;
737: pp = &procq;
738: while ((pp=pp->p_nforw) != &procq) {
739:
740: /* Ignore the current process. */
741: if (pp == ppp)
742: continue;
743: /*
744: * Ignore processes that aren't children of the
745: * current one.
746: */
747: if (pp->p_ppid != ppp->p_pid)
748: continue;
749:
750: if (pp->p_flags&PFSTOP)
751: continue;
752:
753: /* If opid == 0 we want to match gids */
754: if ((opid == 0) && (pp->p_group != ppp->p_group))
755: continue;
756:
757: /* If opid>0, want to match opid to child pid */
758: else if ((opid > 0) && (opid != pp->p_pid))
759: continue;
760:
761: /* If opid<-1, want to match -opid to child gid */
762: else if ((opid < -1) && ((-opid) != pp->p_group))
763: continue;
764:
765: /* if opid == -1, then any child is acceptable */
766:
767: /* Here is an acceptable child that hit a breakpoint. */
768: if (pp->p_flags&PFWAIT) {
769: int work; /* virtual click number */
770: int childUseg; /* system global addr */
771: UPROC * uprc;
772: SEG * sp;
773:
774: pp->p_flags &= ~PFWAIT;
775: pp->p_flags |= PFSTOP;
776:
777: /* fetch u.u_signo from the child */
778:
779: /* Find u area for child process pp */
780: sp = pp->p_segp[SIUSERP];
781: childUseg = MAPIO(sp->s_vmem, U_OFFSET);
782: work = workAlloc();
783: ptable1_v[work] =
784: sysmem.u.pbase[btocrd(childUseg)] | SEG_RW;
785: mmuupd();
786: uprc = (UPROC *) (ctob(work) + U_OFFSET);
787: u.u_rval2 = ((uprc->u_signo)<<8) | 0177;
788: workFree(work);
789:
790: unlock(pnxgate);
791: return pp->p_pid;
792: }
793:
794: /* Here is an acceptable child that is a zombie. */
795: if (pp->p_state == PSDEAD) {
796: ppp->p_cutime += pp->p_utime + pp->p_cutime;
797: ppp->p_cstime += pp->p_stime + pp->p_cstime;
798: u.u_rval2 = pp->p_exit;
799: pid = pp->p_pid;
800: unlock(pnxgate);
801: relproc(pp);
802: if (SIG_BIT(SIGCLD) & ppp->p_isig)
803: continue;
804: else {
805: return pid;
806: }
807: }
808: cpp = pp;
809: }
810: unlock(pnxgate);
811: if (cpp == NULL) {
812: u.u_error = ECHILD;
813: return;
814: }
815:
816: if (options & WNOHANG) {
817: u.u_rval2 = 0;
818: return 0;
819: }
820: else
821: /* Wait for a child to terminate. */
822: x_s = x_sleep((char *)ppp, prilo, slpriSigLjmp,
823: "waitpid");
824: }
825: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.