Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit f24e2529 authored by San Mehat's avatar San Mehat
Browse files

init: Add the ability to start services with dynamic arguments.



    To add arguments dynamically to a service, start the service like so:

    setprop ctl.start service_to_run:arg1 arg2 arg3...

    To start a service with *no* dynamic arguments, start the service normally:

    setprop ctl.start service_to_run

    Dynamic arguments are only supported on 'oneshot' services

Signed-off-by: default avatarSan Mehat <san@google.com>
parent 1b154930
Loading
Loading
Loading
Loading
+3 −3
Original line number Diff line number Diff line
@@ -126,7 +126,7 @@ done:
static void service_start_if_not_disabled(struct service *svc)
{
    if (!(svc->flags & SVC_DISABLED)) {
        service_start(svc);
        service_start(svc, NULL);
    }
}

@@ -316,7 +316,7 @@ int do_start(int nargs, char **args)
    struct service *svc;
    svc = service_find_by_name(args[1]);
    if (svc) {
        service_start(svc);
        service_start(svc, NULL);
    }
    return 0;
}
@@ -337,7 +337,7 @@ int do_restart(int nargs, char **args)
    svc = service_find_by_name(args[1]);
    if (svc) {
        service_stop(svc);
        service_start(svc);
        service_start(svc, NULL);
    }
    return 0;
}
+71 −6
Original line number Diff line number Diff line
@@ -156,7 +156,7 @@ static void publish_socket(const char *name, int fd)
    fcntl(fd, F_SETFD, 0);
}

void service_start(struct service *svc)
void service_start(struct service *svc, const char *dynamic_args)
{
    struct stat s;
    pid_t pid;
@@ -192,6 +192,12 @@ void service_start(struct service *svc)
        return;
    }

    if ((!(svc->flags & SVC_ONESHOT)) && dynamic_args) {
        ERROR("service '%s' must be one-shot to use dynamic args, disabling\n", svc->args[0]);
        svc->flags |= SVC_DISABLED;
        return;
    }

    NOTICE("starting '%s'\n", svc->name);

    pid = fork();
@@ -248,7 +254,50 @@ void service_start(struct service *svc)
            setuid(svc->uid);
        }

        if (!dynamic_args)
            execve(svc->args[0], (char**) svc->args, (char**) ENV);
        else {
            char *arg_ptrs[SVC_MAXARGS+1];
            int arg_idx;
            char *tmp = strdup(dynamic_args);
            char *p = tmp;

            /* Copy the static arguments */
            for (arg_idx = 0; arg_idx < svc->nargs; arg_idx++) {
                arg_ptrs[arg_idx] = svc->args[arg_idx];
            }

            int done = 0;
            while(!done) {

                if (arg_idx == SVC_MAXARGS) 
                    break;

                /* Advance over any leading whitespace */
                if (*p == ' ') {
                    for (p; *p != ' '; p++);
                    p++;
                }
                /* Locate next argument */
                char *q = p;
                while(1) {
                    if (*q == ' ') {
                        *q = '\0';
                        break;
                    } else if (*q == '\0') {
                        done = 1;
                        break;
                    }
                    q++;
                }
                arg_ptrs[arg_idx++] = p;

                q++; // Advance q to the next string
                p = q;
            }
            arg_ptrs[arg_idx] = '\0';
            execve(svc->args[0], (char**) arg_ptrs, (char**) ENV);
        }
        _exit(127);
    }

@@ -379,7 +428,7 @@ static void restart_service_if_needed(struct service *svc)

    if (next_start_time <= gettime()) {
        svc->flags &= (~SVC_RESTARTING);
        service_start(svc);
        service_start(svc, NULL);
        return;
    }

@@ -405,13 +454,29 @@ static void sigchld_handler(int s)

static void msg_start(const char *name)
{
    struct service *svc = service_find_by_name(name);
    struct service *svc;
    char *tmp = NULL;
    char *args = NULL;

    if (!strchr(name, ':'))
        svc = service_find_by_name(name);
    else {
        tmp = strdup(name);
        strcpy(tmp, name);
        args = strchr(tmp, ':');
        *args = '\0';
        args++;

        svc = service_find_by_name(tmp);
    }
    
    if (svc) {
        service_start(svc);
        service_start(svc, args);
    } else {
        ERROR("no such service '%s'\n", name);
    }
    if (tmp)
        free(tmp);
}

static void msg_stop(const char *name)
@@ -737,7 +802,7 @@ void handle_keychord(int fd)
    svc = service_find_by_keychord(id);
    if (svc) {
        INFO("starting service %s from keychord\n", svc->name);
        service_start(svc);   
        service_start(svc, NULL);   
    } else {
        ERROR("service for keychord %d not found\n", id);
    }
+3 −1
Original line number Diff line number Diff line
@@ -116,6 +116,8 @@ struct svcenvinfo {

#define NR_SVC_SUPP_GIDS 6    /* six supplementary groups */

#define SVC_MAXARGS 64

struct service {
        /* list of all services */
    struct listnode slist;
@@ -160,7 +162,7 @@ void service_for_each_class(const char *classname,
void service_for_each_flags(unsigned matchflags,
                            void (*func)(struct service *svc));
void service_stop(struct service *svc);
void service_start(struct service *svc);
void service_start(struct service *svc, const char *dynamic_args);
void property_changed(const char *name, const char *value);

struct action *action_remove_queue_head(void);
+2 −4
Original line number Diff line number Diff line
@@ -60,8 +60,6 @@ void DUMP(void)
#endif       
}

#define MAXARGS 64

#define T_EOF 0
#define T_TEXT 1
#define T_NEWLINE 2
@@ -357,7 +355,7 @@ void parse_new_section(struct parse_state *state, int kw,
static void parse_config(const char *fn, char *s)
{
    struct parse_state state;
    char *args[MAXARGS];
    char *args[SVC_MAXARGS];
    int nargs;

    nargs = 0;
@@ -384,7 +382,7 @@ static void parse_config(const char *fn, char *s)
            }
            break;
        case T_TEXT:
            if (nargs < MAXARGS) {
            if (nargs < SVC_MAXARGS) {
                args[nargs++] = state.text;
            }
            break;