mirror of
https://github.com/troglobit/finit.git
synced 2026-11-06 15:51:03 +00:00
New client side API to access svc_t entries without shared memory
This change is one of the required intermediate steps to remove the shared memory store for all svc_t, this in turn to avoid any external programs manipulating the internal memory of PID 1. Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
This commit is contained in:
1 parent
9a8b55737f
commit
c0515d112e
6 files changed
+169
-52
No files matched your search
+1
-1
@@ -44,7 +44,7 @@ finit_LDADD += -ldl
|
|||||||
endif
|
endif
|
||||||
|
|
||||||
initctl_SOURCES = initctl.c client.c client.h \
|
initctl_SOURCES = initctl.c client.c client.h \
|
||||||
serv.c serv.h svc.c svc.h \
|
serv.c serv.h svc.h \
|
||||||
cond.c cond.h util.c util.h
|
cond.c cond.h util.c util.h
|
||||||
initctl_CFLAGS = -W -Wall -Wextra -Wno-unused-parameter -std=gnu99
|
initctl_CFLAGS = -W -Wall -Wextra -Wno-unused-parameter -std=gnu99
|
||||||
initctl_CFLAGS += $(lite_CFLAGS)
|
initctl_CFLAGS += $(lite_CFLAGS)
|
||||||
|
|||||||
@@ -21,6 +21,7 @@
|
|||||||
* THE SOFTWARE.
|
* THE SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <ctype.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
@@ -87,15 +88,42 @@ static int do_start (char *buf, size_t len) { return call(service_start, buf,
|
|||||||
static int do_stop (char *buf, size_t len) { return call(service_stop, buf, len); }
|
static int do_stop (char *buf, size_t len) { return call(service_stop, buf, len); }
|
||||||
static int do_restart(char *buf, size_t len) { return call(service_restart, buf, len); }
|
static int do_restart(char *buf, size_t len) { return call(service_restart, buf, len); }
|
||||||
|
|
||||||
#ifdef INETD_ENABLED
|
static char query_buf[368];
|
||||||
static int do_query_inetd(char *buf, size_t len)
|
static int missing(char *job, int id)
|
||||||
|
{
|
||||||
|
char buf[20];
|
||||||
|
char idstr[10] = "";
|
||||||
|
|
||||||
|
if (!job)
|
||||||
|
job = "";
|
||||||
|
if (id > 1)
|
||||||
|
snprintf(idstr, sizeof(idstr), ":%d", id);
|
||||||
|
|
||||||
|
snprintf(buf, sizeof(buf), "%s%s ", job, idstr);
|
||||||
|
strlcat(query_buf, buf, sizeof(query_buf));
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int do_query(struct init_request *rq, size_t len)
|
||||||
|
{
|
||||||
|
memset(query_buf, 0, sizeof(query_buf));
|
||||||
|
if (svc_parse_jobstr(rq->data, strlen(rq->data) + 1, NULL, missing)) {
|
||||||
|
memcpy(rq->data, query_buf, sizeof(rq->data));
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static svc_t *do_find(char *buf, size_t len)
|
||||||
{
|
{
|
||||||
int id = 1;
|
int id = 1;
|
||||||
char *ptr, *input = sanitize(buf, len);
|
char *ptr, *input;
|
||||||
svc_t *svc;
|
|
||||||
|
|
||||||
|
input = sanitize(buf, len);
|
||||||
if (!input)
|
if (!input)
|
||||||
return -1;
|
return NULL;
|
||||||
|
|
||||||
ptr = strchr(input, ':');
|
ptr = strchr(input, ':');
|
||||||
if (ptr) {
|
if (ptr) {
|
||||||
@@ -103,11 +131,20 @@ static int do_query_inetd(char *buf, size_t len)
|
|||||||
id = atonum(ptr);
|
id = atonum(ptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
svc = svc_find_by_jobid(atonum(input), id);
|
if (isdigit(input[0]))
|
||||||
if (!svc || !svc_is_inetd(svc)) {
|
return svc_find_by_jobid(atonum(input), id);
|
||||||
_e("Cannot %s svc %s ...", !svc ? "find" : "query, not an inetd", input);
|
|
||||||
|
return svc_find_by_nameid(input, id);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef INETD_ENABLED
|
||||||
|
static int do_query_inetd(char *buf, size_t len)
|
||||||
|
{
|
||||||
|
svc_t *svc;
|
||||||
|
|
||||||
|
svc = do_find(buf, len);
|
||||||
|
if (!svc || !svc_is_inetd(svc))
|
||||||
return 1;
|
return 1;
|
||||||
}
|
|
||||||
|
|
||||||
return inetd_filter_str(&svc->inetd, buf, len);
|
return inetd_filter_str(&svc->inetd, buf, len);
|
||||||
}
|
}
|
||||||
@@ -164,6 +201,22 @@ static int do_handle_emit(char *buf, size_t len)
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void send_svc(int sd, svc_t *svc)
|
||||||
|
{
|
||||||
|
svc_t empty;
|
||||||
|
size_t len;
|
||||||
|
|
||||||
|
if (!svc) {
|
||||||
|
empty.pid = -1;
|
||||||
|
svc = ∅
|
||||||
|
}
|
||||||
|
|
||||||
|
len = write(sd, svc, sizeof(*svc));
|
||||||
|
if (len != sizeof(*svc))
|
||||||
|
_d("Failed sending svc_t to client");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* In contrast to the SysV compat handling in plugins/initctl.c, when
|
* In contrast to the SysV compat handling in plugins/initctl.c, when
|
||||||
* `initctl runlevel 0` is issued we default to POWERDOWN the system
|
* `initctl runlevel 0` is issued we default to POWERDOWN the system
|
||||||
@@ -290,6 +343,21 @@ static void api_cb(uev_t *w, void *arg, int events)
|
|||||||
wdogpid = rq.runlevel;
|
wdogpid = rq.runlevel;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case INIT_CMD_SVC_ITER:
|
||||||
|
_d("svc iter, first: %d", rq.runlevel);
|
||||||
|
send_svc(sd, svc_iterator(rq.runlevel));
|
||||||
|
goto leave;
|
||||||
|
|
||||||
|
case INIT_CMD_SVC_QUERY:
|
||||||
|
_d("svc query: %s", rq.data);
|
||||||
|
result = do_query(&rq, len);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case INIT_CMD_SVC_FIND:
|
||||||
|
_d("svc find: %s", rq.data);
|
||||||
|
send_svc(sd, do_find(rq.data, sizeof(rq.data)));
|
||||||
|
goto leave;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
_d("Unsupported cmd: %d", rq.cmd);
|
_d("Unsupported cmd: %d", rq.cmd);
|
||||||
break;
|
break;
|
||||||
|
|||||||
@@ -89,6 +89,74 @@ exit:
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
svc_t *client_svc_iterator(int first)
|
||||||
|
{
|
||||||
|
int sd = -1;
|
||||||
|
struct init_request rq = {
|
||||||
|
.magic = INIT_MAGIC,
|
||||||
|
.cmd = INIT_CMD_SVC_ITER,
|
||||||
|
};
|
||||||
|
static svc_t svc;
|
||||||
|
|
||||||
|
sd = client_connect();
|
||||||
|
if (sd == -1)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
if (first)
|
||||||
|
rq.runlevel = 1;
|
||||||
|
else
|
||||||
|
rq.runlevel = 0;
|
||||||
|
|
||||||
|
if (write(sd, &rq, sizeof(rq)) != sizeof(rq))
|
||||||
|
goto error;
|
||||||
|
if (read(sd, &svc, sizeof(svc)) != sizeof(svc))
|
||||||
|
goto error;
|
||||||
|
|
||||||
|
client_disconnect();
|
||||||
|
if (svc.pid < 0)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
return &svc;
|
||||||
|
error:
|
||||||
|
perror("Failed communicating with finit");
|
||||||
|
client_disconnect();
|
||||||
|
sd = -1;
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
svc_t *client_svc_find(char *arg)
|
||||||
|
{
|
||||||
|
int sd = -1;
|
||||||
|
struct init_request rq = {
|
||||||
|
.magic = INIT_MAGIC,
|
||||||
|
.cmd = INIT_CMD_SVC_FIND,
|
||||||
|
};
|
||||||
|
static svc_t svc;
|
||||||
|
|
||||||
|
sd = client_connect();
|
||||||
|
if (sd == -1)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
strlcpy(rq.data, arg, sizeof(rq.data));
|
||||||
|
if (write(sd, &rq, sizeof(rq)) != sizeof(rq))
|
||||||
|
goto error;
|
||||||
|
if (read(sd, &svc, sizeof(svc)) != sizeof(svc))
|
||||||
|
goto error;
|
||||||
|
|
||||||
|
client_disconnect();
|
||||||
|
if (svc.pid < 0)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
return &svc;
|
||||||
|
error:
|
||||||
|
client_disconnect();
|
||||||
|
perror("Failed communicating with finit");
|
||||||
|
sd = -1;
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Local Variables:
|
* Local Variables:
|
||||||
* indent-tabs-mode: t
|
* indent-tabs-mode: t
|
||||||
|
|||||||
+6
-3
@@ -25,15 +25,18 @@
|
|||||||
#define FINIT_CLIENT_H_
|
#define FINIT_CLIENT_H_
|
||||||
|
|
||||||
#include "finit.h"
|
#include "finit.h"
|
||||||
|
#include "svc.h"
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
char *cmd;
|
char *cmd;
|
||||||
int (*cb)(char *arg);
|
int (*cb)(char *arg);
|
||||||
} command_t;
|
} command_t;
|
||||||
|
|
||||||
int client_connect (void);
|
int client_connect (void);
|
||||||
int client_disconnect (void);
|
int client_disconnect (void);
|
||||||
|
|
||||||
int client_send (struct init_request *rq, ssize_t len);
|
int client_send (struct init_request *rq, ssize_t len);
|
||||||
|
svc_t *client_svc_iterator (int first);
|
||||||
|
svc_t *client_svc_find (char *arg);
|
||||||
|
|
||||||
#endif /* FINIT_CLIENT_H_ */
|
#endif /* FINIT_CLIENT_H_ */
|
||||||
@@ -78,6 +78,9 @@
|
|||||||
#define INIT_CMD_EMIT 15
|
#define INIT_CMD_EMIT 15
|
||||||
#define INIT_CMD_GET_RUNLEVEL 16
|
#define INIT_CMD_GET_RUNLEVEL 16
|
||||||
#define INIT_CMD_WDOG_HELLO 128 /* Watchdog register and hello */
|
#define INIT_CMD_WDOG_HELLO 128 /* Watchdog register and hello */
|
||||||
|
#define INIT_CMD_SVC_ITER 129
|
||||||
|
#define INIT_CMD_SVC_QUERY 130
|
||||||
|
#define INIT_CMD_SVC_FIND 131
|
||||||
#define INIT_CMD_NACK 254
|
#define INIT_CMD_NACK 254
|
||||||
#define INIT_CMD_ACK 255
|
#define INIT_CMD_ACK 255
|
||||||
|
|
||||||
|
|||||||
+14
-39
@@ -138,21 +138,6 @@ static int do_svc(int cmd, char *arg)
|
|||||||
static int do_emit (char *arg) { return do_svc(INIT_CMD_EMIT, arg); }
|
static int do_emit (char *arg) { return do_svc(INIT_CMD_EMIT, arg); }
|
||||||
static int do_reload (char *arg) { return do_svc(INIT_CMD_RELOAD, arg); }
|
static int do_reload (char *arg) { return do_svc(INIT_CMD_RELOAD, arg); }
|
||||||
|
|
||||||
static int missing(char *job, int id)
|
|
||||||
{
|
|
||||||
char idstr[10] = "";
|
|
||||||
|
|
||||||
if (!job)
|
|
||||||
job = "";
|
|
||||||
if (id > 1)
|
|
||||||
snprintf(idstr, sizeof(idstr), ":%d", id);
|
|
||||||
|
|
||||||
if (verbose)
|
|
||||||
fprintf(stderr, "No such service %s%s\n", job, idstr);
|
|
||||||
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This is a wrapper for do_svc() that adds a simple sanity check of
|
* This is a wrapper for do_svc() that adds a simple sanity check of
|
||||||
* the service(s) provided as argument. If a service does not exist
|
* the service(s) provided as argument. If a service does not exist
|
||||||
@@ -160,8 +145,14 @@ static int missing(char *job, int id)
|
|||||||
*/
|
*/
|
||||||
static int do_startstop(int cmd, char *arg)
|
static int do_startstop(int cmd, char *arg)
|
||||||
{
|
{
|
||||||
/* Include \0 in len, needed by parser */
|
struct init_request rq = {
|
||||||
if (svc_parse_jobstr(arg, strlen(arg) + 1, NULL, missing)) {
|
.magic = INIT_MAGIC,
|
||||||
|
.cmd = INIT_CMD_SVC_QUERY
|
||||||
|
};
|
||||||
|
|
||||||
|
strlcpy(rq.data, arg, sizeof(rq.data));
|
||||||
|
if (client_send(&rq, sizeof(rq))) {
|
||||||
|
fprintf(stderr, "No such job(s) or service(s): %s\n\n", rq.data);
|
||||||
fprintf(stderr, "Usage: initctl %s <JOB|NAME>[:ID]\n",
|
fprintf(stderr, "Usage: initctl %s <JOB|NAME>[:ID]\n",
|
||||||
cmd == INIT_CMD_START_SVC ? "start" :
|
cmd == INIT_CMD_START_SVC ? "start" :
|
||||||
(cmd == INIT_CMD_STOP_SVC ? "stop" : "restart"));
|
(cmd == INIT_CMD_STOP_SVC ? "stop" : "restart"));
|
||||||
@@ -257,7 +248,7 @@ static int do_cond_show(char *arg)
|
|||||||
|
|
||||||
printheader(NULL, "PID SERVICE STATUS CONDITION (+ ON, ~ FLUX, - OFF)", 0);
|
printheader(NULL, "PID SERVICE STATUS CONDITION (+ ON, ~ FLUX, - OFF)", 0);
|
||||||
|
|
||||||
for (svc = svc_iterator(1); svc; svc = svc_iterator(0)) {
|
for (svc = client_svc_iterator(1); svc; svc = client_svc_iterator(0)) {
|
||||||
if (!svc->cond[0])
|
if (!svc->cond[0])
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
@@ -420,23 +411,7 @@ static int show_status(char *arg)
|
|||||||
runlevel = runlevel_get(NULL);
|
runlevel = runlevel_get(NULL);
|
||||||
|
|
||||||
if (arg && arg[0]) {
|
if (arg && arg[0]) {
|
||||||
int id = 1;
|
svc = client_svc_find(arg);
|
||||||
char *ptr, *next;
|
|
||||||
|
|
||||||
ptr = strchr(arg, ':');
|
|
||||||
if (ptr) {
|
|
||||||
*ptr++ = 0;
|
|
||||||
next = strchr(ptr, ' ');
|
|
||||||
if (next)
|
|
||||||
*next = 0;
|
|
||||||
id = atonum(ptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isdigit(arg[0]))
|
|
||||||
svc = svc_find_by_jobid(atonum(arg), id);
|
|
||||||
else
|
|
||||||
svc = svc_find_by_nameid(arg, id);
|
|
||||||
|
|
||||||
if (!svc)
|
if (!svc)
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
@@ -447,12 +422,12 @@ static int show_status(char *arg)
|
|||||||
if (!verbose)
|
if (!verbose)
|
||||||
printheader(NULL, "# STATUS PID RUNLEVELS SERVICE DESCRIPTION", 0);
|
printheader(NULL, "# STATUS PID RUNLEVELS SERVICE DESCRIPTION", 0);
|
||||||
|
|
||||||
for (svc = svc_iterator(1); svc; svc = svc_iterator(0)) {
|
for (svc = client_svc_iterator(1); svc; svc = client_svc_iterator(0)) {
|
||||||
char jobid[10], args[512] = "", *lvls;
|
char jobid[10], args[512] = "", *lvls;
|
||||||
|
|
||||||
if (svc_is_unique(svc))
|
// if (svc_is_unique(svc))
|
||||||
snprintf(jobid, sizeof(jobid), "%d", svc->job);
|
// snprintf(jobid, sizeof(jobid), "%d", svc->job);
|
||||||
else
|
// else
|
||||||
snprintf(jobid, sizeof(jobid), "%d:%d", svc->job, svc->id);
|
snprintf(jobid, sizeof(jobid), "%d:%d", svc->job, svc->id);
|
||||||
|
|
||||||
printf("%-5s %7s ", jobid, svc_status(svc));
|
printf("%-5s %7s ", jobid, svc_status(svc));
|
||||||
|
|||||||
Reference in new issue
Block a user