chiark / gitweb /
service: allow immediate stopping while starting
[elogind.git] / src / util.c
index a01229e659f3906e7191675963b5d0e7c3320534..fa3969b7051e04a248e4034e4af6f995aa081aa3 100644 (file)
@@ -609,19 +609,30 @@ int get_process_cmdline(pid_t pid, size_t max_length, char **line) {
 
         fclose(f);
 
+        if (r[0] == 0)
+                return get_process_name(pid, line);
+
         *line = r;
         return 0;
 }
 
-char *strappend(const char *s, const char *suffix) {
-        size_t a, b;
+char *strnappend(const char *s, const char *suffix, size_t b) {
+        size_t a;
         char *r;
 
+        if (!s && !suffix)
+                return strdup("");
+
+        if (!s)
+                return strndup(suffix, b);
+
+        if (!suffix)
+                return strdup(s);
+
         assert(s);
         assert(suffix);
 
         a = strlen(s);
-        b = strlen(suffix);
 
         if (!(r = new(char, a+b+1)))
                 return NULL;
@@ -633,6 +644,10 @@ char *strappend(const char *s, const char *suffix) {
         return r;
 }
 
+char *strappend(const char *s, const char *suffix) {
+        return strnappend(s, suffix, suffix ? strlen(suffix) : 0);
+}
+
 int readlink_malloc(const char *p, char **r) {
         size_t l = 100;
 
@@ -2692,6 +2707,143 @@ void status_welcome(void) {
 #endif
 }
 
+char *replace_env(const char *format, char **env) {
+        enum {
+                WORD,
+                DOLLAR,
+                VARIABLE
+        } state = WORD;
+
+        const char *e, *word = format;
+        char *r = NULL, *k;
+
+        assert(format);
+
+        for (e = format; *e; e ++) {
+
+                switch (state) {
+
+                case WORD:
+                        if (*e == '$')
+                                state = DOLLAR;
+                        break;
+
+                case DOLLAR:
+                        if (*e == '(') {
+                                if (!(k = strnappend(r, word, e-word-1)))
+                                        goto fail;
+
+                                free(r);
+                                r = k;
+
+                                word = e-1;
+                                state = VARIABLE;
+
+                        } else if (*e == '$') {
+                                if (!(k = strnappend(r, word, e-word)))
+                                        goto fail;
+
+                                free(r);
+                                r = k;
+
+                                word = e+1;
+                                state = WORD;
+                        } else
+                                state = WORD;
+                        break;
+
+                case VARIABLE:
+                        if (*e == ')') {
+                                char *t;
+
+                                if ((t = strv_env_get_with_length(env, word+2, e-word-2))) {
+                                        if (!(k = strappend(r, t)))
+                                                goto fail;
+
+                                        free(r);
+                                        r = k;
+
+                                        word = e+1;
+                                }
+
+                                state = WORD;
+                        }
+                        break;
+                }
+        }
+
+        if (!(k = strnappend(r, word, e-word)))
+                goto fail;
+
+        free(r);
+        return k;
+
+fail:
+        free(r);
+        return NULL;
+}
+
+char **replace_env_argv(char **argv, char **env) {
+        char **r, **i;
+        unsigned k = 0;
+
+        if (!(r = new(char*, strv_length(argv)+1)))
+                return NULL;
+
+        STRV_FOREACH(i, argv) {
+                if (!(r[k++] = replace_env(*i, env))) {
+                        strv_free(r);
+                        return NULL;
+                }
+        }
+
+        r[k] = NULL;
+        return r;
+}
+
+int columns(void) {
+        static __thread int parsed_columns = 0;
+        const char *e;
+
+        if (parsed_columns > 0)
+                return parsed_columns;
+
+        if ((e = getenv("COLUMNS")))
+                parsed_columns = atoi(e);
+
+        if (parsed_columns <= 0) {
+                struct winsize ws;
+                zero(ws);
+
+                if (ioctl(STDIN_FILENO, TIOCGWINSZ, &ws) >= 0)
+                        parsed_columns = ws.ws_col;
+        }
+
+        if (parsed_columns <= 0)
+                parsed_columns = 80;
+
+        return parsed_columns;
+}
+
+int running_in_chroot(void) {
+        struct stat a, b;
+
+        zero(a);
+        zero(b);
+
+        /* Only works as root */
+
+        if (stat("/proc/1/root", &a) < 0)
+                return -errno;
+
+        if (stat("/", &b) < 0)
+                return -errno;
+
+        return
+                a.st_dev != b.st_dev ||
+                a.st_ino != b.st_ino;
+}
+
 static const char *const ioprio_class_table[] = {
         [IOPRIO_CLASS_NONE] = "none",
         [IOPRIO_CLASS_RT] = "realtime",
@@ -2789,3 +2941,39 @@ static const char* const ip_tos_table[] = {
 };
 
 DEFINE_STRING_TABLE_LOOKUP(ip_tos, int);
+
+static const char *const signal_table[] = {
+        [SIGHUP] = "HUP",
+        [SIGINT] = "INT",
+        [SIGQUIT] = "QUIT",
+        [SIGILL] = "ILL",
+        [SIGTRAP] = "TRAP",
+        [SIGABRT] = "ABRT",
+        [SIGBUS] = "BUS",
+        [SIGFPE] = "FPE",
+        [SIGKILL] = "KILL",
+        [SIGUSR1] = "USR1",
+        [SIGSEGV] = "SEGV",
+        [SIGUSR2] = "USR2",
+        [SIGPIPE] = "PIPE",
+        [SIGALRM] = "ALRM",
+        [SIGTERM] = "TERM",
+        [SIGSTKFLT] = "STKFLT",
+        [SIGCHLD] = "CHLD",
+        [SIGCONT] = "CONT",
+        [SIGSTOP] = "STOP",
+        [SIGTSTP] = "TSTP",
+        [SIGTTIN] = "TTIN",
+        [SIGTTOU] = "TTOU",
+        [SIGURG] = "URG",
+        [SIGXCPU] = "XCPU",
+        [SIGXFSZ] = "XFSZ",
+        [SIGVTALRM] = "VTALRM",
+        [SIGPROF] = "PROF",
+        [SIGWINCH] = "WINCH",
+        [SIGIO] = "IO",
+        [SIGPWR] = "PWR",
+        [SIGSYS] = "SYS"
+};
+
+DEFINE_STRING_TABLE_LOOKUP(signal, int);