swapctl.c revision 1.1 1 /* $NetBSD: swapctl.c,v 1.1 1997/06/12 13:14:11 mrg Exp $ */
2
3 /*
4 * Copyright (c) 1996, 1997 Matthew R. Green
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. All advertising materials mentioning features or use of this software
16 * must display the following acknowledgement:
17 * This product includes software developed by Matthew R. Green for
18 * The NetBSD Foundation.
19 * 4. The name of the author may not be used to endorse or promote products
20 * derived from this software without specific prior written permission.
21 *
22 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
23 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
24 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
25 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
26 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
27 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
28 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
29 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
30 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 * SUCH DAMAGE.
33 */
34
35 /*
36 * swapctl command:
37 * -A add all devices listed as `sw' in /etc/fstab
38 * -a <dev> add this device
39 * -d <dev> remove this swap device (not supported yet)
40 * -l list swap devices
41 * -s short listing of swap devices
42 * -k use kilobytes
43 * -p <pri> use this priority
44 * -c change priority
45 */
46
47 #include <sys/param.h>
48
49 #include <vm/vm_swap.h>
50
51 #include <unistd.h>
52 #include <errno.h>
53 #include <stdio.h>
54 #include <stdlib.h>
55 #include <string.h>
56 #include <fstab.h>
57
58 #include "swapctl.h"
59
60 int Aflag;
61 int aflag;
62 int cflag;
63 #ifdef SWAP_OFF_WORKS
64 int dflag;
65 #endif
66 int lflag;
67 int kflag;
68 int sflag;
69 int pflag;
70 int pri; /* uses 0 as default pri */
71 char *path;
72
73 static void change_priority __P((char *));
74 static void add_swap __P((char *));
75 #ifdef SWAP_OFF_WORKS
76 static void del_swap __P((char *));
77 #endif /* SWAP_OFF_WORKS */
78 static void do_fstab __P((void));
79 static void usage __P((void));
80
81 int
82 main(argc, argv)
83 int argc;
84 char *argv[];
85 {
86 int c;
87 int am_swapon = 0;
88 #ifdef SWAP_OFF_WORKS
89 int swapoff = 0;
90 static char getoptstr[] = "Aacdlkp:s";
91 #else
92 static char getoptstr[] = "Aaclkp:s";
93 #endif /* SWAP_OFF_WORKS */
94 extern char *__progname; /* XXX */
95
96 if (strcmp(__progname, "swapon") == 0)
97 aflag = am_swapon = 1;
98 #ifdef SWAP_OFF_WORKS
99 else if (strcmp(__progname, "swapoff") == 0)
100 dflag = swapoff = 1;
101 #endif /* SWAP_OFF_WORKS */
102 while ((c = getopt(argc, argv, getoptstr)) != EOF) {
103 switch(c) {
104 case 'A':
105 Aflag = 1;
106 break;
107 case 'a':
108 if (cflag) {
109 warn("-a and -c are mutually exclusive");
110 usage();
111 }
112 #ifdef SWAP_OFF_WORKS
113 if (dflag) {
114 warn("-a and -d are mutually exclusive");
115 usage();
116 }
117 #endif /* SWAP_OFF_WORKS */
118 if (am_swapon)
119 Aflag = 1;
120 else
121 aflag = 1;
122 break;
123 case 'c':
124 if (aflag) {
125 warn("-c and -a are mutually exclusive");
126 usage();
127 }
128 cflag = 1;
129 break;
130 #ifdef SWAP_OFF_WORKS
131 case 'd':
132 if (aflag || cflag) {
133 warn("-d and -a or -c are mutually exclusive");
134 usage();
135 }
136 dflag = 1;
137 break;
138 #endif /* SWAP_OFF_WORKS */
139 case 'l':
140 lflag = 1;
141 break;
142 case 'k':
143 kflag = 1;
144 break;
145 case 'p':
146 pflag = 1;
147 pri = atoi(optarg);
148 break;
149 case 's':
150 sflag = 1;
151 break;
152 }
153 }
154 /* SWAP_OFF_WORKS */
155 if (!aflag && !Aflag && !cflag && !lflag && !sflag /* && !dflag */)
156 usage();
157
158 argv += optind;
159 if (!*argv && !Aflag && !lflag && !sflag)
160 usage();
161 if (cflag && !pflag)
162 usage();
163
164 if (lflag)
165 list_swap(pri, kflag, pflag, 0, 1);
166 else if (sflag)
167 list_swap(pri, kflag, pflag, 0, 0);
168 else if (cflag)
169 change_priority(argv[0]);
170 else if (aflag)
171 add_swap(argv[0]);
172 #ifdef SWAP_OFF_WORKS
173 else if (dflag)
174 del_swap(argv[0]);
175 #endif /* SWAP_OFF_WORKS */
176 else if (Aflag)
177 do_fstab();
178 exit(0);
179 }
180
181 /*
182 * change_priority: change the priority of a swap device.
183 */
184 void
185 change_priority(path)
186 char *path;
187 {
188
189 if (swapctl(SWAP_CTL, path, pri) < 0)
190 warn("%s", path);
191 }
192
193 /*
194 * add_swap: add the pathname to the list of swap devices.
195 */
196 void
197 add_swap(path)
198 char *path;
199 {
200
201 if (swapctl(SWAP_ON, path, pri) < 0)
202 warn("%s", path);
203 }
204
205 #if SWAP_OFF_WORKS
206 /*
207 * del_swap: remove the pathname to the list of swap devices.
208 *
209 * XXX note that the kernel does not support this operation (yet).
210 */
211 void
212 del_swap(path)
213 char path;
214 {
215
216 if (swapctl(SWAP_OFF, path, pri) < 0)
217 warn("%s", path);
218 }
219 #endif /* SWAP_OFF_WORKS */
220
221 void
222 do_fstab()
223 {
224 struct fstab *fp;
225 char *s;
226 long priority;
227
228 #define PRIORITYEQ "priority="
229 #define NFSMNTPT "nfsmntpt="
230 #define PATH_MOUNT "/sbin/mount_nfs"
231 while (fp = getfsent()) {
232 char *spec;
233
234 if (strcmp(fp->fs_type, "sw") != 0)
235 continue;
236
237 spec = fp->fs_spec;
238
239 if (s = strstr(fp->fs_mntops, PRIORITYEQ)) {
240 s += sizeof(PRIORITYEQ) - 1;
241 priority = atol(s);
242 } else
243 priority = pri;
244
245 if (s = strstr(fp->fs_mntops, NFSMNTPT)) {
246 char *t, cmd[2*PATH_MAX+sizeof(PATH_MOUNT)+2];
247
248 t = strpbrk(s, ",");
249 if (t != 0)
250 *t = '\0';
251 spec = strdup(s + strlen(NFSMNTPT));
252 if (t != 0)
253 *t = ',';
254
255 if (spec == NULL)
256 errx(1, "Out of memory");
257
258 if (strlen(spec) == 0) {
259 warnx("empty mountpoint");
260 free(spec);
261 continue;
262 }
263 snprintf(cmd, sizeof(cmd), "%s %s %s",
264 PATH_MOUNT, fp->fs_spec, spec);
265 if (system(cmd) != 0) {
266 warnx("%s: mount failed", fp->fs_spec);
267 continue;
268 }
269 }
270
271 if (swapctl(SWAP_ON, spec, (int)priority) < 0)
272 warn("%s", spec);
273 else
274 printf("swap: adding %s as swap device at priority %d\n",
275 fp->fs_spec, priority);
276
277 if (spec != fp->fs_spec)
278 free(spec);
279 }
280 }
281
282 void
283 usage()
284 {
285 extern char *__progname;
286 #ifdef SWAP_OFF_WORKS
287 static char usagemsg[] =
288 "usage: %s [-k] [-A|-a|-c|-d|-l|-s] [-p <pri>] [device]\n";
289 #else
290 static char usagemsg[] =
291 "usage: %s [-k] [-A|-a|-c|-l|-s] [-p <pri>] [device]\n";
292 #endif /* SWAP_OFF_WORKS */
293
294 fprintf(stderr, usagemsg, __progname);
295 exit(1);
296 }
297