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