2008-01-14 19:54:20 +05:30
|
|
|
/*
|
2009-04-24 03:01:22 +05:30
|
|
|
rc-applets.c
|
2008-01-14 19:54:20 +05:30
|
|
|
|
2009-04-24 03:01:22 +05:30
|
|
|
Handle multicall applets for use in our init scripts.
|
|
|
|
Basically this makes us a lot faster for the most part, and removes
|
|
|
|
any shell incompatabilities we might otherwise encounter.
|
|
|
|
*/
|
2008-01-14 19:54:20 +05:30
|
|
|
|
|
|
|
/*
|
2009-05-01 19:41:40 +05:30
|
|
|
* Copyright (c) 2007-2009 Roy Marples <roy@marples.name>
|
2011-06-30 05:16:31 +05:30
|
|
|
*
|
2008-01-14 19:54:20 +05:30
|
|
|
* 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 AUTHOR AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#define SYSLOG_NAMES
|
|
|
|
|
|
|
|
#include <sys/types.h>
|
2008-06-04 19:39:25 +05:30
|
|
|
#include <sys/time.h>
|
2008-03-16 22:30:56 +05:30
|
|
|
|
2008-01-14 19:54:20 +05:30
|
|
|
#include <errno.h>
|
|
|
|
#include <ctype.h>
|
2008-01-22 16:37:39 +05:30
|
|
|
#include <inttypes.h>
|
2008-01-14 19:54:20 +05:30
|
|
|
#include <stdbool.h>
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <signal.h>
|
|
|
|
#include <string.h>
|
|
|
|
#include <syslog.h>
|
2008-06-04 19:39:25 +05:30
|
|
|
#include <time.h>
|
2008-01-14 19:54:20 +05:30
|
|
|
#include <unistd.h>
|
|
|
|
|
|
|
|
#include "builtins.h"
|
|
|
|
#include "einfo.h"
|
|
|
|
#include "rc-misc.h"
|
|
|
|
|
2008-06-03 17:27:15 +05:30
|
|
|
/* usecs to wait while we poll the file existance */
|
|
|
|
#define WAIT_INTERVAL 20000000
|
|
|
|
#define ONE_SECOND 690000000
|
|
|
|
|
2008-01-14 19:54:20 +05:30
|
|
|
/* Applet is first parsed in rc.c - no point in doing it again */
|
|
|
|
extern const char *applet;
|
|
|
|
|
2009-04-24 03:01:22 +05:30
|
|
|
static int
|
|
|
|
syslog_decode(char *name, CODE *codetab)
|
2008-01-14 19:54:20 +05:30
|
|
|
{
|
|
|
|
CODE *c;
|
|
|
|
|
2008-04-17 15:49:58 +05:30
|
|
|
if (isdigit((unsigned char)*name))
|
2008-03-16 22:30:56 +05:30
|
|
|
return atoi(name);
|
2008-01-14 19:54:20 +05:30
|
|
|
|
|
|
|
for (c = codetab; c->c_name; c++)
|
2008-03-16 22:30:56 +05:30
|
|
|
if (! strcasecmp(name, c->c_name))
|
|
|
|
return c->c_val;
|
2008-01-14 19:54:20 +05:30
|
|
|
|
2008-03-16 22:30:56 +05:30
|
|
|
return -1;
|
2008-01-14 19:54:20 +05:30
|
|
|
}
|
|
|
|
|
2009-04-24 03:01:22 +05:30
|
|
|
static int
|
|
|
|
do_e(int argc, char **argv)
|
2008-01-14 19:54:20 +05:30
|
|
|
{
|
|
|
|
int retval = EXIT_SUCCESS;
|
|
|
|
int i;
|
2008-01-22 16:37:39 +05:30
|
|
|
size_t l = 0;
|
2008-01-14 19:54:20 +05:30
|
|
|
char *message = NULL;
|
|
|
|
char *p;
|
|
|
|
int level = 0;
|
2008-06-03 17:27:15 +05:30
|
|
|
struct timespec ts;
|
|
|
|
struct timeval stop, now;
|
2008-10-08 21:26:47 +05:30
|
|
|
int (*e) (const char *, ...) EINFO_PRINTF(1, 2) = NULL;
|
|
|
|
int (*ee) (int, const char *, ...) EINFO_PRINTF(2, 3) = NULL;
|
2008-01-14 19:54:20 +05:30
|
|
|
|
|
|
|
/* Punt applet */
|
|
|
|
argc--;
|
|
|
|
argv++;
|
|
|
|
|
2008-03-16 22:30:56 +05:30
|
|
|
if (strcmp(applet, "eval_ecolors") == 0) {
|
|
|
|
printf("GOOD='%s'\nWARN='%s'\nBAD='%s'\nHILITE='%s'\nBRACKET='%s'\nNORMAL='%s'\n",
|
2009-04-24 03:01:22 +05:30
|
|
|
ecolor(ECOLOR_GOOD),
|
|
|
|
ecolor(ECOLOR_WARN),
|
|
|
|
ecolor(ECOLOR_BAD),
|
|
|
|
ecolor(ECOLOR_HILITE),
|
|
|
|
ecolor(ECOLOR_BRACKET),
|
|
|
|
ecolor(ECOLOR_NORMAL));
|
2008-03-16 22:30:56 +05:30
|
|
|
exit(EXIT_SUCCESS);
|
2008-01-14 19:54:20 +05:30
|
|
|
}
|
|
|
|
|
|
|
|
if (argc > 0) {
|
2008-03-16 22:30:56 +05:30
|
|
|
if (strcmp(applet, "eend") == 0 ||
|
|
|
|
strcmp(applet, "ewend") == 0 ||
|
|
|
|
strcmp(applet, "veend") == 0 ||
|
2008-06-03 17:27:15 +05:30
|
|
|
strcmp(applet, "vweend") == 0 ||
|
|
|
|
strcmp(applet, "ewaitfile") == 0)
|
2008-01-14 19:54:20 +05:30
|
|
|
{
|
|
|
|
errno = 0;
|
2008-06-03 17:27:15 +05:30
|
|
|
retval = (int)strtoimax(argv[0], &p, 0);
|
|
|
|
if (!p || *p != '\0')
|
|
|
|
errno = EINVAL;
|
|
|
|
if (errno)
|
2008-01-14 19:54:20 +05:30
|
|
|
retval = EXIT_FAILURE;
|
|
|
|
else {
|
|
|
|
argc--;
|
|
|
|
argv++;
|
|
|
|
}
|
2008-03-16 22:30:56 +05:30
|
|
|
} else if (strcmp(applet, "esyslog") == 0 ||
|
2009-04-24 03:01:22 +05:30
|
|
|
strcmp(applet, "elog") == 0) {
|
2008-03-16 22:30:56 +05:30
|
|
|
p = strchr(argv[0], '.');
|
2009-04-24 03:01:22 +05:30
|
|
|
if (!p ||
|
|
|
|
(level = syslog_decode(p + 1, prioritynames)) == -1)
|
2008-03-16 22:30:56 +05:30
|
|
|
eerrorx("%s: invalid log level `%s'", applet, argv[0]);
|
2008-01-14 19:54:20 +05:30
|
|
|
|
|
|
|
if (argc < 3)
|
2008-03-16 22:30:56 +05:30
|
|
|
eerrorx("%s: not enough arguments", applet);
|
2008-01-14 19:54:20 +05:30
|
|
|
|
2008-03-16 22:30:56 +05:30
|
|
|
unsetenv("EINFO_LOG");
|
|
|
|
setenv("EINFO_LOG", argv[1], 1);
|
2008-01-14 19:54:20 +05:30
|
|
|
|
|
|
|
argc -= 2;
|
|
|
|
argv += 2;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-06-03 17:27:15 +05:30
|
|
|
if (strcmp(applet, "ewaitfile") == 0) {
|
|
|
|
if (errno)
|
|
|
|
eerrorx("%s: invalid timeout", applet);
|
|
|
|
if (argc == 0)
|
|
|
|
eerrorx("%s: not enough arguments", applet);
|
|
|
|
|
|
|
|
gettimeofday(&stop, NULL);
|
|
|
|
/* retval stores the timeout */
|
|
|
|
stop.tv_sec += retval;
|
|
|
|
ts.tv_sec = 0;
|
|
|
|
ts.tv_nsec = WAIT_INTERVAL;
|
|
|
|
for (i = 0; i < argc; i++) {
|
|
|
|
ebeginv("Waiting for %s", argv[i]);
|
2011-01-17 15:19:07 +05:30
|
|
|
for (;;) {
|
2008-06-03 17:27:15 +05:30
|
|
|
if (exists(argv[i]))
|
|
|
|
break;
|
|
|
|
if (nanosleep(&ts, NULL) == -1)
|
|
|
|
return EXIT_FAILURE;
|
|
|
|
gettimeofday(&now, NULL);
|
|
|
|
if (retval <= 0)
|
|
|
|
continue;
|
|
|
|
if (timercmp(&now, &stop, <))
|
|
|
|
continue;
|
|
|
|
eendv(EXIT_FAILURE,
|
2009-04-24 03:01:22 +05:30
|
|
|
"timed out waiting for %s", argv[i]);
|
2008-06-03 17:27:15 +05:30
|
|
|
return EXIT_FAILURE;
|
|
|
|
}
|
|
|
|
eendv(EXIT_SUCCESS, NULL);
|
|
|
|
}
|
|
|
|
return EXIT_SUCCESS;
|
|
|
|
}
|
|
|
|
|
2008-01-14 19:54:20 +05:30
|
|
|
if (argc > 0) {
|
|
|
|
for (i = 0; i < argc; i++)
|
2008-03-16 22:30:56 +05:30
|
|
|
l += strlen(argv[i]) + 1;
|
2008-01-14 19:54:20 +05:30
|
|
|
|
2008-03-16 22:30:56 +05:30
|
|
|
message = xmalloc(l);
|
2008-01-14 19:54:20 +05:30
|
|
|
p = message;
|
|
|
|
|
|
|
|
for (i = 0; i < argc; i++) {
|
|
|
|
if (i > 0)
|
|
|
|
*p++ = ' ';
|
2008-03-16 22:30:56 +05:30
|
|
|
l = strlen(argv[i]);
|
|
|
|
memcpy(p, argv[i], l);
|
|
|
|
p += l;
|
2008-01-14 19:54:20 +05:30
|
|
|
}
|
|
|
|
*p = 0;
|
|
|
|
}
|
|
|
|
|
2008-03-16 22:30:56 +05:30
|
|
|
if (strcmp(applet, "einfo") == 0)
|
2008-09-18 18:39:51 +05:30
|
|
|
e = einfo;
|
2008-03-16 22:30:56 +05:30
|
|
|
else if (strcmp(applet, "einfon") == 0)
|
2008-09-18 18:39:51 +05:30
|
|
|
e = einfon;
|
2008-03-16 22:30:56 +05:30
|
|
|
else if (strcmp(applet, "ewarn") == 0)
|
2008-09-18 18:39:51 +05:30
|
|
|
e = ewarn;
|
2008-03-16 22:30:56 +05:30
|
|
|
else if (strcmp(applet, "ewarnn") == 0)
|
2008-09-18 18:39:51 +05:30
|
|
|
e = ewarnn;
|
2008-03-16 22:30:56 +05:30
|
|
|
else if (strcmp(applet, "eerror") == 0) {
|
2008-09-18 18:39:51 +05:30
|
|
|
e = eerror;
|
2008-01-14 19:54:20 +05:30
|
|
|
retval = 1;
|
2008-03-16 22:30:56 +05:30
|
|
|
} else if (strcmp(applet, "eerrorn") == 0) {
|
2008-09-18 18:39:51 +05:30
|
|
|
e = eerrorn;
|
2008-01-14 19:54:20 +05:30
|
|
|
retval = 1;
|
2008-03-16 22:30:56 +05:30
|
|
|
} else if (strcmp(applet, "ebegin") == 0)
|
2008-09-18 18:39:51 +05:30
|
|
|
e = ebegin;
|
2008-03-16 22:30:56 +05:30
|
|
|
else if (strcmp(applet, "eend") == 0)
|
2008-09-18 18:39:51 +05:30
|
|
|
ee = eend;
|
2008-03-16 22:30:56 +05:30
|
|
|
else if (strcmp(applet, "ewend") == 0)
|
2008-09-18 18:39:51 +05:30
|
|
|
ee = ewend;
|
2008-10-08 21:26:47 +05:30
|
|
|
else if (strcmp(applet, "esyslog") == 0) {
|
|
|
|
elog(retval, "%s", message);
|
|
|
|
retval = 0;
|
|
|
|
} else if (strcmp(applet, "veinfo") == 0)
|
2008-09-18 18:39:51 +05:30
|
|
|
e = einfov;
|
2008-03-16 22:30:56 +05:30
|
|
|
else if (strcmp(applet, "veinfon") == 0)
|
2008-09-18 18:39:51 +05:30
|
|
|
e = einfovn;
|
2008-03-16 22:30:56 +05:30
|
|
|
else if (strcmp(applet, "vewarn") == 0)
|
2008-09-18 18:39:51 +05:30
|
|
|
e = ewarnv;
|
2008-03-16 22:30:56 +05:30
|
|
|
else if (strcmp(applet, "vewarnn") == 0)
|
2008-09-18 18:39:51 +05:30
|
|
|
e = ewarnvn;
|
2008-03-16 22:30:56 +05:30
|
|
|
else if (strcmp(applet, "vebegin") == 0)
|
2008-09-18 18:39:51 +05:30
|
|
|
e = ebeginv;
|
2008-03-16 22:30:56 +05:30
|
|
|
else if (strcmp(applet, "veend") == 0)
|
2008-09-18 18:39:51 +05:30
|
|
|
ee = eendv;
|
2008-03-16 22:30:56 +05:30
|
|
|
else if (strcmp(applet, "vewend") == 0)
|
2008-09-18 18:39:51 +05:30
|
|
|
ee = ewendv;
|
2008-03-16 22:30:56 +05:30
|
|
|
else if (strcmp(applet, "eindent") == 0)
|
|
|
|
eindent();
|
|
|
|
else if (strcmp(applet, "eoutdent") == 0)
|
|
|
|
eoutdent();
|
|
|
|
else if (strcmp(applet, "veindent") == 0)
|
|
|
|
eindentv();
|
|
|
|
else if (strcmp(applet, "veoutdent") == 0)
|
|
|
|
eoutdentv();
|
2008-01-14 19:54:20 +05:30
|
|
|
else {
|
2008-03-16 22:30:56 +05:30
|
|
|
eerror("%s: unknown applet", applet);
|
2008-01-14 19:54:20 +05:30
|
|
|
retval = EXIT_FAILURE;
|
|
|
|
}
|
|
|
|
|
2008-09-18 18:39:51 +05:30
|
|
|
if (message) {
|
|
|
|
if (e)
|
|
|
|
e("%s", message);
|
|
|
|
else if (ee)
|
|
|
|
ee(retval, "%s", message);
|
|
|
|
} else {
|
|
|
|
if (e)
|
|
|
|
e(NULL);
|
|
|
|
else if (ee)
|
|
|
|
ee(retval, NULL);
|
|
|
|
}
|
|
|
|
|
2008-03-16 22:30:56 +05:30
|
|
|
free(message);
|
|
|
|
return retval;
|
2008-01-14 19:54:20 +05:30
|
|
|
}
|
|
|
|
|
2012-05-06 05:58:28 +05:30
|
|
|
static const struct {
|
|
|
|
const char * const name;
|
|
|
|
RC_SERVICE bit;
|
|
|
|
} service_bits[] = {
|
|
|
|
{ "service_started", RC_SERVICE_STARTED, },
|
|
|
|
{ "service_stopped", RC_SERVICE_STOPPED, },
|
|
|
|
{ "service_inactive", RC_SERVICE_INACTIVE, },
|
|
|
|
{ "service_starting", RC_SERVICE_STARTING, },
|
|
|
|
{ "service_stopping", RC_SERVICE_STOPPING, },
|
|
|
|
{ "service_hotplugged", RC_SERVICE_HOTPLUGGED, },
|
|
|
|
{ "service_wasinactive", RC_SERVICE_WASINACTIVE, },
|
|
|
|
{ "service_failed", RC_SERVICE_FAILED, },
|
|
|
|
};
|
|
|
|
|
|
|
|
static RC_SERVICE
|
|
|
|
lookup_service_state(const char *service)
|
|
|
|
{
|
|
|
|
size_t i;
|
|
|
|
for (i = 0; i < ARRAY_SIZE(service_bits); ++i)
|
|
|
|
if (!strcmp(service, service_bits[i].name))
|
|
|
|
return service_bits[i].bit;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2009-04-24 03:01:22 +05:30
|
|
|
static int
|
|
|
|
do_service(int argc, char **argv)
|
2008-01-14 19:54:20 +05:30
|
|
|
{
|
|
|
|
bool ok = false;
|
2008-07-27 17:00:49 +05:30
|
|
|
char *service;
|
|
|
|
char *exec;
|
2012-05-06 05:58:28 +05:30
|
|
|
int idx;
|
|
|
|
RC_SERVICE state, bit;
|
2008-01-14 19:54:20 +05:30
|
|
|
|
|
|
|
if (argc > 1)
|
|
|
|
service = argv[1];
|
|
|
|
else
|
2008-03-20 01:27:24 +05:30
|
|
|
service = getenv("RC_SVCNAME");
|
2008-01-14 19:54:20 +05:30
|
|
|
|
2009-04-24 03:01:22 +05:30
|
|
|
if (service == NULL || *service == '\0')
|
2008-03-16 22:30:56 +05:30
|
|
|
eerrorx("%s: no service specified", applet);
|
|
|
|
|
2012-05-06 05:58:28 +05:30
|
|
|
state = rc_service_state(service);
|
2012-05-17 03:46:04 +05:30
|
|
|
bit = lookup_service_state(applet);
|
2012-05-06 05:58:28 +05:30
|
|
|
if (bit) {
|
|
|
|
ok = (state & bit);
|
|
|
|
} else if (strcmp(applet, "service_started_daemon") == 0) {
|
2008-03-20 01:27:24 +05:30
|
|
|
service = getenv("RC_SVCNAME");
|
2008-07-27 17:00:49 +05:30
|
|
|
exec = argv[1];
|
2008-01-14 19:54:20 +05:30
|
|
|
if (argc > 3) {
|
2008-01-28 18:46:33 +05:30
|
|
|
service = argv[1];
|
2008-07-27 17:00:49 +05:30
|
|
|
exec = argv[2];
|
2008-03-16 22:30:56 +05:30
|
|
|
sscanf(argv[3], "%d", &idx);
|
2008-01-14 19:54:20 +05:30
|
|
|
} else if (argc == 3) {
|
2008-03-16 22:30:56 +05:30
|
|
|
if (sscanf(argv[2], "%d", &idx) != 1) {
|
2008-01-28 18:46:33 +05:30
|
|
|
service = argv[1];
|
2008-07-27 17:00:49 +05:30
|
|
|
exec = argv[2];
|
2008-01-28 18:46:33 +05:30
|
|
|
}
|
2008-01-14 19:54:20 +05:30
|
|
|
}
|
2008-07-27 17:00:49 +05:30
|
|
|
ok = rc_service_started_daemon(service, exec, NULL, idx);
|
2011-01-17 13:58:43 +05:30
|
|
|
|
2009-04-18 05:39:03 +05:30
|
|
|
} else if (strcmp(applet, "service_crashed") == 0) {
|
|
|
|
ok = (_rc_can_find_pids() &&
|
2009-04-24 03:01:22 +05:30
|
|
|
rc_service_daemons_crashed(service) &&
|
|
|
|
errno != EACCES);
|
2008-01-14 19:54:20 +05:30
|
|
|
} else
|
2008-03-16 22:30:56 +05:30
|
|
|
eerrorx("%s: unknown applet", applet);
|
2008-01-14 19:54:20 +05:30
|
|
|
|
2008-03-16 22:30:56 +05:30
|
|
|
return ok ? EXIT_SUCCESS : EXIT_FAILURE;
|
2008-01-14 19:54:20 +05:30
|
|
|
}
|
|
|
|
|
2009-04-24 03:01:22 +05:30
|
|
|
static int
|
|
|
|
do_mark_service(int argc, char **argv)
|
2008-01-14 19:54:20 +05:30
|
|
|
{
|
|
|
|
bool ok = false;
|
2008-03-20 01:27:24 +05:30
|
|
|
char *svcname = getenv("RC_SVCNAME");
|
2008-01-14 19:54:20 +05:30
|
|
|
char *service = NULL;
|
2008-03-16 22:30:56 +05:30
|
|
|
char *runscript_pid;
|
2012-04-26 13:46:56 +05:30
|
|
|
/* char *mtime; */
|
2008-03-16 22:30:56 +05:30
|
|
|
pid_t pid;
|
2012-05-06 05:58:28 +05:30
|
|
|
RC_SERVICE bit;
|
2012-04-26 13:46:56 +05:30
|
|
|
/* size_t l; */
|
2008-01-14 19:54:20 +05:30
|
|
|
|
|
|
|
if (argc > 1)
|
|
|
|
service = argv[1];
|
|
|
|
else
|
2012-04-24 07:19:04 +05:30
|
|
|
service = svcname;
|
2008-01-14 19:54:20 +05:30
|
|
|
|
2009-04-24 03:01:22 +05:30
|
|
|
if (service == NULL || *service == '\0')
|
2008-03-16 22:30:56 +05:30
|
|
|
eerrorx("%s: no service specified", applet);
|
|
|
|
|
2012-05-24 05:02:01 +05:30
|
|
|
if (!strncmp(applet, "mark_", 5) &&
|
2012-05-06 05:58:28 +05:30
|
|
|
(bit = lookup_service_state(applet + 5)))
|
|
|
|
ok = rc_service_mark(service, bit);
|
2008-01-14 19:54:20 +05:30
|
|
|
else
|
2008-03-16 22:30:56 +05:30
|
|
|
eerrorx("%s: unknown applet", applet);
|
2008-01-14 19:54:20 +05:30
|
|
|
|
2009-04-24 03:01:22 +05:30
|
|
|
/* If we're marking ourselves then we need to inform our parent
|
|
|
|
runscript process so they do not mark us based on our exit code */
|
2012-04-26 13:46:56 +05:30
|
|
|
/*
|
|
|
|
* FIXME: svcname and service are almost always equal except called from a
|
|
|
|
* shell with just argv[1] - So that doesn't seem to do what Roy initially
|
|
|
|
* expected.
|
|
|
|
* See 20120424041423.GA23657@odin.qasl.de (Tue, 24 Apr 2012 06:14:23 +0200,
|
|
|
|
* openrc@gentoo.org).
|
|
|
|
*/
|
2008-03-16 22:30:56 +05:30
|
|
|
if (ok && svcname && strcmp(svcname, service) == 0) {
|
|
|
|
runscript_pid = getenv("RC_RUNSCRIPT_PID");
|
|
|
|
if (runscript_pid && sscanf(runscript_pid, "%d", &pid) == 1)
|
|
|
|
if (kill(pid, SIGHUP) != 0)
|
|
|
|
eerror("%s: failed to signal parent %d: %s",
|
2009-04-24 03:01:22 +05:30
|
|
|
applet, pid, strerror(errno));
|
2008-01-14 19:54:20 +05:30
|
|
|
|
|
|
|
/* Remove the exclusive time test. This ensures that it's not
|
|
|
|
in control as well */
|
2012-04-26 13:46:56 +05:30
|
|
|
/*
|
2008-03-25 23:50:23 +05:30
|
|
|
l = strlen(RC_SVCDIR "/exclusive") + strlen(svcname) +
|
2009-04-24 03:01:22 +05:30
|
|
|
strlen(runscript_pid) + 4;
|
2008-03-16 22:30:56 +05:30
|
|
|
mtime = xmalloc(l);
|
2008-03-25 23:50:23 +05:30
|
|
|
snprintf(mtime, l, RC_SVCDIR "/exclusive/%s.%s",
|
2009-04-24 03:01:22 +05:30
|
|
|
svcname, runscript_pid);
|
2008-03-16 22:30:56 +05:30
|
|
|
if (exists(mtime) && unlink(mtime) != 0)
|
|
|
|
eerror("%s: unlink: %s", applet, strerror(errno));
|
|
|
|
free(mtime);
|
2012-04-26 13:46:56 +05:30
|
|
|
*/
|
2008-01-14 19:54:20 +05:30
|
|
|
}
|
|
|
|
|
2008-03-16 22:30:56 +05:30
|
|
|
return ok ? EXIT_SUCCESS : EXIT_FAILURE;
|
2008-01-14 19:54:20 +05:30
|
|
|
}
|
|
|
|
|
2009-04-24 03:01:22 +05:30
|
|
|
static int
|
|
|
|
do_value(int argc, char **argv)
|
2008-01-14 19:54:20 +05:30
|
|
|
{
|
|
|
|
bool ok = false;
|
2008-03-20 01:27:24 +05:30
|
|
|
char *service = getenv("RC_SVCNAME");
|
2008-03-16 22:30:56 +05:30
|
|
|
char *option;
|
2008-01-14 19:54:20 +05:30
|
|
|
|
2009-04-24 03:01:22 +05:30
|
|
|
if (service == NULL)
|
2008-03-16 22:30:56 +05:30
|
|
|
eerrorx("%s: no service specified", applet);
|
2008-01-14 19:54:20 +05:30
|
|
|
|
2008-01-21 21:00:40 +05:30
|
|
|
if (argc < 2 || ! argv[1] || *argv[1] == '\0')
|
2008-03-16 22:30:56 +05:30
|
|
|
eerrorx("%s: no option specified", applet);
|
2008-01-14 19:54:20 +05:30
|
|
|
|
2008-03-16 22:30:56 +05:30
|
|
|
if (strcmp(applet, "service_get_value") == 0 ||
|
|
|
|
strcmp(applet, "get_options") == 0)
|
2008-01-14 19:54:20 +05:30
|
|
|
{
|
2008-03-16 22:30:56 +05:30
|
|
|
option = rc_service_value_get(service, argv[1]);
|
2008-01-14 19:54:20 +05:30
|
|
|
if (option) {
|
2008-03-16 22:30:56 +05:30
|
|
|
printf("%s", option);
|
|
|
|
free(option);
|
2008-01-14 19:54:20 +05:30
|
|
|
ok = true;
|
|
|
|
}
|
2008-03-16 22:30:56 +05:30
|
|
|
} else if (strcmp(applet, "service_set_value") == 0 ||
|
2009-04-24 03:01:22 +05:30
|
|
|
strcmp(applet, "save_options") == 0)
|
2008-03-16 22:30:56 +05:30
|
|
|
ok = rc_service_value_set(service, argv[1], argv[2]);
|
2008-01-14 19:54:20 +05:30
|
|
|
else
|
2008-03-16 22:30:56 +05:30
|
|
|
eerrorx("%s: unknown applet", applet);
|
2008-01-14 19:54:20 +05:30
|
|
|
|
2008-03-16 22:30:56 +05:30
|
|
|
return ok ? EXIT_SUCCESS : EXIT_FAILURE;
|
2008-01-14 19:54:20 +05:30
|
|
|
}
|
|
|
|
|
2009-04-24 03:01:22 +05:30
|
|
|
static int
|
2012-05-06 05:58:28 +05:30
|
|
|
shell_var(int argc, char **argv)
|
2008-01-14 19:54:20 +05:30
|
|
|
{
|
|
|
|
int i;
|
2008-03-16 22:30:56 +05:30
|
|
|
char *p;
|
|
|
|
int c;
|
2008-01-14 19:54:20 +05:30
|
|
|
|
|
|
|
for (i = 1; i < argc; i++) {
|
2008-03-16 22:30:56 +05:30
|
|
|
p = argv[i];
|
2008-01-14 21:47:03 +05:30
|
|
|
if (i != 1)
|
2008-03-16 22:30:56 +05:30
|
|
|
putchar(' ');
|
2008-01-14 19:54:20 +05:30
|
|
|
while (*p) {
|
2008-04-17 15:49:58 +05:30
|
|
|
c = (unsigned char)*p++;
|
2008-03-16 22:30:56 +05:30
|
|
|
if (! isalnum(c))
|
2008-01-14 19:54:20 +05:30
|
|
|
c = '_';
|
2008-03-16 22:30:56 +05:30
|
|
|
putchar(c);
|
2008-01-14 19:54:20 +05:30
|
|
|
}
|
|
|
|
}
|
2008-03-16 22:30:56 +05:30
|
|
|
putchar('\n');
|
|
|
|
return EXIT_SUCCESS;
|
2008-01-14 19:54:20 +05:30
|
|
|
}
|
|
|
|
|
2012-05-06 05:58:28 +05:30
|
|
|
static int
|
|
|
|
is_older_than(int argc, char **argv)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
|
|
|
|
if (argc < 3)
|
|
|
|
return EXIT_FAILURE;
|
|
|
|
|
|
|
|
/* This test is perverted - historically the baselayout function
|
|
|
|
* returns 0 on *failure*, which is plain wrong */
|
|
|
|
for (i = 2; i < argc; ++i)
|
|
|
|
if (!rc_newer_than(argv[1], argv[i], NULL, NULL))
|
|
|
|
return EXIT_SUCCESS;
|
|
|
|
|
|
|
|
return EXIT_FAILURE;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
is_newer_than(int argc, char **argv)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
|
|
|
|
if (argc < 3)
|
|
|
|
return EXIT_FAILURE;
|
|
|
|
|
|
|
|
/* This test is correct as it's not present in baselayout */
|
|
|
|
for (i = 2; i < argc; ++i)
|
|
|
|
if (!rc_newer_than(argv[1], argv[i], NULL, NULL))
|
|
|
|
return EXIT_FAILURE;
|
|
|
|
|
|
|
|
return EXIT_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
is_runlevel_start(_unused int argc, _unused char **argv)
|
|
|
|
{
|
|
|
|
return rc_runlevel_starting() ? 0 : 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
is_runlevel_stop(_unused int argc, _unused char **argv)
|
|
|
|
{
|
|
|
|
return rc_runlevel_stopping() ? 0 : 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
rc_abort(_unused int argc, _unused char **argv)
|
|
|
|
{
|
|
|
|
const char *p = getenv("RC_PID");
|
|
|
|
int pid;
|
|
|
|
|
|
|
|
if (p && sscanf(p, "%d", &pid) == 1) {
|
|
|
|
if (kill(pid, SIGUSR1) != 0)
|
|
|
|
eerrorx("rc-abort: failed to signal parent %d: %s",
|
|
|
|
pid, strerror(errno));
|
|
|
|
return EXIT_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
return EXIT_FAILURE;
|
|
|
|
}
|
|
|
|
|
|
|
|
static const struct {
|
|
|
|
const char * const name;
|
|
|
|
int (* const applet)(int argc, char **argv);
|
|
|
|
} applets[] = {
|
|
|
|
#define A(a) { #a, a }
|
|
|
|
A(fstabinfo),
|
|
|
|
A(mountinfo),
|
2013-12-22 02:21:11 +05:30
|
|
|
{ "openrc-run", openrc_run, },
|
2012-05-06 05:58:28 +05:30
|
|
|
{ "rc-depend", rc_depend, },
|
|
|
|
{ "rc-service", rc_service, },
|
|
|
|
{ "rc-status", rc_status, },
|
|
|
|
{ "rc-update", rc_update, },
|
2013-05-02 04:31:11 +05:30
|
|
|
{ "service", rc_service, },
|
2012-05-06 05:58:28 +05:30
|
|
|
{ "update-rc", rc_update, },
|
|
|
|
A(runscript),
|
|
|
|
{ "start-stop-daemon", start_stop_daemon, },
|
|
|
|
A(checkpath),
|
|
|
|
A(swclock),
|
|
|
|
A(shell_var),
|
|
|
|
A(is_older_than),
|
|
|
|
A(is_newer_than),
|
|
|
|
A(is_runlevel_start),
|
|
|
|
A(is_runlevel_stop),
|
|
|
|
{ "rc-abort", rc_abort, },
|
|
|
|
/* These are purely for init scripts and do not make sense as
|
|
|
|
* anything else */
|
|
|
|
{ "service_get_value", do_value, },
|
|
|
|
{ "service_set_value", do_value, },
|
|
|
|
{ "get_options", do_value, },
|
|
|
|
{ "save_options", do_value, },
|
|
|
|
#undef A
|
|
|
|
};
|
|
|
|
|
2009-04-24 03:01:22 +05:30
|
|
|
void
|
|
|
|
run_applets(int argc, char **argv)
|
2008-01-14 19:54:20 +05:30
|
|
|
{
|
2012-05-06 05:58:28 +05:30
|
|
|
size_t i;
|
2008-03-16 22:30:56 +05:30
|
|
|
|
2013-12-12 05:09:38 +05:30
|
|
|
/*
|
|
|
|
* The "rc" applet is deprecated and should be referred to as
|
|
|
|
* "openrc", so output a warning.
|
|
|
|
*/
|
|
|
|
if (strcmp(applet, "rc") == 0)
|
|
|
|
ewarn("The 'rc' applet is deprecated; please use 'openrc' instead.");
|
2011-02-15 20:20:44 +05:30
|
|
|
/* Bug 351712: We need an extra way to explicitly select an applet OTHER
|
|
|
|
* than trusting argv[0], as argv[0] is not going to be the applet value if
|
|
|
|
* we are doing SELinux context switching. For this, we allow calls such as
|
|
|
|
* 'rc --applet APPLET', and shift ALL of argv down by two array items. */
|
2013-12-12 05:09:38 +05:30
|
|
|
if ((strcmp(applet, "rc") == 0 || strcmp(applet, "openrc") == 0) &&
|
|
|
|
argc >= 3 &&
|
2012-05-06 05:58:28 +05:30
|
|
|
(strcmp(argv[1],"--applet") == 0 || strcmp(argv[1], "-a") == 0)) {
|
2011-02-15 20:20:44 +05:30
|
|
|
applet = argv[2];
|
|
|
|
argv += 2;
|
|
|
|
argc -= 2;
|
|
|
|
}
|
|
|
|
|
2012-05-06 05:58:28 +05:30
|
|
|
for (i = 0; i < ARRAY_SIZE(applets); ++i)
|
|
|
|
if (!strcmp(applet, applets[i].name))
|
|
|
|
exit(applets[i].applet(argc, argv));
|
2008-01-14 19:54:20 +05:30
|
|
|
|
|
|
|
if (applet[0] == 'e' || (applet[0] == 'v' && applet[1] == 'e'))
|
2008-03-16 22:30:56 +05:30
|
|
|
exit(do_e(argc, argv));
|
2008-01-14 19:54:20 +05:30
|
|
|
|
2008-03-16 22:30:56 +05:30
|
|
|
if (strncmp(applet, "service_", strlen("service_")) == 0)
|
|
|
|
exit(do_service(argc, argv));
|
2008-01-14 19:54:20 +05:30
|
|
|
|
2008-03-16 22:30:56 +05:30
|
|
|
if (strncmp(applet, "mark_service_", strlen("mark_service_")) == 0)
|
|
|
|
exit(do_mark_service(argc, argv));
|
2008-01-14 19:54:20 +05:30
|
|
|
|
2013-12-12 05:09:38 +05:30
|
|
|
if (strcmp(applet, "rc") != 0 && strcmp(applet, "openrc") != 0)
|
2008-03-16 22:30:56 +05:30
|
|
|
eerrorx("%s: unknown applet", applet);
|
2008-01-14 19:54:20 +05:30
|
|
|
}
|