1 /* $OpenBSD: swap.c,v 1.28 2019/06/28 13:35:04 deraadt Exp $ */
2 /* $NetBSD: swap.c,v 1.9 1998/12/26 07:05:08 marc Exp $ */
3
4 /*-
5 * Copyright (c) 1997 Matthew R. Green. All rights reserved.
6 * Copyright (c) 1980, 1992, 1993
7 * The Regents of the University of California. All rights reserved.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
17 * 3. Neither the name of the University nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
32 */
33
34 #include <sys/types.h>
35 #include <sys/signal.h>
36 #include <sys/conf.h>
37 #include <sys/ioctl.h>
38 #include <sys/stat.h>
39 #include <sys/swap.h>
40
41 #include <stdio.h>
42 #include <stdlib.h>
43 #include <string.h>
44 #include <errno.h>
45 #include <unistd.h>
46
47 #include "systat.h"
48
49
50 static long blocksize;
51 static int hlen, nswap, rnswap;
52 static struct swapent *swap_devices;
53
54 void print_sw(void);
55 int read_sw(void);
56 int select_sw(void);
57 static void showswap(int i);
58 static void showtotal(void);
59
60
61 field_def fields_sw[] = {
62 {"DISK", 6, 16, 1, FLD_ALIGN_LEFT, -1, 0, 0, 0},
63 {"BLOCKS", 5, 10, 1, FLD_ALIGN_RIGHT, -1, 0, 0, 0},
64 {"USED", 5, 10, 1, FLD_ALIGN_RIGHT, -1, 0, 0, 0},
65 {"", 40, 80, 1, FLD_ALIGN_BAR, -1, 0, 0, 100},
66 };
67
68 #define FLD_SW_NAME FIELD_ADDR(fields_sw,0)
69 #define FLD_SW_BLOCKS FIELD_ADDR(fields_sw,1)
70 #define FLD_SW_USED FIELD_ADDR(fields_sw,2)
71 #define FLD_SW_BAR FIELD_ADDR(fields_sw,3)
72
73 /* Define views */
74 field_def *view_sw_0[] = {
75 FLD_SW_NAME, FLD_SW_BLOCKS, FLD_SW_USED, FLD_SW_BAR, NULL
76 };
77
78
79 /* Define view managers */
80 struct view_manager swap_mgr = {
81 "Swap", select_sw, read_sw, NULL, print_header,
82 print_sw, keyboard_callback, NULL, NULL
83 };
84
85 field_view views_sw[] = {
86 {view_sw_0, "swap", '6', &swap_mgr},
87 {NULL, NULL, 0, NULL}
88 };
89
90
91 int
select_sw(void)92 select_sw(void)
93 {
94 if (swap_devices == NULL || nswap == 0)
95 num_disp = 1;
96 else
97 num_disp = nswap;
98 if (nswap > 1)
99 num_disp++;
100 return (0);
101 }
102
103 int
read_sw(void)104 read_sw(void)
105 {
106 num_disp = 1;
107
108 nswap = swapctl(SWAP_NSWAP, 0, 0);
109
110 if (nswap < 0)
111 error("error: %s", strerror(errno));
112 if (nswap == 0)
113 return 0;
114
115 if (swap_devices)
116 (void)free(swap_devices);
117
118 swap_devices = calloc(nswap, sizeof(*swap_devices));
119 if (swap_devices == NULL)
120 return 0;
121
122 rnswap = swapctl(SWAP_STATS, (void *)swap_devices, nswap);
123 if (rnswap == -1 || nswap != rnswap)
124 return 0;
125
126 num_disp = nswap;
127 if (nswap > 1)
128 num_disp++;
129
130 return 0;
131 }
132
133
134 void
print_sw(void)135 print_sw(void)
136 {
137 int n, count = 0;
138
139 if (swap_devices == NULL || nswap == 0) {
140 print_fld_str(FLD_SW_BAR, "No swap devices");
141 return;
142 }
143
144
145 for (n = dispstart; n < num_disp; n++) {
146 if (n >= nswap)
147 showtotal();
148 else
149 showswap(n);
150 count++;
151 if (maxprint > 0 && count >= maxprint)
152 break;
153 }
154
155 }
156
157 int
initswap(void)158 initswap(void)
159 {
160 field_view *v;
161
162 char *bs = getbsize(&hlen, &blocksize);
163
164 FLD_SW_BLOCKS->title = strdup(bs);
165
166 for (v = views_sw; v->name != NULL; v++)
167 add_view(v);
168
169 return(1);
170 }
171
172
173 static void
showswap(int i)174 showswap(int i)
175 {
176 int d, used, xsize;
177 struct swapent *sep;
178 char *p;
179
180 d = blocksize / 512;
181
182 sep = &swap_devices[i];
183
184 p = strrchr(sep->se_path, '/');
185 p = p ? p+1 : sep->se_path;
186
187 print_fld_str(FLD_SW_NAME, p);
188
189 xsize = sep->se_nblks;
190 used = sep->se_inuse;
191
192 print_fld_uint(FLD_SW_BLOCKS, xsize / d);
193 print_fld_uint(FLD_SW_USED, used / d);
194 print_fld_bar(FLD_SW_BAR, 100 * used / xsize);
195
196 end_line();
197 }
198
199 static void
showtotal(void)200 showtotal(void)
201 {
202 struct swapent *sep;
203 int d, i, avail, used, xsize, mfree;
204
205 d = blocksize / 512;
206 mfree = avail = 0;
207
208 for (sep = swap_devices, i = 0; i < nswap; i++, sep++) {
209 xsize = sep->se_nblks;
210 used = sep->se_inuse;
211 avail += xsize;
212 mfree += xsize - used;
213 }
214 used = avail - mfree;
215
216 print_fld_str(FLD_SW_NAME, "Total");
217 print_fld_uint(FLD_SW_BLOCKS, avail / d);
218 print_fld_uint(FLD_SW_USED, used / d);
219 print_fld_bar(FLD_SW_BAR, 100 * used / avail);
220
221 end_line();
222 }
223