summaryrefslogtreecommitdiffstats
path: root/ksysv/leveldb.c
diff options
context:
space:
mode:
Diffstat (limited to 'ksysv/leveldb.c')
-rw-r--r--ksysv/leveldb.c353
1 files changed, 353 insertions, 0 deletions
diff --git a/ksysv/leveldb.c b/ksysv/leveldb.c
new file mode 100644
index 0000000..149cb3b
--- /dev/null
+++ b/ksysv/leveldb.c
@@ -0,0 +1,353 @@
+/***************************************************************************
+ begin : Sun Oct 3 1999
+ copyright : Modifications (C) 1999 by Peter Putzer
+ email : putzer@kde.org
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#include <ctype.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <glob.h>
+#include <locale.h>
+#include <sys/mman.h>
+#include <sys/stat.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+
+/* Changes
+ 2000-08-04 - Peter Putzer <putzer@kde.org>
+ fixed compilation on *BSD (use GLOB_NOCHECK & strcmp instead of
+ checking for GLOB_NOMATCH)
+
+ 1999-04-11 - Peter Putzer <putzer@kde.org>
+ modified leveldb.h for use with C++
+
+ 1998-09-22 - Arnaldo Carvalho de Melo <acme@conectiva.com.br>
+ i18n for init.d scripts (eg.: description(pt_BR) is a brazilian
+ portuguese description for the package)
+*/
+
+#define _(String) String
+
+#include "leveldb.h"
+
+int parseLevels(const char* str, int emptyOk) {
+ const char* chptr = str;
+ int rc = 0;
+
+ if (!str || !strlen(str))
+ return emptyOk ? 0 : -1;
+
+ while (*chptr) {
+ if (!isdigit(*chptr) || *chptr > '6') return -1;
+ rc |= 1 << (*chptr - '0');
+ chptr++;
+ }
+
+ return rc;
+}
+
+int readServiceInfo(const char* RUNLEVELS, const char * name, struct service * service) {
+ char * filename = (char *) malloc(strlen(name) + strlen(RUNLEVELS) + 50);
+ int fd, i;
+ struct stat sb;
+ char * bufstart, * bufstop, * start, * end, * next;
+ struct service serv = { NULL, -1, -1, -1, NULL };
+ char overflow;
+ char english;
+ char is_my_lang = 0;
+ char levelbuf[20];
+ char * lang = getenv ("LANG"),
+ * final_parenthesis,
+ * english_desc = NULL;
+ char my_lang_loaded = 0;
+
+ sprintf(filename, "%s/init.d/%s", RUNLEVELS, name);
+
+ if ((fd = open(filename, O_RDONLY)) < 0)
+ {
+ free(filename);
+ return -1;
+ }
+ free(filename);
+ fstat(fd, &sb);
+
+ bufstart = mmap(NULL, sb.st_size, PROT_READ, MAP_SHARED, fd, 0);
+ if (bufstart == ((caddr_t) -1)) {
+ close(fd);
+ return -1;
+ }
+
+ bufstop = bufstart + sb.st_size;
+ close(fd);
+
+ next = bufstart;
+ while (next < bufstop && (serv.levels == -1 || !serv.desc)) {
+ start = next;
+
+ while (isspace(*start) && start < bufstop) start++;
+ if (start == bufstop) break;
+
+ end = strchr(start, '\n');
+ if (!end)
+ next = end = bufstop;
+ else
+ next = end + 1;
+
+ if (*start != '#') continue;
+
+ start++;
+ while (isspace(*start) && start < end) start++;
+ if (start == end) continue;
+
+ if (!strncmp(start, "chkconfig:", 10)) {
+ start += 10;
+ while (isspace(*start) && start < end) start++;
+ if (start == end) {
+ if (serv.desc) free(serv.desc);
+ munmap(bufstart, sb.st_size);
+ return 1;
+ }
+
+ if ((sscanf(start, "%19s %d %d%c", levelbuf,
+ &serv.sPriority, &serv.kPriority, &overflow) != 4) ||
+ overflow != '\n') {
+ if (serv.desc) free(serv.desc);
+ munmap(bufstart, sb.st_size);
+ return 1;
+ }
+
+ if (!strcmp(levelbuf, "-"))
+ serv.levels = 0;
+ else
+ serv.levels = parseLevels(levelbuf, 0);
+ if (serv.levels == -1) {
+ if (serv.desc) free(serv.desc);
+ munmap(bufstart, sb.st_size);
+ return 1;
+ }
+ } else if (!strncmp(start, "description", 11)) {
+ start += 11;
+
+ english = *start == ':';
+
+ if (!english) {
+ if (*start != '(') {
+ if (serv.desc) free(serv.desc);
+ munmap(bufstart, sb.st_size);
+ return 1;
+ }
+
+ ++start;
+ final_parenthesis = strchr (start, ')');
+
+ if (final_parenthesis == NULL || final_parenthesis - start > 5) {
+ if (serv.desc) free(serv.desc);
+ munmap(bufstart, sb.st_size);
+ return 1;
+ }
+
+ is_my_lang = lang ? strncmp (lang, start, strlen (lang)) == 0 : 0;
+ start = final_parenthesis + 2;
+ } else ++start;
+
+ while (isspace(*start) && start < end) start++;
+ if (start == end) {
+ munmap(bufstart, sb.st_size);
+ return 1;
+ }
+ {
+ char* desc = malloc(end - start + 1);
+ strncpy(desc, start, end - start);
+ desc[end - start] = '\0';
+
+ start = next;
+
+ while (desc[strlen(desc) - 1] == '\\') {
+ desc[strlen(desc) - 1] = '\0';
+ start = next;
+
+ while (isspace(*start) && start < bufstop) start++;
+ if (start == bufstop || *start != '#') {
+ munmap(bufstart, sb.st_size);
+ return 1;
+ }
+
+ start++;
+
+ while (isspace(*start) && start < bufstop) start++;
+ if (start == bufstop) {
+ munmap(bufstart, sb.st_size);
+ return 1;
+ }
+
+ end = strchr(start, '\n');
+ if (!end)
+ next = end = bufstop;
+ else
+ next = end + 1;
+
+ i = strlen(desc);
+ desc = realloc(desc, i + end - start + 1);
+ strncat(desc, start, end - start);
+ desc[i + end - start] = '\0';
+
+ start = next;
+ }
+
+ if (desc) {
+ if (my_lang_loaded) {
+ free(desc);
+ } else if (is_my_lang) {
+ if (serv.desc)
+ free(serv.desc);
+
+ serv.desc = desc;
+ break;
+ } else if (english) {
+ if (serv.desc)
+ free(serv.desc);
+
+ if (english_desc)
+ free (english_desc);
+
+ english_desc = desc;
+ } else free (desc);
+ }
+ }
+ }
+ }
+
+ munmap(bufstart, sb.st_size);
+
+ if (!serv.desc) {
+ if (english_desc)
+ serv.desc = english_desc;
+ } else if (english_desc)
+ free (english_desc);
+
+ if ((serv.levels == -1 ) || !serv.desc) {
+ return 1;
+ }
+
+ serv.name = strdup(name);
+
+ *service = serv;
+ return 0;
+}
+
+/* returns -1 on error */
+int currentRunlevel(void) {
+ FILE * p;
+ char response[50];
+
+ p = popen("/sbin/runlevel", "r");
+ if (!p) return -1;
+
+ if (!fgets(response, sizeof(response), p)) {
+ pclose(p);
+ return -1;
+ }
+
+ pclose(p);
+
+ if (response[1] != ' ' || !isdigit(response[2]) || response[3] != '\n')
+ return -1;
+
+ return response[2] - '0';
+}
+
+int findServiceEntries(const char* RUNLEVELS, const char* name, int level, glob_t * globresptr) {
+ char match[200];
+ glob_t globres;
+ int rc;
+
+ sprintf(match, "%s/rc%d.d/[SK][0-9][0-9]%s", RUNLEVELS, level, name);
+
+ rc = glob(match, GLOB_ERR | GLOB_NOSORT | GLOB_NOCHECK, NULL, &globres);
+
+ if (rc) {
+ fprintf(stderr, _("failed to glob pattern %s: %s\n"), match,
+ strerror(errno));
+ return 1;
+ } else if (!strcmp(match, globres.gl_pathv[0])) {
+ globresptr->gl_pathc = 0;
+ return 0;
+ }
+
+ *globresptr = globres;
+ return 0;
+}
+
+int isConfigured(const char* RUNLEVELS, const char* name, int level) {
+ glob_t globres;
+
+ if (findServiceEntries(RUNLEVELS, name, level, &globres))
+ exit(1);
+
+ if (!globres.gl_pathc)
+ return 0;
+
+ globfree(&globres);
+ return 1;
+}
+
+int isOn(const char* RUNLEVELS, const char* name, int level) {
+ glob_t globres;
+
+ if (level == -1) {
+ level = currentRunlevel();
+ if (level == -1) {
+ fprintf(stderr, _("cannot determine current run level\n"));
+ return 0;
+ }
+ }
+
+ if (findServiceEntries(RUNLEVELS, name, level, &globres))
+ exit(1);
+
+ if (!globres.gl_pathc || !strstr(globres.gl_pathv[0], "/S"))
+ return 0;
+
+ globfree(&globres);
+ return 1;
+}
+
+int doSetService(const char* RUNLEVELS, struct service s, int level, int on) {
+ int priority = on ? s.sPriority : s.kPriority;
+ char linkname[200];
+ char linkto[200];
+ glob_t globres;
+ int i;
+
+ if (!findServiceEntries(RUNLEVELS, s.name, level, &globres)) {
+ for (i = 0; (unsigned int) i < globres.gl_pathc; i++)
+ unlink(globres.gl_pathv[i]);
+ if (globres.gl_pathc) globfree(&globres);
+ }
+
+ sprintf(linkname, "%s/rc%d.d/%c%02d%s", RUNLEVELS, level,
+ on ? 'S' : 'K', priority, s.name);
+ sprintf(linkto, "../init.d/%s", s.name);
+
+ unlink(linkname); /* just in case */
+ if (symlink(linkto, linkname)) {
+ fprintf(stderr, _("failed to make symlink %s: %s\n"), linkname,
+ strerror(errno));
+ return 1;
+ }
+
+ return 0;
+}
+