chiark / gitweb /
journal: bump RLIMIT_NOFILE when journal files to 16K (if possible)
[elogind.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 "build.h"
35 #include "env-util.h"
36
37 static bool arg_ready = false;
38 static pid_t arg_pid = 0;
39 static const char *arg_status = NULL;
40 static bool arg_booted = false;
41
42 static void help(void) {
43         printf("%s [OPTIONS...] [VARIABLE=VALUE...]\n\n"
44                "Notify the init system about service status updates.\n\n"
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           Returns 0 if the system was booted up with systemd, non-zero otherwise\n",
51                program_invocation_short_name);
52 }
53
54 static int parse_argv(int argc, char *argv[]) {
55
56         enum {
57                 ARG_READY = 0x100,
58                 ARG_VERSION,
59                 ARG_PID,
60                 ARG_STATUS,
61                 ARG_BOOTED,
62         };
63
64         static const struct option options[] = {
65                 { "help",      no_argument,       NULL, 'h'           },
66                 { "version",   no_argument,       NULL, ARG_VERSION   },
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    },
71                 {}
72         };
73
74         int c;
75
76         assert(argc >= 0);
77         assert(argv);
78
79         while ((c = getopt_long(argc, argv, "h", options, NULL)) >= 0) {
80
81                 switch (c) {
82
83                 case 'h':
84                         help();
85                         return 0;
86
87                 case ARG_VERSION:
88                         puts(PACKAGE_STRING);
89                         puts(SYSTEMD_FEATURES);
90                         return 0;
91
92                 case ARG_READY:
93                         arg_ready = true;
94                         break;
95
96                 case ARG_PID:
97
98                         if (optarg) {
99                                 if (parse_pid(optarg, &arg_pid) < 0) {
100                                         log_error("Failed to parse PID %s.", optarg);
101                                         return -EINVAL;
102                                 }
103                         } else
104                                 arg_pid = getppid();
105
106                         break;
107
108                 case ARG_STATUS:
109                         arg_status = optarg;
110                         break;
111
112                 case ARG_BOOTED:
113                         arg_booted = true;
114                         break;
115
116                 case '?':
117                         return -EINVAL;
118
119                 default:
120                         assert_not_reached("Unhandled option");
121                 }
122         }
123
124         if (optind >= argc &&
125             !arg_ready &&
126             !arg_status &&
127             !arg_pid &&
128             !arg_booted) {
129                 help();
130                 return -EINVAL;
131         }
132
133         return 1;
134 }
135
136 int main(int argc, char* argv[]) {
137         _cleanup_free_ char *status = NULL, *cpid = NULL, *n = NULL;
138         _cleanup_strv_free_ char **final_env = NULL;
139         char* our_env[4];
140         unsigned i = 0;
141         int r;
142
143         log_parse_environment();
144         log_open();
145
146         r = parse_argv(argc, argv);
147         if (r <= 0)
148                 goto finish;
149
150         if (arg_booted)
151                 return sd_booted() <= 0;
152
153         if (arg_ready)
154                 our_env[i++] = (char*) "READY=1";
155
156         if (arg_status) {
157                 status = strappend("STATUS=", arg_status);
158                 if (!status) {
159                         r = log_oom();
160                         goto finish;
161                 }
162
163                 our_env[i++] = status;
164         }
165
166         if (arg_pid > 0) {
167                 if (asprintf(&cpid, "MAINPID="PID_FMT, arg_pid) < 0) {
168                         r = log_oom();
169                         goto finish;
170                 }
171
172                 our_env[i++] = cpid;
173         }
174
175         our_env[i++] = NULL;
176
177         final_env = strv_env_merge(2, our_env, argv + optind);
178         if (!final_env) {
179                 r = log_oom();
180                 goto finish;
181         }
182
183         if (strv_length(final_env) <= 0) {
184                 r = 0;
185                 goto finish;
186         }
187
188         n = strv_join(final_env, "\n");
189         if (!n) {
190                 r = log_oom();
191                 goto finish;
192         }
193
194         r = sd_pid_notify(arg_pid, false, n);
195         if (r < 0) {
196                 log_error_errno(r, "Failed to notify init system: %m");
197                 goto finish;
198         }
199
200         if (r == 0)
201                 r = -ENOTSUP;
202
203 finish:
204         return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
205 }