~ubuntu-branches/ubuntu/trusty/systemd/trusty

« back to all changes in this revision

Viewing changes to src/shutdownd/shutdownd.c

Tags: upstream-202
ImportĀ upstreamĀ versionĀ 202

Show diffs side-by-side

added added

removed removed

Lines of Context:
46
46
};
47
47
 
48
48
static int read_packet(int fd, union shutdown_buffer *_b) {
49
 
        struct msghdr msghdr;
50
 
        struct iovec iovec;
51
49
        struct ucred *ucred;
 
50
        ssize_t n;
 
51
 
 
52
        union shutdown_buffer b; /* We maintain our own copy here, in
 
53
                                  * order not to corrupt the last message */
 
54
        struct iovec iovec = {
 
55
                iovec.iov_base = &b,
 
56
                iovec.iov_len = sizeof(b) - 1,
 
57
        };
52
58
        union {
53
59
                struct cmsghdr cmsghdr;
54
60
                uint8_t buf[CMSG_SPACE(sizeof(struct ucred))];
55
 
        } control;
56
 
        ssize_t n;
57
 
        union shutdown_buffer b; /* We maintain our own copy here, in order not to corrupt the last message */
 
61
        } control = {};
 
62
        struct msghdr msghdr = {
 
63
                .msg_iov = &iovec,
 
64
                msghdr.msg_iovlen = 1,
 
65
                msghdr.msg_control = &control,
 
66
                msghdr.msg_controllen = sizeof(control),
 
67
        };
58
68
 
59
69
        assert(fd >= 0);
60
70
        assert(_b);
61
71
 
62
 
        zero(iovec);
63
 
        iovec.iov_base = &b;
64
 
        iovec.iov_len = sizeof(b) - 1;
65
 
 
66
 
        zero(control);
67
 
        zero(msghdr);
68
 
        msghdr.msg_iov = &iovec;
69
 
        msghdr.msg_iovlen = 1;
70
 
        msghdr.msg_control = &control;
71
 
        msghdr.msg_controllen = sizeof(control);
72
 
 
73
72
        n = recvmsg(fd, &msghdr, MSG_DONTWAIT);
74
73
        if (n <= 0) {
75
74
                if (n == 0) {
157
156
                usec_t delay;
158
157
                usec_t interval;
159
158
        } table[] = {
160
 
                { 10 * USEC_PER_MINUTE, USEC_PER_MINUTE      },
161
 
                { USEC_PER_HOUR,        15 * USEC_PER_MINUTE },
162
 
                { 3 * USEC_PER_HOUR,    30 * USEC_PER_MINUTE }
 
159
                { 0,                    USEC_PER_MINUTE      },
 
160
                { 10 * USEC_PER_MINUTE, 15 * USEC_PER_MINUTE },
 
161
                { USEC_PER_HOUR,        30 * USEC_PER_MINUTE },
 
162
                { 3 * USEC_PER_HOUR,    USEC_PER_HOUR        },
163
163
        };
164
164
 
165
165
        usec_t left, sub;
166
 
        unsigned i;
 
166
        unsigned i = ELEMENTSOF(table) - 1;
167
167
 
168
168
        /* If the time is already passed, then don't announce */
169
169
        if (n >= elapse)
170
170
                return 0;
171
171
 
172
172
        left = elapse - n;
173
 
        for (i = 0; i < ELEMENTSOF(table); i++)
174
 
                if (n + table[i].delay >= elapse) {
175
 
                        sub = ((left / table[i].interval) * table[i].interval);
176
 
                        break;
177
 
                }
178
 
 
179
 
        if (i >= ELEMENTSOF(table))
180
 
                sub = ((left / USEC_PER_HOUR) * USEC_PER_HOUR);
181
 
 
182
 
        return elapse > sub ? elapse - sub : 1;
 
173
        while (left < table[i].delay)
 
174
                i--;
 
175
        sub = (left / table[i].interval) * table[i].interval;
 
176
 
 
177
        assert(sub < elapse);
 
178
        return elapse - sub;
183
179
}
184
180
 
185
181
static usec_t when_nologin(usec_t elapse) {
273
269
        };
274
270
 
275
271
        int r = EXIT_FAILURE, n_fds;
276
 
        union shutdown_buffer b;
277
 
        struct pollfd pollfd[_FD_MAX];
 
272
        union shutdown_buffer b = {};
 
273
        struct pollfd pollfd[_FD_MAX] = {};
278
274
        bool exec_shutdown = false, unlink_nologin = false;
279
275
        unsigned i;
280
276
 
305
301
                return EXIT_FAILURE;
306
302
        }
307
303
 
308
 
        zero(b);
309
 
        zero(pollfd);
310
 
 
311
304
        pollfd[FD_SOCKET].fd = SD_LISTEN_FDS_START;
312
305
        pollfd[FD_SOCKET].events = POLLIN;
313
306
 
405
398
                }
406
399
 
407
400
                if (pollfd[FD_WALL_TIMER].revents) {
408
 
                        struct itimerspec its;
 
401
                        struct itimerspec its = {};
409
402
 
410
403
                        warn_wall(n, &b.command);
411
404
                        flush_fd(pollfd[FD_WALL_TIMER].fd);
412
405
 
413
406
                        /* Restart timer */
414
 
                        zero(its);
415
407
                        timespec_store(&its.it_value, when_wall(n, b.command.usec));
416
408
                        if (timerfd_settime(pollfd[FD_WALL_TIMER].fd, TFD_TIMER_ABSTIME, &its, NULL) < 0) {
417
409
                                log_error("timerfd_settime(): %m");
424
416
 
425
417
                        log_info("Creating /run/nologin, blocking further logins...");
426
418
 
427
 
                        e = write_one_line_file_atomic("/run/nologin", "System is going down.");
 
419
                        e = write_string_file_atomic("/run/nologin", "System is going down.");
428
420
                        if (e < 0)
429
421
                                log_error("Failed to create /run/nologin: %s", strerror(-e));
430
422
                        else