aboutsummaryrefslogtreecommitdiff
path: root/sbin/chkconfig/chkconfig.c
diff options
context:
space:
mode:
Diffstat (limited to 'sbin/chkconfig/chkconfig.c')
-rw-r--r--sbin/chkconfig/chkconfig.c363
1 files changed, 363 insertions, 0 deletions
diff --git a/sbin/chkconfig/chkconfig.c b/sbin/chkconfig/chkconfig.c
new file mode 100644
index 000000000000..0c0f51da79d8
--- /dev/null
+++ b/sbin/chkconfig/chkconfig.c
@@ -0,0 +1,363 @@
+/*
+ * Copyright 1993, Garrett A. Wollman.
+ * Copyright 1993, University of Vermont and State Agricultural College.
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE UNIVERSITY AND 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 UNIVERSITY OR 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.
+ */
+
+const char chkconfig_c_rcsid[] =
+ "$Id: chkconfig.c,v 1.4 1993/11/12 03:54:24 wollman Exp $";
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <dirent.h>
+#include <errno.h>
+#include <string.h>
+#include "paths.h"
+
+static int testvalue(const char *);
+static int printflags(const char *);
+static int setvalue(const char *, int);
+static int printvalues(void);
+static void usage(void);
+static void die(const char *);
+static int is_on(const char *);
+
+const char *whoami;
+static const char *configdir = _PATH_CONFIG;
+static int sortbystate = 0;
+static int doflags = 0;
+static int force = 0;
+static int verbose = 0;
+
+int main(int argc, char **argv) {
+ int opt;
+
+ whoami = argv[0];
+
+ while((opt = getopt(argc, argv, "osfd:v")) != EOF) {
+ switch(opt) {
+ case 'o':
+ doflags = 1;
+ break;
+ case 's':
+ sortbystate = 1;
+ break;
+ case 'f':
+ force = 1;
+ break;
+ case 'd':
+ configdir = optarg;
+ break;
+ case 'v':
+ verbose = 1;
+ break;
+ case '?':
+ default:
+ usage();
+ return -1;
+ }
+ }
+
+ if(sortbystate && optind != argc) {
+ fprintf(stderr, "%s: -s: too many arguments\n", whoami);
+ usage();
+ return -1;
+ }
+
+ if(force && optind == argc) {
+ fprintf(stderr, "%s: -f: too few arguments\n", whoami);
+ usage();
+ return -1;
+ }
+
+ switch(argc - optind) {
+ case 0:
+ return printvalues();
+
+ case 1:
+ return doflags ? printflags(argv[optind]) : testvalue(argv[optind]);
+
+ case 2:
+ return setvalue(argv[optind], is_on(argv[optind + 1]));
+
+ default:
+ usage();
+ return -1;
+ }
+}
+
+static int is_on(const char *str) {
+ if(!str) return 0;
+ return ( ((str[0] == 'o') || (str[0] == 'O'))
+ && ((str[1] == 'n') || (str[1] == 'N'))
+ && ((str[2] == '\n')|| (str[2] == '\0')));
+}
+
+static void chat(const char *str, int state) {
+ if(verbose)
+ printf("`%s' is %s.\n", str, state ? "ON" : "OFF");
+}
+
+static const char *confname(const char *str, const char *str2) {
+ int len = strlen(configdir) + strlen(str) + strlen(str2) + 2;
+ char *rv = malloc(len);
+
+ if(!rv) {
+ errno = ENOMEM;
+ die("confname: malloc");
+ }
+
+ strcpy(rv, configdir);
+ strcat(rv, "/");
+ strcat(rv, str);
+ strcat(rv, str2);
+ return rv;
+}
+
+static int testvalue(const char *str) {
+ FILE *fp;
+ char *line;
+ const char *fname;
+ int rv = 1; /* NB: shell's convention is opposite C's */
+
+ fname = confname(str, "");
+ fp = fopen(fname, "r");
+ if(fp) {
+ do {
+ line = fgetline(fp, (size_t *)0);
+ } while(line && line[0] == '#');
+ rv = !is_on(line); /* shell's convention is opposite C's */
+ fclose(fp);
+ }
+
+ free((void *)fname); /* cast away `const' to avoid warning */
+ chat(str, !rv); /* tell the user about it if verbose */
+ return rv;
+}
+
+static char *getflags(const char *str) {
+ FILE *fp;
+ char *line;
+ const char *fname;
+ char *rv = strdup("");
+
+ if(!rv) {
+ errno = ENOMEM;
+ die("getflags: strdup");
+ }
+
+ fname = confname(str, ".flags");
+ fp = fopen(fname, "r");
+ if(fp) {
+ do {
+ line = fgetline(fp, (size_t *)0);
+ } while(line && line[0] == '#');
+
+ if(line) {
+ free(rv);
+ rv = strdup(line);
+
+ if(!rv) {
+ errno = ENOMEM;
+ die("getflags: strdup");
+ }
+ }
+
+ fclose(fp);
+ }
+ free((void *)fname);
+
+ return rv;
+}
+
+
+static int printflags(const char *str) {
+ int rv = 0;
+ char *flags;
+
+ flags = getflags(str);
+ if(flags[0]) printf("%s\n", flags);
+ free(flags);
+ return 0;
+}
+
+static int setvalue(const char *str, int state) {
+ FILE *fp;
+ const char *fname;
+
+ fname = confname(str, "");
+ errno = 0;
+ fp = fopen(fname, "r");
+ if(!fp && !force) {
+ /*
+ * Yes, I know this is bogus, but SGI must have had some sort of
+ * reason...
+ */
+ if(errno == ENOENT) {
+ fprintf(stderr,
+ "%s: configuration file does not exist;"
+ " use `-f' flag to create it.\n", whoami);
+ return -1;
+ } else {
+ die(fname);
+ }
+ }
+
+ if(fp)
+ fclose(fp);
+
+ errno = 0;
+ fp = fopen(fname, "w");
+ if(!fp)
+ die(fname);
+
+ fprintf(fp, "%s\n", state ? "on" : "off");
+
+ fclose(fp);
+
+ chat(str, state);
+ return 0;
+}
+
+/*
+ * From here down is the code for listing the value of every option.
+ */
+struct q {
+ struct q *next;
+ int state;
+ char *name;
+ char *flags;
+};
+
+static struct q *onhead;
+static struct q *offhead; /* only used for sortbystate == 1 */
+
+static void insert(const char *fname) {
+ struct q *q;
+ struct q **headp;
+ int state;
+
+ q = malloc(sizeof *q);
+ if(!q) {
+ errno = ENOMEM;
+ die("insert: malloc");
+ }
+
+ q->name = strdup(fname);
+ q->state = state = !testvalue(fname);
+ q->flags = getflags(fname);
+
+ if(state || !sortbystate)
+ headp = &onhead;
+ else
+ headp = &offhead;
+
+ while(*headp && strcmp(q->name, (**headp).name) > 0) {
+ headp = &(**headp).next;
+ }
+
+ q->next = *headp;
+ *headp = q;
+}
+
+static int printvalues(void) {
+ struct q *temp;
+ DIR *dir;
+ struct dirent *entry;
+ struct stat stab;
+ int doneheader = 0;
+
+ verbose = 0; /* we're already verbose enough */
+
+ errno = 0;
+ dir = opendir(configdir);
+ if(!dir)
+ die(configdir);
+
+ while((entry = readdir(dir))) {
+ if(stat(entry->d_name, &stab) < 0) {
+ die(entry->d_name);
+ }
+
+ if(S_ISREG(stab.st_mode) && !strchr(entry->d_name, '.')) {
+ insert(entry->d_name);
+ }
+ }
+
+ closedir(dir);
+
+ /*
+ * Now we're done reading the file names, so we can print them out.
+ * Thanks to insert(), everything is already in ASCII order.
+ */
+#define FORMAT "%15s %-5s %s\n"
+
+ if(sortbystate) {
+ printf("%15s %s %s\n",
+ "Option", "State", "Flags");
+ printf("%15s %s %s\n",
+ "===============", "=====", "====================");
+ doneheader = 1;
+
+ while((temp = offhead)) {
+ printf(FORMAT, temp->name, "off", temp->flags);
+ free(temp->name);
+ free(temp->flags);
+ offhead = temp->next;
+ free(temp);
+ }
+ }
+
+ if(!doneheader) {
+ printf("%15s %s %s\n", "Option", "State", "Flags");
+ printf("%15s %s %s\n",
+ "===============", "=====", "====================");
+ }
+
+ while((temp = onhead)) {
+ printf(FORMAT, temp->name, temp->state ? "on" : "off", temp->flags);
+ free(temp->name);
+ free(temp->flags);
+ onhead = temp->next;
+ free(temp);
+ }
+
+ return 0;
+}
+
+
+static void die(const char *why) {
+ fprintf(stderr, "%s: %s: %s\n", whoami, why, strerror(errno));
+ exit(-1);
+}
+
+static void usage(void) {
+ fprintf(stderr, "%s: usage:\n"
+ "%s [ -d configdir ] [ -s ]\n"
+ "%s [ -d configdir ] option\n"
+ "%s [ -d configdir ] [ -f ] option [ on | off ]\n",
+ whoami, whoami, whoami, whoami);
+}