1#include "ninqu.h"
2#include "wexec.h"
3
4#include <ctype.h>
5#include <stdio.h>
6#include <string.h>
7
8void
9sl_push(struct StrList *sl, const char *s)
10{
11 GROW(sl->v, sl->n, sl->cap, 8);
12 sl->v[sl->n++] = estrdup(s);
13}
14
15int
16sl_has(struct StrList *sl, const char *s)
17{
18 int i;
19 for (i = 0; i < sl->n; i++)
20 if (strcmp(sl->v[i], s) == 0)
21 return 1;
22 return 0;
23}
24
25void
26sl_split(struct StrList *sl, const char *s)
27{
28 const char *p = s;
29
30 sl->n = 0;
31 while (*p) {
32 const char *start;
33 char buf[4096];
34 size_t len;
35
36 while (*p && isspace((unsigned char)*p))
37 p++;
38 if (!*p)
39 break;
40 start = p;
41 while (*p && !isspace((unsigned char)*p))
42 p++;
43 len = (size_t)(p - start);
44 if (len >= sizeof buf)
45 len = sizeof buf - 1;
46 memcpy(buf, start, len);
47 buf[len] = '\0';
48 sl_push(sl, buf);
49 }
50}
51
52char *
53sl_join(struct StrList *sl)
54{
55 size_t cap = 64, len = 0;
56 char *out = emalloc(cap);
57 int i;
58
59 out[0] = '\0';
60 for (i = 0; i < sl->n; i++) {
61 size_t addlen = strlen(sl->v[i]) + 1;
62 while (len + addlen + 1 > cap) {
63 cap *= 2;
64 out = erealloc(out, cap);
65 }
66 if (i > 0)
67 out[len++] = ' ';
68 memcpy(out + len, sl->v[i], strlen(sl->v[i]));
69 len += strlen(sl->v[i]);
70 out[len] = '\0';
71 }
72 return out;
73}
74
75const char *
76base_of(const char *path)
77{
78 const char *p = strrchr(path, '/');
79 return p ? p + 1 : path;
80}
81
82/* null-terminate the array so wexecvp stops scanning */
83char **
84sl_argv(struct StrList *sl)
85{
86 char **av = emalloc((size_t)(sl->n + 1) * sizeof *av);
87 int i;
88 for (i = 0; i < sl->n; i++)
89 av[i] = sl->v[i];
90 av[sl->n] = NULL;
91 return av;
92}
93
94/* noreturn so callers do not guard the dead path after fork */
95void
96child_execvp(char **av)
97{
98 wexecvp_self(av[0], av);
99}