]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/notify/notify.c
remove unneeded error.h includes
[thirdparty/systemd.git] / src / notify / notify.c
1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
2
3 /***
4 This file is part of systemd.
5
6 Copyright 2010 Lennart Poettering
7
8 systemd is free software; you can redistribute it and/or modify it
9 under the terms of the GNU Lesser General Public License as published by
10 the Free Software Foundation; either version 2.1 of the License, or
11 (at your option) any later version.
12
13 systemd is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Lesser General Public License for more details.
17
18 You should have received a copy of the GNU Lesser General Public License
19 along with systemd; If not, see <http://www.gnu.org/licenses/>.
20 ***/
21
22 #include <stdio.h>
23 #include <getopt.h>
24 #include <errno.h>
25 #include <unistd.h>
26 #include <stdlib.h>
27 #include <string.h>
28
29 #include "systemd/sd-daemon.h"
30
31 #include "strv.h"
32 #include "util.h"
33 #include "log.h"
34 #include "sd-readahead.h"
35 #include "build.h"
36 #include "env-util.h"
37
38 static bool arg_ready = false;
39 static pid_t arg_pid = 0;
40 static const char *arg_status = NULL;
41 static bool arg_booted = false;
42 static const char *arg_readahead = NULL;
43
44 static void help(void) {
45 printf("%s [OPTIONS...] [VARIABLE=VALUE...]\n\n"
46 "Notify the init system about service status updates.\n\n"
47 " -h --help Show this help\n"
48 " --version Show package version\n"
49 " --ready Inform the init system about service start-up completion\n"
50 " --pid[=PID] Set main pid of daemon\n"
51 " --status=TEXT Set status text\n"
52 " --booted Returns 0 if the system was booted up with systemd, non-zero otherwise\n"
53 " --readahead=ACTION Controls read-ahead operations\n",
54 program_invocation_short_name);
55 }
56
57 static int parse_argv(int argc, char *argv[]) {
58
59 enum {
60 ARG_READY = 0x100,
61 ARG_VERSION,
62 ARG_PID,
63 ARG_STATUS,
64 ARG_BOOTED,
65 ARG_READAHEAD
66 };
67
68 static const struct option options[] = {
69 { "help", no_argument, NULL, 'h' },
70 { "version", no_argument, NULL, ARG_VERSION },
71 { "ready", no_argument, NULL, ARG_READY },
72 { "pid", optional_argument, NULL, ARG_PID },
73 { "status", required_argument, NULL, ARG_STATUS },
74 { "booted", no_argument, NULL, ARG_BOOTED },
75 { "readahead", required_argument, NULL, ARG_READAHEAD },
76 {}
77 };
78
79 int c;
80
81 assert(argc >= 0);
82 assert(argv);
83
84 while ((c = getopt_long(argc, argv, "h", options, NULL)) >= 0) {
85
86 switch (c) {
87
88 case 'h':
89 help();
90 return 0;
91
92 case ARG_VERSION:
93 puts(PACKAGE_STRING);
94 puts(SYSTEMD_FEATURES);
95 return 0;
96
97 case ARG_READY:
98 arg_ready = true;
99 break;
100
101 case ARG_PID:
102
103 if (optarg) {
104 if (parse_pid(optarg, &arg_pid) < 0) {
105 log_error("Failed to parse PID %s.", optarg);
106 return -EINVAL;
107 }
108 } else
109 arg_pid = getppid();
110
111 break;
112
113 case ARG_STATUS:
114 arg_status = optarg;
115 break;
116
117 case ARG_BOOTED:
118 arg_booted = true;
119 break;
120
121 case ARG_READAHEAD:
122 arg_readahead = optarg;
123 break;
124
125 case '?':
126 return -EINVAL;
127
128 default:
129 assert_not_reached("Unhandled option");
130 }
131 }
132
133 if (optind >= argc &&
134 !arg_ready &&
135 !arg_status &&
136 !arg_pid &&
137 !arg_booted &&
138 !arg_readahead) {
139 help();
140 return -EINVAL;
141 }
142
143 return 1;
144 }
145
146 int main(int argc, char* argv[]) {
147 _cleanup_free_ char *status = NULL, *cpid = NULL, *n = NULL;
148 _cleanup_strv_free_ char **final_env = NULL;
149 char* our_env[4];
150 unsigned i = 0;
151 int r;
152
153 log_parse_environment();
154 log_open();
155
156 r = parse_argv(argc, argv);
157 if (r <= 0)
158 goto finish;
159
160 if (arg_booted)
161 return sd_booted() <= 0;
162
163 if (arg_readahead) {
164 r = sd_readahead(arg_readahead);
165 if (r < 0) {
166 log_error("Failed to issue read-ahead control command: %s", strerror(-r));
167 goto finish;
168 }
169 }
170
171 if (arg_ready)
172 our_env[i++] = (char*) "READY=1";
173
174 if (arg_status) {
175 status = strappend("STATUS=", arg_status);
176 if (!status) {
177 r = log_oom();
178 goto finish;
179 }
180
181 our_env[i++] = status;
182 }
183
184 if (arg_pid > 0) {
185 if (asprintf(&cpid, "MAINPID="PID_FMT, arg_pid) < 0) {
186 r = log_oom();
187 goto finish;
188 }
189
190 our_env[i++] = cpid;
191 }
192
193 our_env[i++] = NULL;
194
195 final_env = strv_env_merge(2, our_env, argv + optind);
196 if (!final_env) {
197 r = log_oom();
198 goto finish;
199 }
200
201 if (strv_length(final_env) <= 0) {
202 r = 0;
203 goto finish;
204 }
205
206 n = strv_join(final_env, "\n");
207 if (!n) {
208 r = log_oom();
209 goto finish;
210 }
211
212 r = sd_pid_notify(arg_pid, false, n);
213 if (r < 0) {
214 log_error("Failed to notify init system: %s", strerror(-r));
215 goto finish;
216 }
217
218 if (r == 0)
219 r = -ENOTSUP;
220
221 finish:
222 return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
223 }