1/*
2 * Copyright (c) 2005-2007 Sendmail, Inc. and its suppliers.
3 *      All rights reserved.
4 *
5 * By using this file, you agree to the terms and conditions set
6 * forth in the LICENSE file which can be found at the top level of
7 * the sendmail distribution.
8 */
9
10#pragma ident	"%Z%%M%	%I%	%E% SMI"
11
12#include <sm/gen.h>
13SM_RCSID("@(#)$Id: memstat.c,v 1.6 2007/03/20 23:26:12 ca Exp $")
14
15#include <errno.h>
16#include <sm/misc.h>
17
18#if USESWAPCTL
19#include <sys/stat.h>
20#include <sys/swap.h>
21
22static long sc_page_size;
23
24/*
25**  SM_MEMSTAT_OPEN -- open memory statistics
26**
27**	Parameters:
28**		none
29**
30**	Results:
31**		errno as error code, 0: ok
32*/
33
34int
35sm_memstat_open()
36{
37	sc_page_size = sysconf(_SC_PAGE_SIZE);
38	if (sc_page_size == -1)
39		return (errno != 0) ? errno : -1;
40	return 0;
41}
42
43/*
44**  SM_MEMSTAT_CLOSE -- close memory statistics
45**
46**	Parameters:
47**		none
48**
49**	Results:
50**		errno as error code, 0: ok
51*/
52
53int
54sm_memstat_close()
55{
56	return 0;
57}
58
59/*
60**  SM_MEMSTAT_GET -- get memory statistics
61**
62**	Parameters:
63**		resource -- resource to look up
64**		pvalue -- (pointer to) memory statistics value (output)
65**
66**	Results:
67**		0: success
68**		!=0: error
69*/
70
71int
72sm_memstat_get(resource, pvalue)
73	char *resource;
74	long *pvalue;
75{
76	int r;
77	struct anoninfo ai;
78
79	r = swapctl(SC_AINFO, &ai);
80	if (r == -1)
81		return (errno != 0) ? errno : -1;
82	r = ai.ani_max - ai.ani_resv;
83	r *= sc_page_size >> 10;
84   	*pvalue = r;
85	return 0;
86}
87
88#elif USEKSTAT
89
90#include <kstat.h>
91#include <sys/sysinfo.h>
92
93static kstat_ctl_t *kc;
94static kstat_t *kst;
95
96/*
97**  SM_MEMSTAT_OPEN -- open memory statistics
98**
99**	Parameters:
100**		none
101**
102**	Results:
103**		errno as error code, 0: ok
104*/
105
106int
107sm_memstat_open()
108{
109	kstat_named_t *kn;
110
111	kc = kstat_open();
112	if (kc == NULL)
113		return (errno != 0) ? errno : -1;
114	kst = kstat_lookup(kc, "unix", 0,
115		(name != NULL) ? name : "system_pages");
116	if (kst == 0)
117		return (errno != 0) ? errno : -2;
118	return 0;
119}
120
121/*
122**  SM_MEMSTAT_CLOSE -- close memory statistics
123**
124**	Parameters:
125**		none
126**
127**	Results:
128**		errno as error code, 0: ok
129*/
130
131int
132sm_memstat_close()
133{
134	int r;
135
136	if (kc == NULL)
137		return 0;
138	r = kstat_close(kc);
139	if (r != 0)
140		return (errno != 0) ? errno : -1;
141	return 0;
142}
143
144/*
145**  SM_MEMSTAT_GET -- get memory statistics
146**
147**	Parameters:
148**		resource -- resource to look up
149**		pvalue -- (pointer to) memory statistics value (output)
150**
151**	Results:
152**		0: success
153**		!=0: error
154*/
155
156int
157sm_memstat_get(resource, pvalue)
158	char *resource;
159	long *pvalue;
160{
161	int r;
162	kstat_named_t *kn;
163
164	if (kc == NULL || kst == NULL)
165		return -1;
166	if (kstat_read(kc, kst, NULL) == -1)
167		return (errno != 0) ? errno : -2;
168	kn = kstat_data_lookup(kst,
169			(resource != NULL) ? resource: "freemem");
170	if (kn == NULL)
171		return (errno != 0) ? errno : -3;
172   	*pvalue = kn->value.ul;
173	return 0;
174}
175
176#elif USEPROCMEMINFO
177
178/*
179/proc/meminfo?
180        total:    used:    free:  shared: buffers:  cached:
181Mem:  261468160 252149760  9318400        0  3854336 109813760
182Swap: 1052794880 62185472 990609408
183MemTotal:       255340 kB
184MemFree:          9100 kB
185MemShared:           0 kB
186Buffers:          3764 kB
187Cached:         107240 kB
188Active:         104340 kB
189Inact_dirty:      4220 kB
190Inact_clean:      2444 kB
191Inact_target:     4092 kB
192HighTotal:           0 kB
193HighFree:            0 kB
194LowTotal:       255340 kB
195LowFree:          9100 kB
196SwapTotal:     1028120 kB
197SwapFree:       967392 kB
198*/
199
200#include <stdio.h>
201#include <string.h>
202static FILE *fp;
203
204/*
205**  SM_MEMSTAT_OPEN -- open memory statistics
206**
207**	Parameters:
208**		none
209**
210**	Results:
211**		errno as error code, 0: ok
212*/
213
214int
215sm_memstat_open()
216{
217	fp = fopen("/proc/meminfo", "r");
218	return (fp != NULL) ? 0 : errno;
219}
220
221/*
222**  SM_MEMSTAT_CLOSE -- close memory statistics
223**
224**	Parameters:
225**		none
226**
227**	Results:
228**		errno as error code, 0: ok
229*/
230
231int
232sm_memstat_close()
233{
234	if (fp != NULL)
235	{
236		fclose(fp);
237		fp = NULL;
238	}
239	return 0;
240}
241
242/*
243**  SM_MEMSTAT_GET -- get memory statistics
244**
245**	Parameters:
246**		resource -- resource to look up
247**		pvalue -- (pointer to) memory statistics value (output)
248**
249**	Results:
250**		0: success
251**		!=0: error
252*/
253
254int
255sm_memstat_get(resource, pvalue)
256	char *resource;
257	long *pvalue;
258{
259	int r;
260	size_t l;
261	char buf[80];
262
263	if (resource == NULL)
264		return EINVAL;
265	if (pvalue == NULL)
266		return EINVAL;
267	if (fp == NULL)
268		return -1;	/* try to reopen? */
269	rewind(fp);
270	l = strlen(resource);
271	if (l >= sizeof(buf))
272		return EINVAL;
273	while (fgets(buf, sizeof(buf), fp) != NULL)
274	{
275		if (strncmp(buf, resource, l) == 0 && buf[l] == ':')
276		{
277			r = sscanf(buf + l + 1, "%ld", pvalue);
278			return (r > 0) ? 0 : -1;
279		}
280	}
281	return 0;
282}
283
284#else /* USEPROCMEMINFO */
285
286/*
287**  SM_MEMSTAT_OPEN -- open memory statistics
288**
289**	Parameters:
290**		none
291**
292**	Results:
293**		errno as error code, 0: ok
294*/
295
296int
297sm_memstat_open()
298{
299	return -1;
300}
301
302/*
303**  SM_MEMSTAT_CLOSE -- close memory statistics
304**
305**	Parameters:
306**		none
307**
308**	Results:
309**		errno as error code, 0: ok
310*/
311
312int
313sm_memstat_close()
314{
315	return 0;
316}
317
318/*
319**  SM_MEMSTAT_GET -- get memory statistics
320**
321**	Parameters:
322**		resource -- resource to look up
323**		pvalue -- (pointer to) memory statistics value (output)
324**
325**	Results:
326**		0: success
327**		!=0: error
328*/
329
330int
331sm_memstat_get(resource, pvalue)
332	char *resource;
333	long *pvalue;
334{
335	return -1;
336}
337
338#endif /* USEKSTAT */
339