chiark / gitweb /
network-address,test-network: avoid undefined behaviour
[elogind.git] / src / network / networkd-wait-online.c
1
2 /***
3   This file is part of systemd.
4
5   Copyright 2013 Tom Gundersen <teg@jklm.no>
6
7   systemd is free software; you can redistribute it and/or modify it
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
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
15   Lesser General Public License for more details.
16
17   You should have received a copy of the GNU Lesser General Public License
18   along with systemd; If not, see <http://www.gnu.org/licenses/>.
19 ***/
20
21 #include <getopt.h>
22
23 #include "sd-daemon.h"
24
25 #include "networkd-wait-online.h"
26
27 #include "strv.h"
28 #include "build.h"
29
30 static bool arg_quiet = false;
31 static usec_t arg_timeout = 120 * USEC_PER_SEC;
32 static char **arg_interfaces = NULL;
33 static char **arg_ignore = NULL;
34
35 static void help(void) {
36         printf("%s [OPTIONS...]\n\n"
37                "Block until network is configured.\n\n"
38                "  -h --help                 Show this help\n"
39                "     --version              Print version string\n"
40                "  -q --quiet                Do not show status information\n"
41                "  -i --interface=INTERFACE  Block until at least these interfaces have appeared\n"
42                "     --ignore=INTERFACE     Don't take these interfaces into account\n"
43                "     --timeout=SECS         Maximum time to wait for network connectivity\n"
44                , program_invocation_short_name);
45 }
46
47 static int parse_argv(int argc, char *argv[]) {
48
49         enum {
50                 ARG_VERSION = 0x100,
51                 ARG_IGNORE,
52                 ARG_TIMEOUT,
53         };
54
55         static const struct option options[] = {
56                 { "help",            no_argument,       NULL, 'h'         },
57                 { "version",         no_argument,       NULL, ARG_VERSION },
58                 { "quiet",           no_argument,       NULL, 'q'         },
59                 { "interface",       required_argument, NULL, 'i'         },
60                 { "ignore",          required_argument, NULL, ARG_IGNORE  },
61                 { "timeout",         required_argument, NULL, ARG_TIMEOUT  },
62                 {}
63         };
64
65         int c, r;
66
67         assert(argc >= 0);
68         assert(argv);
69
70         while ((c = getopt_long(argc, argv, "+hiq", options, NULL)) >= 0)
71
72                 switch (c) {
73
74                 case 'h':
75                         help();
76                         return 0;
77
78                 case 'q':
79                         arg_quiet = true;
80                         break;
81
82                 case ARG_VERSION:
83                         puts(PACKAGE_STRING);
84                         puts(SYSTEMD_FEATURES);
85                         return 0;
86
87                 case 'i':
88                         if (strv_extend(&arg_interfaces, optarg) < 0)
89                                 return log_oom();
90
91                         break;
92
93                 case ARG_IGNORE:
94                         if (strv_extend(&arg_ignore, optarg) < 0)
95                                 return log_oom();
96
97                         break;
98
99                 case ARG_TIMEOUT:
100                         r = parse_sec(optarg, &arg_timeout);
101                         if (r < 0)
102                                 return r;
103
104                         break;
105
106                 case '?':
107                         return -EINVAL;
108
109                 default:
110                         assert_not_reached("Unhandled option");
111                 }
112
113         return 1;
114 }
115
116 int main(int argc, char *argv[]) {
117         _cleanup_(manager_freep) Manager *m = NULL;
118         int r;
119
120         log_set_target(LOG_TARGET_AUTO);
121         log_parse_environment();
122         log_open();
123
124         umask(0022);
125
126         r = parse_argv(argc, argv);
127         if (r <= 0)
128                 return r;
129
130         if (arg_quiet)
131                 log_set_max_level(LOG_WARNING);
132
133         assert_se(sigprocmask_many(SIG_BLOCK, SIGTERM, SIGINT, -1) == 0);
134
135         r = manager_new(&m, arg_interfaces, arg_ignore, arg_timeout);
136         if (r < 0) {
137                 log_error_errno(r, "Could not create manager: %m");
138                 goto finish;
139         }
140
141         if (manager_all_configured(m)) {
142                 r = 0;
143                 goto finish;
144         }
145
146         sd_notify(false,
147                   "READY=1\n"
148                   "STATUS=Waiting for network connections...");
149
150         r = sd_event_loop(m->event);
151         if (r < 0) {
152                 log_error_errno(r, "Event loop failed: %m");
153                 goto finish;
154         }
155
156 finish:
157         strv_free(arg_interfaces);
158         strv_free(arg_ignore);
159
160         if (r >= 0) {
161                 sd_notify(false, "STATUS=All interfaces configured...");
162
163                 return EXIT_SUCCESS;
164         } else {
165                 sd_notify(false, "STATUS=Failed waiting for network connectivity...");
166
167                 return EXIT_FAILURE;
168         }
169 }