xref: /illumos-gate/usr/src/cmd/csh/wait3.c (revision 7c478bd9)
1 /*
2  * Copyright 2003 Sun Microsystems, Inc.  All rights reserved.
3  * Use is subject to license terms.
4  */
5 
6 /*	Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T	*/
7 /*	  All Rights Reserved  	*/
8 
9 /*
10  * Copyright (c) 1980 Regents of the University of California.
11  * All rights reserved. The Berkeley Software License Agreement
12  * specifies the terms and conditions for redistribution.
13  */
14 
15 #pragma ident	"%Z%%M%	%I%	%E% SMI"
16 
17 /*
18  *      Compatibility lib for BSD's wait3(). It is not
19  *      binary compatible, since BSD's WNOHANG and WUNTRACED
20  *      carry different #define values.
21  */
22 #include <errno.h>
23 #include <sys/types.h>
24 #include <sys/time.h>
25 #include <sys/times.h>
26 #include <wait.h>
27 #include <sys/siginfo.h>
28 #include <sys/procset.h>
29 #include <sys/param.h>
30 #include <sys/resource.h>
31 
32 /*
33  * Since sysV does not support rusage as in BSD, an approximate approach
34  * is:
35  *      ...
36  *      call times
37  *      call waitid
38  *      if ( a child is found )
39  *              call times again
40  *              rusage ~= diff in the 2 times call
41  *      ...
42  *
43  */
44 
45 /*
46  * XXX:  There is now a wait3 function in libc which should be used instead
47  * of this local version of wait3.  With the addition of a wait3 prototype
48  * in <sys/wait.h> as per the X/Open XPG4v2 specification, compilation of
49  * the csh utility will result in warnings, hence the renaming of the local
50  * version.  Using the libc wait3 rather than the local version results in
51  * a failure with csh, however, this version should eventually be dropped
52  * in favor of the libc wait3 with appropriate updates made to sh.proc.c
53  * to account for the difference in implementation of the local versus
54  * the libc versions.  This should probably be done as part of an overall
55  * effort to rid csh of local versions of functions now in libc.
56  */
57 
58 csh_wait3(status, options, rp)
59         int	*status;
60         int     options;
61 	struct	rusage	*rp;
62 
63 {
64         struct  tms     before_tms;
65         struct  tms     after_tms;
66         siginfo_t       info;
67         int             error;
68 
69 	if (rp)
70 		memset((void *)rp, 0, sizeof(struct rusage));
71 	memset((void *)&info, 0, sizeof(siginfo_t));
72         if ( times(&before_tms) == -1 )
73                 return (-1);            /* errno is set by times() */
74 
75 	/*
76 	 * BSD's wait3() only supports WNOHANG & WUNTRACED
77 	 */
78 	options |= (WNOHANG|WUNTRACED|WEXITED|WSTOPPED|WTRAPPED|WCONTINUED);
79         error = waitid(P_ALL, 0, &info, options);
80         if ( error == 0 ) {
81                 clock_t	diffu;  /* difference in usertime (ticks) */
82                 clock_t	diffs;  /* difference in systemtime (ticks) */
83 
84                 if ( (options & WNOHANG) && (info.si_pid == 0) )
85                         return (0);     /* no child found */
86 
87 		if (rp) {
88                 	if ( times(&after_tms) == -1 )
89                         	return (-1);    /* errno set by times() */
90                 	/*
91                  	 * The system/user time is an approximation only !!!
92                  	 */
93                 	diffu = after_tms.tms_cutime - before_tms.tms_cutime;
94                 	diffs = after_tms.tms_cstime - before_tms.tms_cstime;
95                 	rp->ru_utime.tv_sec = diffu/HZ;
96                 	rp->ru_utime.tv_usec = (diffu % HZ) / HZ * 1000000;
97                 	rp->ru_stime.tv_sec = diffs/HZ;
98                 	rp->ru_stime.tv_usec = (diffs % HZ) / HZ * 1000000;
99 		}
100                	*status = wstat(info.si_code, info.si_status);
101                 return (info.si_pid);
102 
103         } else {
104                 return (-1);            /* error number is set by waitid() */
105         }
106 }
107 
108 /*
109  * Convert the status code to old style wait status
110  */
111 wstat(code, status)
112         int     code;
113         int     status;
114 {
115         register stat = (status & 0377);
116 
117         switch (code) {
118                 case CLD_EXITED:
119                         stat <<= 8;
120                         break;
121                 case CLD_DUMPED:
122                         stat |= WCOREFLG;
123                         break;
124                 case CLD_KILLED:
125                         break;
126                 case CLD_TRAPPED:
127                 case CLD_STOPPED:
128                         stat <<= 8;
129                         stat |= WSTOPFLG;
130                         break;
131 		case CLD_CONTINUED:
132                         stat = WCONTFLG;
133                         break;
134         }
135         return (stat);
136 }
137