chiark / gitweb /
ac9c39c3c83d16dfd88b69c045e0483b6771b945
[elogind.git] / service.c
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 };