1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
|
/* ISC license. */
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <stdlib.h>
#include <skalibs/types.h>
#include <skalibs/sgetopt.h>
#include <skalibs/strerr2.h>
#include <skalibs/stralloc.h>
#include <skalibs/tai.h>
#include <skalibs/djbunix.h>
#include <skalibs/unix-transactional.h>
#include <s6-rc/config.h>
#include <s6-rc/s6rc.h>
#define USAGE "s6-rc-init [ -c compiled ] [ -l live ] [ -p prefix ] [ -t timeout ] [ -d ] scandir"
#define dieusage() strerr_dieusage(100, USAGE)
static void cleanup (stralloc *sa)
{
int e = errno ;
rm_rf_in_tmp(sa, 0) ;
errno = e ;
}
int main (int argc, char const *const *argv)
{
tain_t deadline ;
stralloc sa = STRALLOC_ZERO ;
size_t dirlen ;
char const *live = S6RC_LIVE_BASE ;
char const *compiled = S6RC_COMPILED_BASE ;
char const *prefix = "" ;
int deref = 0 ;
PROG = "s6-rc-init" ;
{
unsigned int t = 0 ;
subgetopt_t l = SUBGETOPT_ZERO ;
for (;;)
{
int opt = subgetopt_r(argc, argv, "c:l:p:t:bd", &l) ;
if (opt == -1) break ;
switch (opt)
{
case 'c' : compiled = l.arg ; break ;
case 'l' : live = l.arg ; break ;
case 'p' : prefix = l.arg ; break ;
case 't' : if (!uint0_scan(l.arg, &t)) dieusage() ; break ;
case 'b' : break ;
case 'd' : deref = 1 ; break ;
default : dieusage() ;
}
}
argc -= l.ind ; argv += l.ind ;
if (t) tain_from_millisecs(&deadline, t) ;
else deadline = tain_infinite_relative ;
}
if (!argc) dieusage() ;
if (!deref && compiled[0] != '/')
strerr_dief2x(100, compiled, " is not an absolute path") ;
if (argv[0][0] != '/')
strerr_dief2x(100, argv[0], " is not an absolute path") ;
if (strchr(prefix, '/') || strchr(prefix, '\n'))
strerr_dief1x(100, "prefix cannot contain a / or a newline") ;
tain_now_g() ;
tain_add_g(&deadline, &deadline) ;
if (deref)
{
char *x = realpath(compiled, 0) ;
if (!x) strerr_diefu2sys(111, "realpath ", compiled) ;
compiled = x ;
}
{
s6rc_db_t db ;
int r ;
int fdcompiled = open_readb(compiled) ;
if (fdcompiled < 0)
strerr_diefu2sys(111, "open ", compiled) ;
r = s6rc_db_read_sizes(fdcompiled, &db) ;
if (r < 0)
strerr_diefu2sys(111, "read database size in ", compiled) ;
else if (!r)
strerr_dief2x(4, "invalid database size in ", compiled) ;
close(fdcompiled) ;
{
unsigned char state[db.nshort + db.nlong] ;
memset(state, 0, db.nshort + db.nlong) ;
if (!s6rc_livedir_create(&sa, live, PROG, argv[0], prefix, compiled, state, db.nshort + db.nlong, &dirlen))
strerr_diefu1sys(111, "create live directory") ;
}
}
{
size_t clen = strlen(compiled) ;
char lfn[sa.len + 13] ;
char cfn[clen + 13] ;
memcpy(lfn, sa.s, sa.len) ;
memcpy(lfn + sa.len, "/servicedirs", 13) ;
memcpy(cfn, compiled, clen) ;
memcpy(cfn + clen, "/servicedirs", 13) ;
if (!hiercopy(cfn, lfn))
{
cleanup(&sa) ;
strerr_diefu4sys(111, "recursively copy ", cfn, " to ", lfn) ;
}
}
if (!atomic_symlink(sa.s + dirlen, live, PROG))
{
cleanup(&sa) ;
strerr_diefu4sys(111, "symlink ", sa.s + dirlen, " to ", live) ;
}
deref = s6rc_servicedir_manage_g(live, prefix, &deadline) ;
if (!deref)
{
cleanup(&sa) ;
strerr_diefu3sys(111, "supervise service directories in ", live, "/servicedirs") ;
}
if (deref & 2)
strerr_warnw2x("s6-svscan not running on ", argv[0]) ;
return 0 ;
}
|