1 /* @(#)getrusage.c	1.31 21/07/22 Copyright 1987-2021 J. Schilling */
2 #undef	USE_LARGEFILES	/* XXX Tempor�rer Hack f�r Solaris */
3 #include <schily/mconfig.h>
4 #ifndef lint
5 static	UConst char sccsid[] =
6 	"@(#)getrusage.c	1.31 21/07/22 Copyright 1987-2021 J. Schilling";
7 #endif
8 /*
9  *	getrusage() emulation for SVr4
10  *
11  *	Copyright (c) 1987-2021 J. Schilling
12  */
13 /*
14  * The contents of this file are subject to the terms of the
15  * Common Development and Distribution License, Version 1.0 only
16  * (the "License").  You may not use this file except in compliance
17  * with the License.
18  *
19  * See the file CDDL.Schily.txt in this distribution for details.
20  * A copy of the CDDL is also available via the Internet at
21  * http://www.opensource.org/licenses/cddl1.txt
22  *
23  * When distributing Covered Code, include this CDDL HEADER in each
24  * file and include the License file CDDL.Schily.txt from this distribution.
25  */
26 
27 /*
28  * XXX Solaris kann kein 64 bit proc file (LF32)
29  */
30 #undef	USE_LARGEFILES	/* XXX Tempor�rer Hack f�r Solaris */
31 
32 #include <schily/stdio.h>
33 #include "bsh.h"
34 #include <schily/unistd.h>
35 #include <schily/fcntl.h>
36 #include <schily/time.h>
37 #include <schily/resource.h>
38 #include <schily/procfs.h>
39 #include <schily/times.h>
40 #include "limit.h"
41 
42 
43 /*#undef	HAVE_GETRUSAGE*/
44 
45 #ifndef	HAVE_GETRUSAGE
46 EXPORT	int	getrusage	__PR((int who, struct rusage *rusage));
47 #endif
48 
49 #ifndef	HAVE_GETRUSAGE
50 /*
51  * XXX who wird nicht untersteutzt!
52  */
53 EXPORT int
getrusage(who,rusage)54 getrusage(who,  rusage)
55 	int		who;
56 	struct rusage	*rusage;
57 {
58 #if	defined(PIOCUSAGE) || _STRUCTURED_PROC == 1
59 	int		f;
60 	char		cproc[32];
61 	prusage_t	prusage;
62 #endif
63 #if _STRUCTURED_PROC == 1
64 	pstatus_t	pstatus;
65 #endif
66 
67 	if (rusage)
68 		fillbytes((void *)rusage, sizeof (struct rusage), 0);
69 
70 #if	defined(PIOCUSAGE) || _STRUCTURED_PROC == 1
71 #define	DID_RUSAGE
72 
73 #if _STRUCTURED_PROC == 1
74 	if (who == RUSAGE_CHILDREN)
75 		sprintf(cproc, "/proc/%ld/status", (long)getpid());
76 	else
77 		sprintf(cproc, "/proc/%ld/usage", (long)getpid());
78 	if ((f = open(cproc, O_RDONLY)) < 0)
79 		return (-1);
80 	if (who == RUSAGE_CHILDREN) {
81 		if (read(f, &pstatus, sizeof (pstatus)) < 0) {
82 			close(f);
83 			return (-1);
84 		}
85 	} else {
86 		if (read(f, &prusage, sizeof (prusage)) < 0) {
87 			close(f);
88 			return (-1);
89 		}
90 	}
91 #else
92 	if (who == RUSAGE_CHILDREN)
93 		return (-1);
94 	sprintf(cproc, "/proc/%ld", (long)getpid());
95 	if ((f = open(cproc, O_RDONLY)) < 0)
96 		return (-1);
97 	if (ioctl(f, PIOCUSAGE, &prusage) < 0) {
98 		close(f);
99 		return (-1);
100 	}
101 #endif
102 	close(f);
103 	if (rusage) {
104 #if _STRUCTURED_PROC == 1
105 		if (who == RUSAGE_CHILDREN) {
106 			rusage->ru_utime.tv_sec =  pstatus.pr_cutime.tv_sec;
107 			rusage->ru_utime.tv_usec = pstatus.pr_cutime.tv_nsec/1000;
108 			rusage->ru_stime.tv_sec =  pstatus.pr_cstime.tv_sec;
109 			rusage->ru_stime.tv_usec = pstatus.pr_cstime.tv_nsec/1000;
110 			return (0);
111 		}
112 #endif
113 		rusage->ru_utime.tv_sec =  prusage.pr_utime.tv_sec;
114 		rusage->ru_utime.tv_usec = prusage.pr_utime.tv_nsec/1000;
115 		rusage->ru_stime.tv_sec =  prusage.pr_stime.tv_sec;
116 		rusage->ru_stime.tv_usec = prusage.pr_stime.tv_nsec/1000;
117 
118 /* Missing fields:			*/
119 /*		rusage->ru_maxrss = XXX;*/
120 /*		rusage->ru_ixrss = XXX;*/
121 /*		rusage->ru_idrss = XXX;*/
122 /*		rusage->ru_isrss = XXX;*/
123 
124 		rusage->ru_minflt = prusage.pr_minf;
125 		rusage->ru_majflt = prusage.pr_majf;
126 		rusage->ru_nswap  = prusage.pr_nswap;
127 		rusage->ru_inblock = prusage.pr_inblk;
128 		rusage->ru_oublock = prusage.pr_oublk;
129 		rusage->ru_msgsnd = prusage.pr_msnd;
130 		rusage->ru_msgrcv = prusage.pr_mrcv;
131 		rusage->ru_nsignals = prusage.pr_sigs;
132 		rusage->ru_nvcsw = prusage.pr_vctx;
133 		rusage->ru_nivcsw = prusage.pr_ictx;
134 	}
135 #endif	/* PIOCUSAGE */
136 #if	!defined(DID_RUSAGE) && defined(HAVE_TIMES)
137 #define	DID_RUSAGE
138 #define	NEED_CLOCK2TV
139 	{
140 		struct tms	tms;
141 	LOCAL	void clock2tv	__PR((clock_t t, struct timeval *tp));
142 
143 		times(&tms);
144 
145 		if (who == RUSAGE_SELF) {
146 			clock2tv(tms.tms_utime, &rusage->ru_utime);
147 			clock2tv(tms.tms_stime, &rusage->ru_stime);
148 		} else if (who == RUSAGE_CHILDREN) {
149 			clock2tv(tms.tms_cutime, &rusage->ru_utime);
150 			clock2tv(tms.tms_cstime, &rusage->ru_stime);
151 		}
152 	}
153 #endif
154 	return (0);
155 }
156 
157 #ifdef	NEED_CLOCK2TV
158 #ifndef	HZ
159 #define	HZ	sysconf(_SC_CLK_TCK)
160 #endif
161 
162 LOCAL void
clock2tv(t,tp)163 clock2tv(t, tp)
164 	clock_t		t;
165 	struct timeval	*tp;
166 {
167 	int _hz = HZ;	/* HZ may be a macro to a sysconf() call */
168 
169 	tp->tv_sec = t / _hz;
170 	tp->tv_usec = t % _hz;
171 	if (_hz <= 1000000)
172 		tp->tv_usec *= 1000000 / _hz;
173 	else
174 		tp->tv_usec /= _hz / 1000000;
175 }
176 #endif
177 
178 #endif	/* HAVE_GETRUSAGE */
179