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