File: [local] / src / sbin / swapctl / swapctl.c (download)
Revision 1.3, Fri Jun 30 16:00:09 2000 UTC (23 years, 11 months ago) by millert
Branch: MAIN
CVS Tags: OPENBSD_2_8_BASE, OPENBSD_2_8 Changes since 1.2: +2 -2 lines
warnx?/errx? paranoia (use "%s" not a bare string unless it is a
constant). These are not security holes but it is worth fixing
them anyway both for robustness and so folks looking for examples
in the tree are not misled into doing something potentially dangerous.
Furthermore, it is a bad idea to assume that pathnames will not
include '%' in them and that error routines don't return strings
with '%' in them (especially in light of the possibility of locales).
|
/* $OpenBSD: swapctl.c,v 1.3 2000/06/30 16:00:09 millert Exp $ */
/* $NetBSD: swapctl.c,v 1.9 1998/07/26 20:23:15 mycroft Exp $ */
/*
* Copyright (c) 1996, 1997 Matthew R. Green
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
/*
* swapctl command:
* -A add all devices listed as `sw' in /etc/fstab
* -t [blk|noblk] if -A, add either all block device or all non-block
* devices
* -a <dev> add this device
* -d <dev> remove this swap device (not supported yet)
* -l list swap devices
* -s short listing of swap devices
* -k use kilobytes
* -p <pri> use this priority
* -c change priority
*
* or, if invoked as "swapon" (compatibility mode):
*
* -a all devices listed as `sw' in /etc/fstab
* -t same as -t above (feature not present in old
* swapon(8) command)
* <dev> add this device
*/
#include <sys/param.h>
#include <sys/stat.h>
#include <sys/swap.h>
#include <unistd.h>
#include <err.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fstab.h>
#include "swapctl.h"
int command;
/*
* Commands for swapctl(8). These are mutually exclusive.
*/
#define CMD_A 0x01 /* process /etc/fstab */
#define CMD_a 0x02 /* add a swap file/device */
#define CMD_c 0x04 /* change priority of a swap file/device */
#define CMD_d 0x08 /* delete a swap file/device */
#define CMD_l 0x10 /* list swap files/devices */
#define CMD_s 0x20 /* summary of swap files/devices */
#define SET_COMMAND(cmd) \
do { \
if (command) \
usage(); \
command = (cmd); \
} while (0)
/*
* Commands that require a "path" argument at the end of the command
* line, and the ones which require that none exist.
*/
#define REQUIRE_PATH (CMD_a | CMD_c | CMD_d)
#define REQUIRE_NOPATH (CMD_A | CMD_l | CMD_s)
/*
* Option flags, and the commands with which they are valid.
*/
int kflag; /* display in 1K blocks */
#define KFLAG_CMDS (CMD_l | CMD_s)
int pflag; /* priority was specified */
#define PFLAG_CMDS (CMD_A | CMD_a | CMD_c)
char *tflag; /* swap device type (blk or noblk) */
#define TFLAG_CMDS (CMD_A)
int pri; /* uses 0 as default pri */
static void change_priority __P((char *));
static void add_swap __P((char *));
static void del_swap __P((char *));
int main __P((int, char *[]));
static void do_fstab __P((void));
static void usage __P((void));
static void swapon_command __P((int, char **));
#if 0
static void swapoff_command __P((int, char **));
#endif
extern char *__progname; /* from crt0.o */
int
main(argc, argv)
int argc;
char *argv[];
{
int c;
if (strcmp(__progname, "swapon") == 0) {
swapon_command(argc, argv);
/* NOTREACHED */
}
#if 0
if (strcmp(__progname, "swapoff") == 0) {
swapoff_command(argc, argv);
/* NOTREACHED */
}
#endif
while ((c = getopt(argc, argv, "Aacdlkp:st:")) != -1) {
switch (c) {
case 'A':
SET_COMMAND(CMD_A);
break;
case 'a':
SET_COMMAND(CMD_a);
break;
case 'c':
SET_COMMAND(CMD_c);
break;
case 'd':
SET_COMMAND(CMD_d);
break;
case 'l':
SET_COMMAND(CMD_l);
break;
case 'k':
kflag = 1;
break;
case 'p':
pflag = 1;
/* XXX strtol() */
pri = atoi(optarg);
break;
case 's':
SET_COMMAND(CMD_s);
break;
case 't':
if (tflag != NULL)
usage();
tflag = optarg;
break;
default:
usage();
/* NOTREACHED */
}
}
/* Did the user specify a command? */
if (command == 0)
usage();
argv += optind;
argc -= optind;
switch (argc) {
case 0:
if (command & REQUIRE_PATH)
usage();
break;
case 1:
if (command & REQUIRE_NOPATH)
usage();
break;
default:
usage();
}
/* To change priority, you have to specify one. */
if ((command == CMD_c) && pflag == 0)
usage();
/* Sanity-check -t */
if (tflag != NULL) {
if (command != CMD_A)
usage();
if (strcmp(tflag, "blk") != 0 &&
strcmp(tflag, "noblk") != 0)
usage();
}
/* Dispatch the command. */
switch (command) {
case CMD_l:
list_swap(pri, kflag, pflag, 0, 1);
break;
case CMD_s:
list_swap(pri, kflag, pflag, 0, 0);
break;
case CMD_c:
change_priority(argv[0]);
break;
case CMD_a:
add_swap(argv[0]);
break;
case CMD_d:
del_swap(argv[0]);
break;
case CMD_A:
do_fstab();
break;
}
exit(0);
}
/*
* swapon_command: emulate the old swapon(8) program.
*/
void
swapon_command(argc, argv)
int argc;
char **argv;
{
int ch, fiztab = 0;
while ((ch = getopt(argc, argv, "at:")) != -1) {
switch (ch) {
case 'a':
fiztab = 1;
break;
case 't':
if (tflag != NULL)
usage();
tflag = optarg;
break;
default:
goto swapon_usage;
}
}
argc -= optind;
argv += optind;
if (fiztab) {
if (argc)
goto swapon_usage;
/* Sanity-check -t */
if (tflag != NULL) {
if (strcmp(tflag, "blk") != 0 &&
strcmp(tflag, "noblk") != 0)
usage();
}
do_fstab();
exit(0);
} else if (argc == 0 || tflag != NULL)
goto swapon_usage;
while (argc) {
add_swap(argv[0]);
argc--;
argv++;
}
exit(0);
/* NOTREACHED */
swapon_usage:
fprintf(stderr, "usage: %s -a [-t blk|noblk]\n", __progname);
fprintf(stderr, " %s <path> ...\n", __progname);
exit(1);
}
/*
* change_priority: change the priority of a swap device.
*/
void
change_priority(path)
char *path;
{
if (swapctl(SWAP_CTL, path, pri) < 0)
warn("%s", path);
}
/*
* add_swap: add the pathname to the list of swap devices.
*/
void
add_swap(path)
char *path;
{
if (swapctl(SWAP_ON, path, pri) < 0)
err(1, "%s", path);
}
/*
* del_swap: remove the pathname to the list of swap devices.
*/
void
del_swap(path)
char *path;
{
if (swapctl(SWAP_OFF, path, pri) < 0)
err(1, "%s", path);
}
void
do_fstab()
{
struct fstab *fp;
char *s;
long priority;
struct stat st;
int isblk;
int gotone = 0;
#define PRIORITYEQ "priority="
#define NFSMNTPT "nfsmntpt="
#define PATH_MOUNT "/sbin/mount_nfs"
while ((fp = getfsent()) != NULL) {
const char *spec;
if (strcmp(fp->fs_type, "sw") != 0)
continue;
spec = fp->fs_spec;
isblk = 0;
if ((s = strstr(fp->fs_mntops, PRIORITYEQ)) != NULL) {
s += sizeof(PRIORITYEQ) - 1;
priority = atol(s);
} else
priority = pri;
if ((s = strstr(fp->fs_mntops, NFSMNTPT)) != NULL) {
char *t, cmd[2*PATH_MAX+sizeof(PATH_MOUNT)+2];
/*
* Skip this song and dance if we're only
* doing block devices.
*/
if (tflag != NULL &&
strcmp(tflag, "blk") == 0)
continue;
t = strpbrk(s, ",");
if (t != 0)
*t = '\0';
spec = strdup(s + strlen(NFSMNTPT));
if (t != 0)
*t = ',';
if (spec == NULL)
errx(1, "Out of memory");
if (strlen(spec) == 0) {
warnx("empty mountpoint");
free((char *)spec);
continue;
}
snprintf(cmd, sizeof(cmd), "%s %s %s",
PATH_MOUNT, fp->fs_spec, spec);
if (system(cmd) != 0) {
warnx("%s: mount failed", fp->fs_spec);
continue;
}
} else {
/*
* Determine blk-ness.
*/
if (stat(spec, &st) < 0) {
warn("%s", spec);
continue;
}
if (S_ISBLK(st.st_mode))
isblk = 1;
}
/*
* Skip this type if we're told to.
*/
if (tflag != NULL) {
if (strcmp(tflag, "blk") == 0 && isblk == 0)
continue;
if (strcmp(tflag, "noblk") == 0 && isblk == 1)
continue;
}
if (swapctl(SWAP_ON, spec, (int)priority) < 0)
warn("%s", spec);
else {
gotone = 1;
printf("%s: adding %s as swap device at priority %d\n",
__progname, fp->fs_spec, (int)priority);
}
if (spec != fp->fs_spec)
free((char *)spec);
}
if (gotone == 0)
exit(1);
}
void
usage()
{
fprintf(stderr, "usage: %s -A [-p priority] [-t blk|noblk]\n",
__progname);
fprintf(stderr, " %s -a [-p priority] path\n", __progname);
fprintf(stderr, " %s -c -p priority path\n", __progname);
fprintf(stderr, " %s -d path\n", __progname);
fprintf(stderr, " %s -l | -s [-k]\n", __progname);
exit(1);
}