]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/notify/notify.c
Add SPDX license identifiers to source files under the LGPL
[thirdparty/systemd.git] / src / notify / notify.c
CommitLineData
53e1b683 1/* SPDX-License-Identifier: LGPL-2.1+ */
4a2a8b5a
LP
2/***
3 This file is part of systemd.
4
5 Copyright 2010 Lennart Poettering
6
7 systemd is free software; you can redistribute it and/or modify it
5430f7f2
LP
8 under the terms of the GNU Lesser General Public License as published by
9 the Free Software Foundation; either version 2.1 of the License, or
4a2a8b5a
LP
10 (at your option) any later version.
11
12 systemd is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
5430f7f2 15 Lesser General Public License for more details.
4a2a8b5a 16
5430f7f2 17 You should have received a copy of the GNU Lesser General Public License
4a2a8b5a
LP
18 along with systemd; If not, see <http://www.gnu.org/licenses/>.
19***/
20
4a2a8b5a 21#include <errno.h>
6f2deb84
LP
22#include <getopt.h>
23#include <stdio.h>
4a2a8b5a 24#include <stdlib.h>
6f2deb84 25#include <unistd.h>
4a2a8b5a 26
6f2deb84 27#include "sd-daemon.h"
81527be1 28
b5efdb8a 29#include "alloc-util.h"
4d1a6904 30#include "env-util.h"
f97b34a6 31#include "format-util.h"
6f2deb84 32#include "log.h"
6bedfcbb 33#include "parse-util.h"
07630cea 34#include "string-util.h"
6f2deb84
LP
35#include "strv.h"
36#include "util.h"
4a2a8b5a
LP
37
38static bool arg_ready = false;
39static pid_t arg_pid = 0;
40static const char *arg_status = NULL;
96551bae 41static bool arg_booted = false;
4a2a8b5a 42
601185b4 43static void help(void) {
2e33c433 44 printf("%s [OPTIONS...] [VARIABLE=VALUE...]\n\n"
4a2a8b5a 45 "Notify the init system about service status updates.\n\n"
b57b0625
ZJS
46 " -h --help Show this help\n"
47 " --version Show package version\n"
48 " --ready Inform the init system about service start-up completion\n"
49 " --pid[=PID] Set main pid of daemon\n"
50 " --status=TEXT Set status text\n"
51 " --booted Check if the system was booted up with systemd\n",
4a2a8b5a 52 program_invocation_short_name);
4a2a8b5a
LP
53}
54
55static int parse_argv(int argc, char *argv[]) {
56
57 enum {
58 ARG_READY = 0x100,
9aac0b2c 59 ARG_VERSION,
4a2a8b5a 60 ARG_PID,
96551bae 61 ARG_STATUS,
6624768c 62 ARG_BOOTED,
4a2a8b5a
LP
63 };
64
65 static const struct option options[] = {
6624768c 66 { "help", no_argument, NULL, 'h' },
9aac0b2c 67 { "version", no_argument, NULL, ARG_VERSION },
6624768c
LP
68 { "ready", no_argument, NULL, ARG_READY },
69 { "pid", optional_argument, NULL, ARG_PID },
70 { "status", required_argument, NULL, ARG_STATUS },
71 { "booted", no_argument, NULL, ARG_BOOTED },
eb9da376 72 {}
4a2a8b5a
LP
73 };
74
75 int c;
76
77 assert(argc >= 0);
78 assert(argv);
79
ee8c4568 80 while ((c = getopt_long(argc, argv, "h", options, NULL)) >= 0) {
4a2a8b5a
LP
81
82 switch (c) {
83
84 case 'h':
601185b4
ZJS
85 help();
86 return 0;
4a2a8b5a 87
9aac0b2c 88 case ARG_VERSION:
3f6fd1ba 89 return version();
9aac0b2c 90
4a2a8b5a
LP
91 case ARG_READY:
92 arg_ready = true;
93 break;
94
95 case ARG_PID:
96
97 if (optarg) {
98 if (parse_pid(optarg, &arg_pid) < 0) {
99 log_error("Failed to parse PID %s.", optarg);
100 return -EINVAL;
101 }
102 } else
103 arg_pid = getppid();
104
105 break;
106
107 case ARG_STATUS:
108 arg_status = optarg;
109 break;
110
96551bae
LP
111 case ARG_BOOTED:
112 arg_booted = true;
113 break;
114
4a2a8b5a
LP
115 case '?':
116 return -EINVAL;
117
118 default:
eb9da376 119 assert_not_reached("Unhandled option");
4a2a8b5a 120 }
ee8c4568 121 }
4a2a8b5a 122
2f02ce40
LP
123 if (optind >= argc &&
124 !arg_ready &&
125 !arg_status &&
126 !arg_pid &&
d6bc8348 127 !arg_booted) {
2f02ce40
LP
128 help();
129 return -EINVAL;
130 }
131
4a2a8b5a
LP
132 return 1;
133}
134
135int main(int argc, char* argv[]) {
be8f4e9e
LP
136 _cleanup_free_ char *status = NULL, *cpid = NULL, *n = NULL;
137 _cleanup_strv_free_ char **final_env = NULL;
138 char* our_env[4];
4a2a8b5a 139 unsigned i = 0;
be8f4e9e 140 int r;
4a2a8b5a
LP
141
142 log_parse_environment();
2396fb04 143 log_open();
4a2a8b5a 144
6c12b52e 145 r = parse_argv(argc, argv);
be8f4e9e 146 if (r <= 0)
4a2a8b5a 147 goto finish;
4a2a8b5a 148
96551bae
LP
149 if (arg_booted)
150 return sd_booted() <= 0;
151
4a2a8b5a
LP
152 if (arg_ready)
153 our_env[i++] = (char*) "READY=1";
154
155 if (arg_status) {
be8f4e9e
LP
156 status = strappend("STATUS=", arg_status);
157 if (!status) {
158 r = log_oom();
4a2a8b5a
LP
159 goto finish;
160 }
161
162 our_env[i++] = status;
163 }
164
165 if (arg_pid > 0) {
de0671ee 166 if (asprintf(&cpid, "MAINPID="PID_FMT, arg_pid) < 0) {
be8f4e9e 167 r = log_oom();
4a2a8b5a
LP
168 goto finish;
169 }
170
171 our_env[i++] = cpid;
172 }
173
174 our_env[i++] = NULL;
175
be8f4e9e
LP
176 final_env = strv_env_merge(2, our_env, argv + optind);
177 if (!final_env) {
178 r = log_oom();
4a2a8b5a
LP
179 goto finish;
180 }
181
182 if (strv_length(final_env) <= 0) {
be8f4e9e 183 r = 0;
4a2a8b5a
LP
184 goto finish;
185 }
186
be8f4e9e
LP
187 n = strv_join(final_env, "\n");
188 if (!n) {
189 r = log_oom();
4a2a8b5a
LP
190 goto finish;
191 }
192
9de009a9 193 r = sd_pid_notify(arg_pid ? arg_pid : getppid(), false, n);
be8f4e9e 194 if (r < 0) {
da927ba9 195 log_error_errno(r, "Failed to notify init system: %m");
4a2a8b5a 196 goto finish;
39b50ad1
EV
197 } else if (r == 0) {
198 log_error("No status data could be sent: $NOTIFY_SOCKET was not set");
15411c0c 199 r = -EOPNOTSUPP;
39b50ad1 200 }
4a2a8b5a
LP
201
202finish:
be8f4e9e 203 return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
4a2a8b5a 204}