You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
tdeadmin/ksysv/leveldb.c

354 lines
8.4 KiB

/***************************************************************************
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;
}