]>
Commit | Line | Data |
---|---|---|
5cb5a6ff LP |
1 | /*-*- Mode: C; c-basic-offset: 8 -*-*/ |
2 | ||
3 | #include <errno.h> | |
4 | ||
5 | #include "name.h" | |
6 | #include "service.h" | |
7 | #include "load-fragment.h" | |
8 | #include "load-dropin.h" | |
9 | ||
10 | static int service_load_sysv(Service *s) { | |
11 | assert(s); | |
12 | ||
13 | /* Load service data from SysV init scripts, preferably with | |
14 | * LSB headers ... */ | |
15 | ||
16 | return -ENOENT; | |
17 | } | |
18 | ||
19 | static int service_load(Name *n) { | |
20 | int r; | |
21 | Service *s = SERVICE(n); | |
22 | ||
23 | assert(s); | |
24 | ||
25 | exec_context_defaults(&s->exec_context); | |
26 | ||
27 | /* Load a .service file */ | |
28 | r = name_load_fragment(n); | |
29 | ||
30 | /* Load a classic init script as a fallback */ | |
31 | if (r == -ENOENT) | |
32 | r = service_load_sysv(s); | |
33 | ||
34 | if (r < 0) | |
35 | return r; | |
36 | ||
37 | /* Load dropin directory data */ | |
38 | if ((r = name_load_dropin(n)) < 0) | |
39 | return r; | |
40 | ||
41 | return 0; | |
42 | } | |
43 | ||
44 | static void service_dump(Name *n, FILE *f, const char *prefix) { | |
45 | ||
46 | static const char* const state_table[_SERVICE_STATE_MAX] = { | |
47 | [SERVICE_DEAD] = "dead", | |
48 | [SERVICE_START_PRE] = "start-pre", | |
49 | [SERVICE_START] = "start", | |
50 | [SERVICE_START_POST] = "post", | |
51 | [SERVICE_RUNNING] = "running", | |
52 | [SERVICE_RELOAD_PRE] = "reload-pre", | |
53 | [SERVICE_RELOAD] = "reload", | |
54 | [SERVICE_RELOAD_POST] = "reload-post", | |
55 | [SERVICE_STOP_PRE] = "stop-pre", | |
56 | [SERVICE_STOP] = "stop", | |
57 | [SERVICE_SIGTERM] = "sigterm", | |
58 | [SERVICE_SIGKILL] = "sigkill", | |
59 | [SERVICE_STOP_POST] = "stop-post", | |
60 | [SERVICE_MAINTAINANCE] = "maintainance" | |
61 | }; | |
62 | ||
63 | static const char* const command_table[_SERVICE_EXEC_MAX] = { | |
64 | [SERVICE_EXEC_START_PRE] = "StartPre", | |
65 | [SERVICE_EXEC_START] = "Start", | |
66 | [SERVICE_EXEC_START_POST] = "StartPost", | |
67 | [SERVICE_EXEC_RELOAD_PRE] = "ReloadPre", | |
68 | [SERVICE_EXEC_RELOAD] = "Reload", | |
69 | [SERVICE_EXEC_RELOAD_POST] = "ReloadPost", | |
70 | [SERVICE_EXEC_STOP_PRE] = "StopPre", | |
71 | [SERVICE_EXEC_STOP] = "Stop", | |
72 | [SERVICE_EXEC_STOP_POST] = "StopPost", | |
73 | }; | |
74 | ||
75 | ServiceExecCommand c; | |
76 | Service *s = SERVICE(n); | |
77 | ||
78 | assert(s); | |
79 | ||
80 | fprintf(f, | |
81 | "%sService State: %s\n", | |
82 | prefix, state_table[s->state]); | |
83 | ||
84 | exec_context_dump(&s->exec_context, f, prefix); | |
85 | ||
86 | for (c = 0; c < _SERVICE_EXEC_MAX; c++) { | |
87 | ExecCommand *i; | |
88 | ||
89 | LIST_FOREACH(i, s->exec_command[c]) | |
90 | fprintf(f, "%s%s: %s\n", prefix, command_table[c], i->path); | |
91 | } | |
92 | } | |
93 | ||
94 | static int service_set_state(Service *s, ServiceState state) { | |
95 | assert(s); | |
96 | ||
97 | s->state = state; | |
98 | return 0; | |
99 | } | |
100 | ||
101 | static int service_start(Name *n) { | |
102 | Service *s = SERVICE(n); | |
103 | ||
104 | assert(s); | |
105 | ||
106 | /* We cannot fulfill this request right now */ | |
107 | if (s->state == SERVICE_STOP_PRE || | |
108 | s->state == SERVICE_STOP || | |
109 | s->state == SERVICE_SIGTERM || | |
110 | s->state == SERVICE_SIGKILL || | |
111 | s->state == SERVICE_STOP_POST) | |
112 | return -EAGAIN; | |
113 | ||
114 | assert(s->state == SERVICE_DEAD || s->state == SERVICE_MAINTAINANCE); | |
115 | ||
116 | return service_set_state(s, SERVICE_START_PRE); | |
117 | } | |
118 | ||
119 | static int service_stop(Name *n) { | |
120 | Service *s = SERVICE(n); | |
121 | ||
122 | assert(s); | |
123 | ||
124 | ||
125 | return 0; | |
126 | } | |
127 | ||
128 | static int service_reload(Name *n) { | |
129 | return 0; | |
130 | } | |
131 | ||
132 | static NameActiveState service_active_state(Name *n) { | |
133 | ||
134 | static const NameActiveState table[_SERVICE_STATE_MAX] = { | |
135 | [SERVICE_DEAD] = NAME_INACTIVE, | |
136 | [SERVICE_START_PRE] = NAME_ACTIVATING, | |
137 | [SERVICE_START] = NAME_ACTIVATING, | |
138 | [SERVICE_START_POST] = NAME_ACTIVATING, | |
139 | [SERVICE_RUNNING] = NAME_ACTIVE, | |
140 | [SERVICE_RELOAD_PRE] = NAME_ACTIVE_RELOADING, | |
141 | [SERVICE_RELOAD] = NAME_ACTIVE_RELOADING, | |
142 | [SERVICE_RELOAD_POST] = NAME_ACTIVE_RELOADING, | |
143 | [SERVICE_STOP_PRE] = NAME_DEACTIVATING, | |
144 | [SERVICE_STOP] = NAME_DEACTIVATING, | |
145 | [SERVICE_SIGTERM] = NAME_DEACTIVATING, | |
146 | [SERVICE_SIGKILL] = NAME_DEACTIVATING, | |
147 | [SERVICE_STOP_POST] = NAME_DEACTIVATING, | |
148 | [SERVICE_MAINTAINANCE] = NAME_INACTIVE, | |
149 | }; | |
150 | ||
151 | return table[SERVICE(n)->state]; | |
152 | } | |
153 | ||
154 | static void service_free_hook(Name *n) { | |
155 | Service *s = SERVICE(n); | |
156 | unsigned c; | |
157 | ||
158 | assert(s); | |
159 | ||
160 | exec_context_free(&s->exec_context); | |
161 | ||
162 | for (c = 0; c < _SERVICE_EXEC_MAX; c++) | |
163 | exec_command_free_list(s->exec_command[c]); | |
164 | ||
165 | if (s->socket) | |
166 | s->socket->service = NULL; | |
167 | } | |
168 | ||
169 | const NameVTable service_vtable = { | |
170 | .suffix = ".service", | |
171 | ||
172 | .load = service_load, | |
173 | .dump = service_dump, | |
174 | ||
175 | .start = service_start, | |
176 | .stop = service_stop, | |
177 | .reload = service_reload, | |
178 | ||
179 | .active_state = service_active_state, | |
180 | ||
181 | .free_hook = service_free_hook | |
182 | }; |