Пример #1
0
int config_parse_prefix_lifetime(const char *unit,
                                 const char *filename,
                                 unsigned line,
                                 const char *section,
                                 unsigned section_line,
                                 const char *lvalue,
                                 int ltype,
                                 const char *rvalue,
                                 void *data,
                                 void *userdata) {
        Network *network = userdata;
        _cleanup_(prefix_free_or_set_invalidp) Prefix *p = NULL;
        usec_t usec;
        int r;

        assert(filename);
        assert(section);
        assert(lvalue);
        assert(rvalue);
        assert(data);

        r = prefix_new_static(network, filename, section_line, &p);
        if (r < 0)
                return r;

        r = parse_sec(rvalue, &usec);
        if (r < 0) {
                log_syntax(unit, LOG_ERR, filename, line, r, "Lifetime is invalid, ignoring assignment: %s", rvalue);
                return 0;
        }

        /* a value of 0xffffffff represents infinity */
        if (streq(lvalue, "PreferredLifetimeSec"))
                r = sd_radv_prefix_set_preferred_lifetime(p->radv_prefix,
                                                          DIV_ROUND_UP(usec, USEC_PER_SEC));
        else if (streq(lvalue, "ValidLifetimeSec"))
                r = sd_radv_prefix_set_valid_lifetime(p->radv_prefix,
                                                      DIV_ROUND_UP(usec, USEC_PER_SEC));
        if (r < 0)
                return r;

        p = NULL;

        return 0;
}
Пример #2
0
static void test_format_timespan_one(usec_t x, usec_t accuracy) {
        char l[FORMAT_TIMESPAN_MAX];
        const char *t;
        usec_t y;

        log_info(USEC_FMT"     (at accuracy "USEC_FMT")", x, accuracy);

        assert_se(t = format_timespan(l, sizeof l, x, accuracy));
        log_info(" = <%s>", t);

        assert_se(parse_sec(t, &y) >= 0);
        log_info(" = "USEC_FMT, y);

        if (accuracy <= 0)
                accuracy = 1;

        assert_se(x / accuracy == y / accuracy);
}
static int parse_argv(int argc, char *argv[]) {
        static const struct option options[] = {
                { "timeout",        required_argument, NULL, 't' },
                { "exit-if-exists", required_argument, NULL, 'E' },
                { "version",        no_argument,       NULL, 'V' },
                { "help",           no_argument,       NULL, 'h' },
                { "seq-start",      required_argument, NULL, 's' }, /* removed */
                { "seq-end",        required_argument, NULL, 'e' }, /* removed */
                { "quiet",          no_argument,       NULL, 'q' }, /* removed */
                {}
        };

        int c, r;

        while ((c = getopt_long(argc, argv, "t:E:Vhs:e:q", options, NULL)) >= 0) {
                switch (c) {
                case 't':
                        r = parse_sec(optarg, &arg_timeout);
                        if (r < 0)
                                return log_error_errno(r, "Failed to parse timeout value '%s': %m", optarg);
                        break;
                case 'E':
                        arg_exists = optarg;
                        break;
                case 'V':
                        return print_version();
                case 'h':
                        return help();
                case 's':
                case 'e':
                case 'q':
                        return log_info_errno(SYNTHETIC_ERRNO(EINVAL),
                                              "Option -%c no longer supported.",
                                              c);
                case '?':
                        return -EINVAL;
                default:
                        assert_not_reached("Unknown option.");
                }
        }

        return 1;
}
Пример #4
0
int generator_write_timeouts(
                const char *dir,
                const char *what,
                const char *where,
                const char *opts,
                char **filtered) {

        /* Allow configuration how long we wait for a device that
         * backs a mount point to show up. This is useful to support
         * endless device timeouts for devices that show up only after
         * user input, like crypto devices. */

        _cleanup_free_ char *node = NULL, *unit = NULL, *timeout = NULL;
        usec_t u;
        int r;

        r = fstab_filter_options(opts, "comment=systemd.device-timeout\0" "x-systemd.device-timeout\0",
                                 NULL, &timeout, filtered);
        if (r <= 0)
                return r;

        r = parse_sec(timeout, &u);
        if (r < 0) {
                log_warning("Failed to parse timeout for %s, ignoring: %s", where, timeout);
                return 0;
        }

        node = fstab_node_to_udev_node(what);
        if (!node)
                return log_oom();

        r = unit_name_from_path(node, ".device", &unit);
        if (r < 0)
                return log_error_errno(r, "Failed to make unit name from path: %m");

        return write_drop_in_format(dir, unit, 50, "device-timeout",
                                    "# Automatically generated by %s\n\n"
                                    "[Unit]\nJobTimeoutSec=%s",
                                    program_invocation_short_name, timeout);
}
Пример #5
0
static int write_idle_timeout(FILE *f, const char *where, const char *opts) {
        _cleanup_free_ char *timeout = NULL;
        char timespan[FORMAT_TIMESPAN_MAX];
        usec_t u;
        int r;

        r = fstab_filter_options(opts, "x-systemd.idle-timeout\0", NULL, &timeout, NULL);
        if (r < 0)
                return log_warning_errno(r, "Failed to parse options: %m");
        if (r == 0)
                return 0;

        r = parse_sec(timeout, &u);
        if (r < 0) {
                log_warning("Failed to parse timeout for %s, ignoring: %s", where, timeout);
                return 0;
        }

        fprintf(f, "TimeoutIdleSec=%s\n", format_timespan(timespan, sizeof(timespan), u, 0));

        return 0;
}
Пример #6
0
int udev_parse_config_full(
                unsigned *ret_children_max,
                usec_t *ret_exec_delay_usec,
                usec_t *ret_event_timeout_usec,
                ResolveNameTiming *ret_resolve_name_timing) {

        _cleanup_free_ char *log_val = NULL, *children_max = NULL, *exec_delay = NULL, *event_timeout = NULL, *resolve_names = NULL;
        int r;

        r = parse_env_file(NULL, "/etc/udev/udev.conf",
                           "udev_log", &log_val,
                           "children_max", &children_max,
                           "exec_delay", &exec_delay,
                           "event_timeout", &event_timeout,
                           "resolve_names", &resolve_names);
        if (r == -ENOENT)
                return 0;
        if (r < 0)
                return r;

        if (log_val) {
                const char *log;
                size_t n;

                /* unquote */
                n = strlen(log_val);
                if (n >= 2 &&
                    ((log_val[0] == '"' && log_val[n-1] == '"') ||
                     (log_val[0] == '\'' && log_val[n-1] == '\''))) {
                        log_val[n - 1] = '\0';
                        log = log_val + 1;
                } else
                        log = log_val;

                /* we set the udev log level here explicitly, this is supposed
                 * to regulate the code in libudev/ and udev/. */
                r = log_set_max_level_from_string_realm(LOG_REALM_UDEV, log);
                if (r < 0)
                        log_debug_errno(r, "/etc/udev/udev.conf: failed to set udev log level '%s', ignoring: %m", log);
        }

        if (ret_children_max && children_max) {
                r = safe_atou(children_max, ret_children_max);
                if (r < 0)
                        log_notice_errno(r, "/etc/udev/udev.conf: failed to set parse children_max=%s, ignoring: %m", children_max);
        }

        if (ret_exec_delay_usec && exec_delay) {
                r = parse_sec(exec_delay, ret_exec_delay_usec);
                if (r < 0)
                        log_notice_errno(r, "/etc/udev/udev.conf: failed to set parse exec_delay=%s, ignoring: %m", exec_delay);
        }

        if (ret_event_timeout_usec && event_timeout) {
                r = parse_sec(event_timeout, ret_event_timeout_usec);
                if (r < 0)
                        log_notice_errno(r, "/etc/udev/udev.conf: failed to set parse event_timeout=%s, ignoring: %m", event_timeout);
        }

        if (ret_resolve_name_timing && resolve_names) {
                ResolveNameTiming t;

                t = resolve_name_timing_from_string(resolve_names);
                if (t < 0)
                        log_notice("/etc/udev/udev.conf: failed to set parse resolve_names=%s, ignoring.", resolve_names);
                else
                        *ret_resolve_name_timing = t;
        }

        return 0;
}
Пример #7
0
int main(int argc, char *argv[]) {
        enum {
                MODE_BISECT,
                MODE_CHART,
        } mode = MODE_BISECT;
        Type type = TYPE_KDBUS;
        int i, pair[2] = { -1, -1 };
        _cleanup_free_ char *name = NULL, *bus_name = NULL, *address = NULL, *server_name = NULL;
        _cleanup_close_ int bus_ref = -1;
        const char *unique;
        cpu_set_t cpuset;
        size_t result;
        sd_bus *b;
        pid_t pid;
        int r;

        for (i = 1; i < argc; i++) {
                if (streq(argv[i], "chart")) {
                        mode = MODE_CHART;
                        continue;
                } else if (streq(argv[i], "legacy")) {
                        type = TYPE_LEGACY;
                        continue;
                } else if (streq(argv[i], "direct")) {
                        type = TYPE_DIRECT;
                        continue;
                }

                assert_se(parse_sec(argv[i], &arg_loop_usec) >= 0);
        }

        assert_se(!MODE_BISECT || TYPE_KDBUS);

        assert_se(arg_loop_usec > 0);

        if (type == TYPE_KDBUS) {
                assert_se(asprintf(&name, "deine-mutter-%u", (unsigned) getpid()) >= 0);

                bus_ref = bus_kernel_create_bus(name, false, &bus_name);
                if (bus_ref == -ENOENT)
                        exit(EXIT_TEST_SKIP);

                assert_se(bus_ref >= 0);

                address = strappend("kernel:path=", bus_name);
                assert_se(address);
        } else if (type == TYPE_LEGACY) {
                const char *e;

                e = secure_getenv("DBUS_SESSION_BUS_ADDRESS");
                assert_se(e);

                address = strdup(e);
                assert_se(address);
        }

        r = sd_bus_new(&b);
        assert_se(r >= 0);

        if (type == TYPE_DIRECT) {
                assert_se(socketpair(AF_UNIX, SOCK_STREAM, 0, pair) >= 0);

                r = sd_bus_set_fd(b, pair[0], pair[0]);
                assert_se(r >= 0);

                r = sd_bus_set_server(b, true, SD_ID128_NULL);
                assert_se(r >= 0);
        } else {
                r = sd_bus_set_address(b, address);
                assert_se(r >= 0);

                r = sd_bus_set_bus_client(b, true);
                assert_se(r >= 0);
        }

        r = sd_bus_start(b);
        assert_se(r >= 0);

        if (type != TYPE_DIRECT) {
                r = sd_bus_get_unique_name(b, &unique);
                assert_se(r >= 0);

                server_name = strdup(unique);
                assert_se(server_name);
        }

        sync();
        setpriority(PRIO_PROCESS, 0, -19);

        pid = fork();
        assert_se(pid >= 0);

        if (pid == 0) {
                CPU_ZERO(&cpuset);
                CPU_SET(0, &cpuset);
                pthread_setaffinity_np(pthread_self(), sizeof(cpu_set_t), &cpuset);

                safe_close(bus_ref);
                sd_bus_unref(b);

                switch (mode) {
                case MODE_BISECT:
                        client_bisect(address, server_name);
                        break;

                case MODE_CHART:
                        client_chart(type, address, server_name, pair[1]);
                        break;
                }

                _exit(0);
        }

        CPU_ZERO(&cpuset);
        CPU_SET(1, &cpuset);
        pthread_setaffinity_np(pthread_self(), sizeof(cpu_set_t), &cpuset);

        server(b, &result);

        if (mode == MODE_BISECT)
                printf("Copying/memfd are equally fast at %zu bytes\n", result);

        assert_se(waitpid(pid, NULL, 0) == pid);

        safe_close(pair[1]);
        sd_bus_unref(b);

        return 0;
}
Пример #8
0
static int parse_argv(int argc, char *argv[]) {

        enum {
                ARG_ICON = 0x100,
                ARG_TIMEOUT,
                ARG_ECHO,
                ARG_NO_TTY,
                ARG_ACCEPT_CACHED,
                ARG_MULTIPLE,
                ARG_ID,
                ARG_KEYNAME,
                ARG_NO_OUTPUT,
        };

        static const struct option options[] = {
                { "help",          no_argument,       NULL, 'h'               },
                { "icon",          required_argument, NULL, ARG_ICON          },
                { "timeout",       required_argument, NULL, ARG_TIMEOUT       },
                { "echo",          no_argument,       NULL, ARG_ECHO          },
                { "no-tty",        no_argument,       NULL, ARG_NO_TTY        },
                { "accept-cached", no_argument,       NULL, ARG_ACCEPT_CACHED },
                { "multiple",      no_argument,       NULL, ARG_MULTIPLE      },
                { "id",            required_argument, NULL, ARG_ID            },
                { "keyname",       required_argument, NULL, ARG_KEYNAME       },
                { "no-output",     no_argument,       NULL, ARG_NO_OUTPUT     },
                {}
        };

        int c;

        assert(argc >= 0);
        assert(argv);

        while ((c = getopt_long(argc, argv, "h", options, NULL)) >= 0)

                switch (c) {

                case 'h':
                        help();
                        return 0;

                case ARG_ICON:
                        arg_icon = optarg;
                        break;

                case ARG_TIMEOUT:
                        if (parse_sec(optarg, &arg_timeout) < 0) {
                                log_error("Failed to parse --timeout parameter %s", optarg);
                                return -EINVAL;
                        }
                        break;

                case ARG_ECHO:
                        arg_flags |= ASK_PASSWORD_ECHO;
                        break;

                case ARG_NO_TTY:
                        arg_flags |= ASK_PASSWORD_NO_TTY;
                        break;

                case ARG_ACCEPT_CACHED:
                        arg_flags |= ASK_PASSWORD_ACCEPT_CACHED;
                        break;

                case ARG_MULTIPLE:
                        arg_multiple = true;
                        break;

                case ARG_ID:
                        arg_id = optarg;
                        break;

                case ARG_KEYNAME:
                        arg_keyname = optarg;
                        break;

                case ARG_NO_OUTPUT:
                        arg_no_output = true;
                        break;

                case '?':
                        return -EINVAL;

                default:
                        assert_not_reached("Unhandled option");
                }

        if (argc > optind) {
                arg_message = strv_join(argv + optind, " ");
                if (!arg_message)
                        return log_oom();
        }

        return 1;
}
Пример #9
0
static int parse_argv(int argc, char *argv[]) {

        enum {
                ARG_VERSION = 0x100,
                ARG_IGNORE,
                ARG_TIMEOUT,
        };

        static const struct option options[] = {
                { "help",            no_argument,       NULL, 'h'         },
                { "version",         no_argument,       NULL, ARG_VERSION },
                { "quiet",           no_argument,       NULL, 'q'         },
                { "interface",       required_argument, NULL, 'i'         },
                { "ignore",          required_argument, NULL, ARG_IGNORE  },
                { "timeout",         required_argument, NULL, ARG_TIMEOUT  },
                {}
        };

        int c, r;

        assert(argc >= 0);
        assert(argv);

        while ((c = getopt_long(argc, argv, "+hiq", options, NULL)) >= 0)

                switch (c) {

                case 'h':
                        help();
                        return 0;

                case 'q':
                        arg_quiet = true;
                        break;

                case ARG_VERSION:
                        puts(PACKAGE_STRING);
                        puts(SYSTEMD_FEATURES);
                        return 0;

                case 'i':
                        if (strv_extend(&arg_interfaces, optarg) < 0)
                                return log_oom();

                        break;

                case ARG_IGNORE:
                        if (strv_extend(&arg_ignore, optarg) < 0)
                                return log_oom();

                        break;

                case ARG_TIMEOUT:
                        r = parse_sec(optarg, &arg_timeout);
                        if (r < 0)
                                return r;

                        break;

                case '?':
                        return -EINVAL;

                default:
                        assert_not_reached("Unhandled option");
                }

        return 1;
}
Пример #10
0
static int parse_argv(int argc, char *argv[]) {

        enum {
                ARG_VERSION = 0x100,
                ARG_FILES_MAX,
                ARG_FILE_SIZE_MAX,
                ARG_TIMEOUT
        };

        static const struct option options[] = {
                { "help",          no_argument,       NULL, 'h'                },
                { "version",       no_argument,       NULL, ARG_VERSION        },
                { "files-max",     required_argument, NULL, ARG_FILES_MAX      },
                { "file-size-max", required_argument, NULL, ARG_FILE_SIZE_MAX  },
                { "timeout",       required_argument, NULL, ARG_TIMEOUT        },
                {}
        };

        int c;

        assert(argc >= 0);
        assert(argv);

        while ((c = getopt_long(argc, argv, "h", options, NULL)) >= 0) {

                switch (c) {

                case 'h':
                        return help();

                case ARG_VERSION:
                        puts(PACKAGE_STRING);
                        puts(SYSTEMD_FEATURES);
                        return 0;

                case ARG_FILES_MAX:
                        if (safe_atou(optarg, &arg_files_max) < 0 || arg_files_max <= 0) {
                                log_error("Failed to parse maximum number of files %s.", optarg);
                                return -EINVAL;
                        }
                        break;

                case ARG_FILE_SIZE_MAX: {
                        unsigned long long ull;

                        if (safe_atollu(optarg, &ull) < 0 || ull <= 0) {
                                log_error("Failed to parse maximum file size %s.", optarg);
                                return -EINVAL;
                        }

                        arg_file_size_max = (off_t) ull;
                        break;
                }

                case ARG_TIMEOUT:
                        if (parse_sec(optarg, &arg_timeout) < 0 || arg_timeout <= 0) {
                                log_error("Failed to parse timeout %s.", optarg);
                                return -EINVAL;
                        }

                        break;

                case '?':
                        return -EINVAL;

                default:
                        assert_not_reached("Unhandled option");
                }
        }

        if (optind != argc-1 &&
            optind != argc-2) {
                help();
                return -EINVAL;
        }

        return 1;
}
Пример #11
0
int parse_timestamp(const char *t, usec_t *usec) {
        static const struct {
                const char *name;
                const int nr;
        } day_nr[] = {
                { "Sunday",    0 },
                { "Sun",       0 },
                { "Monday",    1 },
                { "Mon",       1 },
                { "Tuesday",   2 },
                { "Tue",       2 },
                { "Wednesday", 3 },
                { "Wed",       3 },
                { "Thursday",  4 },
                { "Thu",       4 },
                { "Friday",    5 },
                { "Fri",       5 },
                { "Saturday",  6 },
                { "Sat",       6 },
        };

        const char *k;
        const char *utc;
        struct tm tm, copy;
        time_t x;
        usec_t x_usec, plus = 0, minus = 0, ret;
        int r, weekday = -1;
        unsigned i;

        /*
         * Allowed syntaxes:
         *
         *   2012-09-22 16:34:22
         *   2012-09-22 16:34     (seconds will be set to 0)
         *   2012-09-22           (time will be set to 00:00:00)
         *   16:34:22             (date will be set to today)
         *   16:34                (date will be set to today, seconds to 0)
         *   now
         *   yesterday            (time is set to 00:00:00)
         *   today                (time is set to 00:00:00)
         *   tomorrow             (time is set to 00:00:00)
         *   +5min
         *   -5days
         *   @2147483647          (seconds since epoch)
         *
         */

        assert(t);
        assert(usec);

        if (t[0] == '@')
                return parse_sec(t + 1, usec);

        ret = now(CLOCK_REALTIME);

        if (streq(t, "now"))
                goto finish;

        else if (t[0] == '+') {
                r = parse_sec(t+1, &plus);
                if (r < 0)
                        return r;

                goto finish;

        } else if (t[0] == '-') {
                r = parse_sec(t+1, &minus);
                if (r < 0)
                        return r;

                goto finish;

        } else if ((k = endswith(t, " ago"))) {
                t = strndupa(t, k - t);

                r = parse_sec(t, &minus);
                if (r < 0)
                        return r;

                goto finish;

        } else if ((k = endswith(t, " left"))) {
                t = strndupa(t, k - t);

                r = parse_sec(t, &plus);
                if (r < 0)
                        return r;

                goto finish;
        }

        utc = endswith_no_case(t, " UTC");
        if (utc)
                t = strndupa(t, utc - t);

        x = ret / USEC_PER_SEC;
        x_usec = 0;

        assert_se(localtime_or_gmtime_r(&x, &tm, utc));
        tm.tm_isdst = -1;

        if (streq(t, "today")) {
                tm.tm_sec = tm.tm_min = tm.tm_hour = 0;
                goto from_tm;

        } else if (streq(t, "yesterday")) {
                tm.tm_mday --;
                tm.tm_sec = tm.tm_min = tm.tm_hour = 0;
                goto from_tm;

        } else if (streq(t, "tomorrow")) {
                tm.tm_mday ++;
                tm.tm_sec = tm.tm_min = tm.tm_hour = 0;
                goto from_tm;
        }


        for (i = 0; i < ELEMENTSOF(day_nr); i++) {
                size_t skip;

                if (!startswith_no_case(t, day_nr[i].name))
                        continue;

                skip = strlen(day_nr[i].name);
                if (t[skip] != ' ')
                        continue;

                weekday = day_nr[i].nr;
                t += skip + 1;
                break;
        }

        copy = tm;
        k = strptime(t, "%y-%m-%d %H:%M:%S", &tm);
        if (k) {
                if (*k == '.')
                        goto parse_usec;
                else if (*k == 0)
                        goto from_tm;
        }

        tm = copy;
        k = strptime(t, "%Y-%m-%d %H:%M:%S", &tm);
        if (k) {
                if (*k == '.')
                        goto parse_usec;
                else if (*k == 0)
                        goto from_tm;
        }

        tm = copy;
        k = strptime(t, "%y-%m-%d %H:%M", &tm);
        if (k && *k == 0) {
                tm.tm_sec = 0;
                goto from_tm;
        }

        tm = copy;
        k = strptime(t, "%Y-%m-%d %H:%M", &tm);
        if (k && *k == 0) {
                tm.tm_sec = 0;
                goto from_tm;
        }

        tm = copy;
        k = strptime(t, "%y-%m-%d", &tm);
        if (k && *k == 0) {
                tm.tm_sec = tm.tm_min = tm.tm_hour = 0;
                goto from_tm;
        }

        tm = copy;
        k = strptime(t, "%Y-%m-%d", &tm);
        if (k && *k == 0) {
                tm.tm_sec = tm.tm_min = tm.tm_hour = 0;
                goto from_tm;
        }

        tm = copy;
        k = strptime(t, "%H:%M:%S", &tm);
        if (k) {
                if (*k == '.')
                        goto parse_usec;
                else if (*k == 0)
                        goto from_tm;
        }

        tm = copy;
        k = strptime(t, "%H:%M", &tm);
        if (k && *k == 0) {
                tm.tm_sec = 0;
                goto from_tm;
        }

        return -EINVAL;

parse_usec:
        {
                unsigned add;

                k++;
                r = parse_fractional_part_u(&k, 6, &add);
                if (r < 0)
                        return -EINVAL;

                if (*k)
                        return -EINVAL;

                x_usec = add;

        }

from_tm:
        x = mktime_or_timegm(&tm, utc);
        if (x == (time_t) -1)
                return -EINVAL;

        if (weekday >= 0 && tm.tm_wday != weekday)
                return -EINVAL;

        ret = (usec_t) x * USEC_PER_SEC + x_usec;

finish:
        ret += plus;
        if (ret > minus)
                ret -= minus;
        else
                ret = 0;

        *usec = ret;

        return 0;
}
Пример #12
0
static int adm_control(struct udev *udev, int argc, char *argv[]) {
        _cleanup_udev_ctrl_unref_ struct udev_ctrl *uctrl = NULL;
        int timeout = 60;
        int rc = 1, c;

        static const struct option options[] = {
                { "exit",             no_argument,       NULL, 'e' },
                { "log-priority",     required_argument, NULL, 'l' },
                { "stop-exec-queue",  no_argument,       NULL, 's' },
                { "start-exec-queue", no_argument,       NULL, 'S' },
                { "reload",           no_argument,       NULL, 'R' },
                { "reload-rules",     no_argument,       NULL, 'R' }, /* alias for -R */
                { "property",         required_argument, NULL, 'p' },
                { "env",              required_argument, NULL, 'p' }, /* alias for -p */
                { "children-max",     required_argument, NULL, 'm' },
                { "timeout",          required_argument, NULL, 't' },
                { "version",          no_argument,       NULL, 'V' },
                { "help",             no_argument,       NULL, 'h' },
                {}
        };

        if (must_be_root() < 0)
                return 1;

        uctrl = udev_ctrl_new(udev);
        if (uctrl == NULL)
                return 2;

        while ((c = getopt_long(argc, argv, "el:sSRp:m:t:Vh", options, NULL)) >= 0)
                switch (c) {
                case 'e':
                        if (udev_ctrl_send_exit(uctrl, timeout) < 0)
                                rc = 2;
                        else
                                rc = 0;
                        break;
                case 'l': {
                        int i;

                        i = util_log_priority(optarg);
                        if (i < 0) {
                                log_error("invalid number '%s'", optarg);
                                return rc;
                        }
                        if (udev_ctrl_send_set_log_level(uctrl, util_log_priority(optarg), timeout) < 0)
                                rc = 2;
                        else
                                rc = 0;
                        break;
                }
                case 's':
                        if (udev_ctrl_send_stop_exec_queue(uctrl, timeout) < 0)
                                rc = 2;
                        else
                                rc = 0;
                        break;
                case 'S':
                        if (udev_ctrl_send_start_exec_queue(uctrl, timeout) < 0)
                                rc = 2;
                        else
                                rc = 0;
                        break;
                case 'R':
                        if (udev_ctrl_send_reload(uctrl, timeout) < 0)
                                rc = 2;
                        else
                                rc = 0;
                        break;
                case 'p':
                        if (strchr(optarg, '=') == NULL) {
                                log_error("expect <KEY>=<value> instead of '%s'", optarg);
                                return rc;
                        }
                        if (udev_ctrl_send_set_env(uctrl, optarg, timeout) < 0)
                                rc = 2;
                        else
                                rc = 0;
                        break;
                case 'm': {
                        char *endp;
                        int i;

                        i = strtoul(optarg, &endp, 0);
                        if (endp[0] != '\0' || i < 1) {
                                log_error("invalid number '%s'", optarg);
                                return rc;
                        }
                        if (udev_ctrl_send_set_children_max(uctrl, i, timeout) < 0)
                                rc = 2;
                        else
                                rc = 0;
                        break;
                }
                case 't': {
                        usec_t s;
                        int seconds;
                        int r;

                        r = parse_sec(optarg, &s);
                        if (r < 0)
                                return log_error_errno(r, "Failed to parse timeout value '%s'.", optarg);

                        if (((s + USEC_PER_SEC - 1) / USEC_PER_SEC) > INT_MAX)
                                log_error("Timeout value is out of range.");
                        else {
                                seconds = s != USEC_INFINITY ? (int) ((s + USEC_PER_SEC - 1) / USEC_PER_SEC) : INT_MAX;
                                timeout = seconds;
                                rc = 0;
                        }
                        break;
                }
                case 'V':
                        print_version();
                        rc = 0;
                        break;
                case 'h':
                        print_help();
                        rc = 0;
                        break;
                }

        if (optind < argc)
                log_error("Extraneous argument: %s", argv[optind]);
        else if (optind == 1)
                log_error("Option missing");
        return rc;
}
Пример #13
0
static int parse_argv(int argc, char *argv[]) {
        enum {
                ARG_LOG_LEVEL = 0x100,
                ARG_LOG_TARGET,
                ARG_LOG_COLOR,
                ARG_LOG_LOCATION,
                ARG_EXIT_CODE,
                ARG_TIMEOUT,
        };

        static const struct option options[] = {
                { "log-level",     required_argument, NULL, ARG_LOG_LEVEL    },
                { "log-target",    required_argument, NULL, ARG_LOG_TARGET   },
                { "log-color",     optional_argument, NULL, ARG_LOG_COLOR    },
                { "log-location",  optional_argument, NULL, ARG_LOG_LOCATION },
                { "exit-code",     required_argument, NULL, ARG_EXIT_CODE    },
                { "timeout",       required_argument, NULL, ARG_TIMEOUT      },
                {}
        };

        int c, r;

        assert(argc >= 1);
        assert(argv);

        /* "-" prevents getopt from permuting argv[] and moving the verb away
         * from argv[1]. Our interface to initrd promises it'll be there. */
        while ((c = getopt_long(argc, argv, "-", options, NULL)) >= 0)
                switch (c) {

                case ARG_LOG_LEVEL:
                        r = log_set_max_level_from_string(optarg);
                        if (r < 0)
                                log_error_errno(r, "Failed to parse log level %s, ignoring: %m", optarg);

                        break;

                case ARG_LOG_TARGET:
                        r = log_set_target_from_string(optarg);
                        if (r < 0)
                                log_error_errno(r, "Failed to parse log target %s, ignoring: %m", optarg);

                        break;

                case ARG_LOG_COLOR:

                        if (optarg) {
                                r = log_show_color_from_string(optarg);
                                if (r < 0)
                                        log_error_errno(r, "Failed to parse log color setting %s, ignoring: %m", optarg);
                        } else
                                log_show_color(true);

                        break;

                case ARG_LOG_LOCATION:
                        if (optarg) {
                                r = log_show_location_from_string(optarg);
                                if (r < 0)
                                        log_error_errno(r, "Failed to parse log location setting %s, ignoring: %m", optarg);
                        } else
                                log_show_location(true);

                        break;

                case ARG_EXIT_CODE:
                        r = safe_atou8(optarg, &arg_exit_code);
                        if (r < 0)
                                log_error_errno(r, "Failed to parse exit code %s, ignoring: %m", optarg);

                        break;

                case ARG_TIMEOUT:
                        r = parse_sec(optarg, &arg_timeout);
                        if (r < 0)
                                log_error_errno(r, "Failed to parse shutdown timeout %s, ignoring: %m", optarg);

                        break;

                case '\001':
                        if (!arg_verb)
                                arg_verb = optarg;
                        else
                                log_error("Excess arguments, ignoring");
                        break;

                case '?':
                        return -EINVAL;

                default:
                        assert_not_reached("Unhandled option code.");
                }

        if (!arg_verb)
                return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
                                       "Verb argument missing.");

        return 0;
}
Пример #14
0
int main(int argc, char *argv[]) {
        enum {
                MODE_BISECT,
                MODE_CHART,
        } mode = MODE_BISECT;
        int i;
        _cleanup_free_ char *bus_name = NULL, *address = NULL;
        _cleanup_close_ int bus_ref = -1;
        cpu_set_t cpuset;
        size_t result;
        sd_bus *b;
        pid_t pid;
        int r;

        log_set_max_level(LOG_DEBUG);

        for (i = 1; i < argc; i++) {
                if (streq(argv[i], "chart")) {
                        mode = MODE_CHART;
                        continue;
                }

                assert_se(parse_sec(argv[i], &arg_loop_usec) >= 0);
        }

        assert_se(arg_loop_usec > 0);

        bus_ref = bus_kernel_create("deine-mutter", &bus_name);
        if (bus_ref == -ENOENT)
                exit(EXIT_TEST_SKIP);

        assert_se(bus_ref >= 0);

        address = strappend("kernel:path=", bus_name);
        assert_se(address);

        r = sd_bus_new(&b);
        assert_se(r >= 0);

        r = sd_bus_set_address(b, address);
        assert_se(r >= 0);

        r = sd_bus_start(b);
        assert_se(r >= 0);

        sync();
        setpriority(PRIO_PROCESS, 0, -19);

        pid = fork();
        assert_se(pid >= 0);

        if (pid == 0) {
                CPU_ZERO(&cpuset);
                CPU_SET(0, &cpuset);
                pthread_setaffinity_np(pthread_self(), sizeof(cpu_set_t), &cpuset);

                close_nointr_nofail(bus_ref);
                sd_bus_unref(b);

                switch (mode) {
                case MODE_BISECT:
                        client_bisect(address);
                        break;

                case MODE_CHART:
                        client_chart(address);
                        break;
                }

                _exit(0);
        }

        CPU_ZERO(&cpuset);
        CPU_SET(1, &cpuset);
        pthread_setaffinity_np(pthread_self(), sizeof(cpu_set_t), &cpuset);

        server(b, &result);

        if (mode == MODE_BISECT)
                printf("Copying/memfd are equally fast at %zu bytes\n", result);

        assert_se(waitpid(pid, NULL, 0) == pid);

        sd_bus_unref(b);

        return 0;
}
Пример #15
0
static int parse_argv(int argc, char *argv[]) {

        enum {
                ARG_VERSION = 0x100,
                ARG_NO_PAGER,
                ARG_NO_TAIL,
                ARG_NEW_ID128,
                ARG_ROOT,
                ARG_HEADER,
                ARG_FULL,
                ARG_SETUP_KEYS,
                ARG_INTERVAL,
                ARG_VERIFY,
                ARG_VERIFY_KEY,
                ARG_DISK_USAGE,
                ARG_SINCE,
                ARG_UNTIL,
                ARG_USER_UNIT,
                ARG_LIST_CATALOG,
                ARG_DUMP_CATALOG,
                ARG_UPDATE_CATALOG
        };

        static const struct option options[] = {
                { "help",         no_argument,       NULL, 'h'              },
                { "version" ,     no_argument,       NULL, ARG_VERSION      },
                { "no-pager",     no_argument,       NULL, ARG_NO_PAGER     },
                { "pager-end",    no_argument,       NULL, 'e'              },
                { "follow",       no_argument,       NULL, 'f'              },
                { "output",       required_argument, NULL, 'o'              },
                { "all",          no_argument,       NULL, 'a'              },
                { "full",         no_argument,       NULL, ARG_FULL         },
                { "lines",        optional_argument, NULL, 'n'              },
                { "no-tail",      no_argument,       NULL, ARG_NO_TAIL      },
                { "new-id128",    no_argument,       NULL, ARG_NEW_ID128    },
                { "quiet",        no_argument,       NULL, 'q'              },
                { "merge",        no_argument,       NULL, 'm'              },
                { "this-boot",    no_argument,       NULL, 'b'              },
                { "directory",    required_argument, NULL, 'D'              },
                { "root",         required_argument, NULL, ARG_ROOT         },
                { "header",       no_argument,       NULL, ARG_HEADER       },
                { "priority",     required_argument, NULL, 'p'              },
                { "setup-keys",   no_argument,       NULL, ARG_SETUP_KEYS   },
                { "interval",     required_argument, NULL, ARG_INTERVAL     },
                { "verify",       no_argument,       NULL, ARG_VERIFY       },
                { "verify-key",   required_argument, NULL, ARG_VERIFY_KEY   },
                { "disk-usage",   no_argument,       NULL, ARG_DISK_USAGE   },
                { "cursor",       required_argument, NULL, 'c'              },
                { "since",        required_argument, NULL, ARG_SINCE        },
                { "until",        required_argument, NULL, ARG_UNTIL        },
                { "unit",         required_argument, NULL, 'u'              },
                { "user-unit",    required_argument, NULL, ARG_USER_UNIT    },
                { "field",        required_argument, NULL, 'F'              },
                { "catalog",      no_argument,       NULL, 'x'              },
                { "list-catalog", no_argument,       NULL, ARG_LIST_CATALOG },
                { "dump-catalog", no_argument,       NULL, ARG_DUMP_CATALOG },
                { "update-catalog",no_argument,      NULL, ARG_UPDATE_CATALOG },
                { "reverse",      no_argument,       NULL, 'r'              },
                { NULL,           0,                 NULL, 0                }
        };

        int c, r;

        assert(argc >= 0);
        assert(argv);

        while ((c = getopt_long(argc, argv, "hefo:an::qmbD:p:c:u:F:xr", options, NULL)) >= 0) {

                switch (c) {

                case 'h':
                        help();
                        return 0;

                case ARG_VERSION:
                        puts(PACKAGE_STRING);
                        puts(SYSTEMD_FEATURES);
                        return 0;

                case ARG_NO_PAGER:
                        arg_no_pager = true;
                        break;

                case 'e':
                        arg_pager_end = true;

                        if (arg_lines < 0)
                                arg_lines = 1000;

                        break;

                case 'f':
                        arg_follow = true;
                        break;

                case 'o':
                        arg_output = output_mode_from_string(optarg);
                        if (arg_output < 0) {
                                log_error("Unknown output format '%s'.", optarg);
                                return -EINVAL;
                        }

                        if (arg_output == OUTPUT_EXPORT ||
                            arg_output == OUTPUT_JSON ||
                            arg_output == OUTPUT_JSON_PRETTY ||
                            arg_output == OUTPUT_JSON_SSE ||
                            arg_output == OUTPUT_CAT)
                                arg_quiet = true;

                        break;

                case ARG_FULL:
                        arg_full = true;
                        break;

                case 'a':
                        arg_all = true;
                        break;

                case 'n':
                        if (optarg) {
                                r = safe_atoi(optarg, &arg_lines);
                                if (r < 0 || arg_lines < 0) {
                                        log_error("Failed to parse lines '%s'", optarg);
                                        return -EINVAL;
                                }
                        } else {
                                int n;

                                /* Hmm, no argument? Maybe the next
                                 * word on the command line is
                                 * supposed to be the argument? Let's
                                 * see if there is one, and is
                                 * parsable as a positive
                                 * integer... */

                                if (optind < argc &&
                                    safe_atoi(argv[optind], &n) >= 0 &&
                                    n >= 0) {

                                        arg_lines = n;
                                        optind++;
                                } else
                                        arg_lines = 10;
                        }

                        break;

                case ARG_NO_TAIL:
                        arg_no_tail = true;
                        break;

                case ARG_NEW_ID128:
                        arg_action = ACTION_NEW_ID128;
                        break;

                case 'q':
                        arg_quiet = true;
                        break;

                case 'm':
                        arg_merge = true;
                        break;

                case 'b':
                        arg_this_boot = true;
                        break;

                case 'D':
                        arg_directory = optarg;
                        break;

                case ARG_ROOT:
                        arg_root = optarg;
                        break;

                case 'c':
                        arg_cursor = optarg;
                        break;

                case ARG_HEADER:
                        arg_action = ACTION_PRINT_HEADER;
                        break;

                case ARG_VERIFY:
                        arg_action = ACTION_VERIFY;
                        break;

                case ARG_DISK_USAGE:
                        arg_action = ACTION_DISK_USAGE;
                        break;

#ifdef HAVE_GCRYPT
                case ARG_SETUP_KEYS:
                        arg_action = ACTION_SETUP_KEYS;
                        break;


                case ARG_VERIFY_KEY:
                        arg_action = ACTION_VERIFY;
                        arg_verify_key = optarg;
                        arg_merge = false;
                        break;

                case ARG_INTERVAL:
                        r = parse_sec(optarg, &arg_interval);
                        if (r < 0 || arg_interval <= 0) {
                                log_error("Failed to parse sealing key change interval: %s", optarg);
                                return -EINVAL;
                        }
                        break;
#else
                case ARG_SETUP_KEYS:
                case ARG_VERIFY_KEY:
                case ARG_INTERVAL:
                        log_error("Forward-secure sealing not available.");
                        return -ENOTSUP;
#endif

                case 'p': {
                        const char *dots;

                        dots = strstr(optarg, "..");
                        if (dots) {
                                char *a;
                                int from, to, i;

                                /* a range */
                                a = strndup(optarg, dots - optarg);
                                if (!a)
                                        return log_oom();

                                from = log_level_from_string(a);
                                to = log_level_from_string(dots + 2);
                                free(a);

                                if (from < 0 || to < 0) {
                                        log_error("Failed to parse log level range %s", optarg);
                                        return -EINVAL;
                                }

                                arg_priorities = 0;

                                if (from < to) {
                                        for (i = from; i <= to; i++)
                                                arg_priorities |= 1 << i;
                                } else {
                                        for (i = to; i <= from; i++)
                                                arg_priorities |= 1 << i;
                                }

                        } else {
                                int p, i;

                                p = log_level_from_string(optarg);
                                if (p < 0) {
                                        log_error("Unknown log level %s", optarg);
                                        return -EINVAL;
                                }

                                arg_priorities = 0;

                                for (i = 0; i <= p; i++)
                                        arg_priorities |= 1 << i;
                        }

                        break;
                }

                case ARG_SINCE:
                        r = parse_timestamp(optarg, &arg_since);
                        if (r < 0) {
                                log_error("Failed to parse timestamp: %s", optarg);
                                return -EINVAL;
                        }
                        arg_since_set = true;
                        break;

                case ARG_UNTIL:
                        r = parse_timestamp(optarg, &arg_until);
                        if (r < 0) {
                                log_error("Failed to parse timestamp: %s", optarg);
                                return -EINVAL;
                        }
                        arg_until_set = true;
                        break;

                case 'u':
                        r = strv_extend(&arg_system_units, optarg);
                        if (r < 0)
                                return log_oom();
                        break;

                case ARG_USER_UNIT:
                        r = strv_extend(&arg_user_units, optarg);
                        if (r < 0)
                                return log_oom();
                        break;

                case '?':
                        return -EINVAL;

                case 'F':
                        arg_field = optarg;
                        break;

                case 'x':
                        arg_catalog = true;
                        break;

                case ARG_LIST_CATALOG:
                        arg_action = ACTION_LIST_CATALOG;
                        break;

                case ARG_DUMP_CATALOG:
                        arg_action = ACTION_DUMP_CATALOG;
                        break;

                case ARG_UPDATE_CATALOG:
                        arg_action = ACTION_UPDATE_CATALOG;
                        break;

                case 'r':
                        arg_reverse = true;
                        break;

                default:
                        log_error("Unknown option code %c", c);
                        return -EINVAL;
                }
        }

        if (arg_follow && !arg_no_tail && arg_lines < 0)
                arg_lines = 10;

        if (arg_since_set && arg_until_set && arg_since > arg_until) {
                log_error("--since= must be before --until=.");
                return -EINVAL;
        }

        if (arg_cursor && arg_since_set) {
                log_error("Please specify either --since= or --cursor=, not both.");
                return -EINVAL;
        }

        if (arg_follow && arg_reverse) {
                log_error("Please specify either --reverse= or --follow=, not both.");
                return -EINVAL;
        }

        return 1;
}
Пример #16
0
static int parse_argv(int argc, char *argv[]) {

        enum {
                ARG_VERSION = 0x100,
                ARG_NO_ASK_PASSWORD,
                ARG_USER,
                ARG_SYSTEM,
                ARG_SCOPE,
                ARG_UNIT,
                ARG_DESCRIPTION,
                ARG_SLICE,
                ARG_SEND_SIGHUP,
                ARG_EXEC_USER,
                ARG_EXEC_GROUP,
                ARG_SERVICE_TYPE,
                ARG_NICE,
                ARG_SETENV,
                ARG_TTY,
                ARG_ON_ACTIVE,
                ARG_ON_BOOT,
                ARG_ON_STARTUP,
                ARG_ON_UNIT_ACTIVE,
                ARG_ON_UNIT_INACTIVE,
                ARG_ON_CALENDAR,
                ARG_TIMER_PROPERTY,
                ARG_NO_BLOCK,
        };

        static const struct option options[] = {
                { "help",              no_argument,       NULL, 'h'                  },
                { "version",           no_argument,       NULL, ARG_VERSION          },
                { "user",              no_argument,       NULL, ARG_USER             },
                { "system",            no_argument,       NULL, ARG_SYSTEM           },
                { "scope",             no_argument,       NULL, ARG_SCOPE            },
                { "unit",              required_argument, NULL, ARG_UNIT             },
                { "description",       required_argument, NULL, ARG_DESCRIPTION      },
                { "slice",             required_argument, NULL, ARG_SLICE            },
                { "remain-after-exit", no_argument,       NULL, 'r'                  },
                { "send-sighup",       no_argument,       NULL, ARG_SEND_SIGHUP      },
                { "host",              required_argument, NULL, 'H'                  },
                { "machine",           required_argument, NULL, 'M'                  },
                { "service-type",      required_argument, NULL, ARG_SERVICE_TYPE     },
                { "uid",               required_argument, NULL, ARG_EXEC_USER        },
                { "gid",               required_argument, NULL, ARG_EXEC_GROUP       },
                { "nice",              required_argument, NULL, ARG_NICE             },
                { "setenv",            required_argument, NULL, ARG_SETENV           },
                { "property",          required_argument, NULL, 'p'                  },
                { "tty",               no_argument,       NULL, 't'                  },
                { "quiet",             no_argument,       NULL, 'q'                  },
                { "on-active",         required_argument, NULL, ARG_ON_ACTIVE        },
                { "on-boot",           required_argument, NULL, ARG_ON_BOOT          },
                { "on-startup",        required_argument, NULL, ARG_ON_STARTUP       },
                { "on-unit-active",    required_argument, NULL, ARG_ON_UNIT_ACTIVE   },
                { "on-unit-inactive",  required_argument, NULL, ARG_ON_UNIT_INACTIVE },
                { "on-calendar",       required_argument, NULL, ARG_ON_CALENDAR      },
                { "timer-property",    required_argument, NULL, ARG_TIMER_PROPERTY   },
                { "no-block",          no_argument,       NULL, ARG_NO_BLOCK         },
                { "no-ask-password",   no_argument,       NULL, ARG_NO_ASK_PASSWORD },
                {},
        };

        int r, c;

        assert(argc >= 0);
        assert(argv);

        while ((c = getopt_long(argc, argv, "+hrH:M:p:tq", options, NULL)) >= 0)

                switch (c) {

                case 'h':
                        help();
                        return 0;

                case ARG_NO_ASK_PASSWORD:
                        arg_ask_password = false;
                        break;

                case ARG_VERSION:
                        return version();

                case ARG_USER:
                        arg_user = true;
                        break;

                case ARG_SYSTEM:
                        arg_user = false;
                        break;

                case ARG_SCOPE:
                        arg_scope = true;
                        break;

                case ARG_UNIT:
                        arg_unit = optarg;
                        break;

                case ARG_DESCRIPTION:
                        arg_description = optarg;
                        break;

                case ARG_SLICE:
                        arg_slice = optarg;
                        break;

                case ARG_SEND_SIGHUP:
                        arg_send_sighup = true;
                        break;

                case 'r':
                        arg_remain_after_exit = true;
                        break;

                case 'H':
                        arg_transport = BUS_TRANSPORT_REMOTE;
                        arg_host = optarg;
                        break;

                case 'M':
                        arg_transport = BUS_TRANSPORT_MACHINE;
                        arg_host = optarg;
                        break;

                case ARG_SERVICE_TYPE:
                        arg_service_type = optarg;
                        break;

                case ARG_EXEC_USER:
                        arg_exec_user = optarg;
                        break;

                case ARG_EXEC_GROUP:
                        arg_exec_group = optarg;
                        break;

                case ARG_NICE:
                        r = safe_atoi(optarg, &arg_nice);
                        if (r < 0 || arg_nice < PRIO_MIN || arg_nice >= PRIO_MAX) {
                                log_error("Failed to parse nice value");
                                return -EINVAL;
                        }

                        arg_nice_set = true;
                        break;

                case ARG_SETENV:
                        if (strv_extend(&arg_environment, optarg) < 0)
                                return log_oom();

                        break;

                case 'p':
                        if (strv_extend(&arg_property, optarg) < 0)
                                return log_oom();

                        break;

                case 't':
                        arg_pty = true;
                        break;

                case 'q':
                        arg_quiet = true;
                        break;

                case ARG_ON_ACTIVE:

                        r = parse_sec(optarg, &arg_on_active);
                        if (r < 0) {
                                log_error("Failed to parse timer value: %s", optarg);
                                return r;
                        }

                        break;

                case ARG_ON_BOOT:

                        r = parse_sec(optarg, &arg_on_boot);
                        if (r < 0) {
                                log_error("Failed to parse timer value: %s", optarg);
                                return r;
                        }

                        break;

                case ARG_ON_STARTUP:

                        r = parse_sec(optarg, &arg_on_startup);
                        if (r < 0) {
                                log_error("Failed to parse timer value: %s", optarg);
                                return r;
                        }

                        break;

                case ARG_ON_UNIT_ACTIVE:

                        r = parse_sec(optarg, &arg_on_unit_active);
                        if (r < 0) {
                                log_error("Failed to parse timer value: %s", optarg);
                                return r;
                        }

                        break;

                case ARG_ON_UNIT_INACTIVE:

                        r = parse_sec(optarg, &arg_on_unit_inactive);
                        if (r < 0) {
                                log_error("Failed to parse timer value: %s", optarg);
                                return r;
                        }

                        break;

                case ARG_ON_CALENDAR: {
                        CalendarSpec *spec = NULL;

                        r = calendar_spec_from_string(optarg, &spec);
                        if (r < 0) {
                                log_error("Invalid calendar spec: %s", optarg);
                                return r;
                        }

                        calendar_spec_free(spec);
                        arg_on_calendar = optarg;
                        break;
                }

                case ARG_TIMER_PROPERTY:

                        if (strv_extend(&arg_timer_property, optarg) < 0)
                                return log_oom();

                        break;

                case ARG_NO_BLOCK:
                        arg_no_block = true;
                        break;

                case '?':
                        return -EINVAL;

                default:
                        assert_not_reached("Unhandled option");
                }

        if ((optind >= argc) && (!arg_unit || !with_timer())) {
                log_error("Command line to execute required.");
                return -EINVAL;
        }

        if (arg_user && arg_transport != BUS_TRANSPORT_LOCAL) {
                log_error("Execution in user context is not supported on non-local systems.");
                return -EINVAL;
        }

        if (arg_scope && arg_transport != BUS_TRANSPORT_LOCAL) {
                log_error("Scope execution is not supported on non-local systems.");
                return -EINVAL;
        }

        if (arg_scope && (arg_remain_after_exit || arg_service_type)) {
                log_error("--remain-after-exit and --service-type= are not supported in --scope mode.");
                return -EINVAL;
        }

        if (arg_pty && (with_timer() || arg_scope)) {
                log_error("--pty is not compatible in timer or --scope mode.");
                return -EINVAL;
        }

        if (arg_pty && arg_transport == BUS_TRANSPORT_REMOTE) {
                log_error("--pty is only supported when connecting to the local system or containers.");
                return -EINVAL;
        }

        if (arg_scope && with_timer()) {
                log_error("Timer options are not supported in --scope mode.");
                return -EINVAL;
        }

        if (arg_timer_property && !with_timer()) {
                log_error("--timer-property= has no effect without any other timer options.");
                return -EINVAL;
        }

        return 1;
}
Пример #17
0
static int parse_argv(int argc, char *argv[]) {

        enum {
                ARG_VERSION = 0x100,
                ARG_DEPTH,
                ARG_CPU_TYPE
        };

        static const struct option options[] = {
                { "help",       no_argument,       NULL, 'h'         },
                { "version",    no_argument,       NULL, ARG_VERSION },
                { "delay",      required_argument, NULL, 'd'         },
                { "iterations", required_argument, NULL, 'n'         },
                { "batch",      no_argument,       NULL, 'b'         },
                { "depth",      required_argument, NULL, ARG_DEPTH   },
                { "cpu",        optional_argument, NULL, ARG_CPU_TYPE},
                {}
        };

        int c;
        int r;

        assert(argc >= 1);
        assert(argv);

        while ((c = getopt_long(argc, argv, "hptcmin:bd:", options, NULL)) >= 0)

                switch (c) {

                case 'h':
                        help();
                        return 0;

                case ARG_VERSION:
                        puts(PACKAGE_STRING);
                        puts(SYSTEMD_FEATURES);
                        return 0;

                case ARG_CPU_TYPE:
                        if (optarg) {
                                if (strcmp(optarg, "time") == 0)
                                        arg_cpu_type = CPU_TIME;
                                else if (strcmp(optarg, "percentage") == 0)
                                        arg_cpu_type = CPU_PERCENT;
                                else
                                        return -EINVAL;
                        }
                        break;

                case ARG_DEPTH:
                        r = safe_atou(optarg, &arg_depth);
                        if (r < 0) {
                                log_error("Failed to parse depth parameter.");
                                return -EINVAL;
                        }

                        break;

                case 'd':
                        r = parse_sec(optarg, &arg_delay);
                        if (r < 0 || arg_delay <= 0) {
                                log_error("Failed to parse delay parameter.");
                                return -EINVAL;
                        }

                        break;

                case 'n':
                        r = safe_atou(optarg, &arg_iterations);
                        if (r < 0) {
                                log_error("Failed to parse iterations parameter.");
                                return -EINVAL;
                        }

                        break;

                case 'b':
                        arg_batch = true;
                        break;

                case 'p':
                        arg_order = ORDER_PATH;
                        break;

                case 't':
                        arg_order = ORDER_TASKS;
                        break;

                case 'c':
                        arg_order = ORDER_CPU;
                        break;

                case 'm':
                        arg_order = ORDER_MEMORY;
                        break;

                case 'i':
                        arg_order = ORDER_IO;
                        break;

                case '?':
                        return -EINVAL;

                default:
                        assert_not_reached("Unhandled option");
                }

        if (optind < argc) {
                log_error("Too many arguments.");
                return -EINVAL;
        }

        return 1;
}
Пример #18
0
int nfs4mount(const char *spec, const char *node, int flags,
	      char **extra_opts, int fake, int running_bg)
{
	static struct nfs4_mount_data data;
	static char hostdir[1024];
	static char ip_addr[16] = "127.0.0.1";
	static struct sockaddr_in server_addr, client_addr;
	static int pseudoflavour[MAX_USER_FLAVOUR];
	int num_flavour = 0;
	int ip_addr_in_opts = 0;

	char *hostname, *dirname, *old_opts;
	char new_opts[1024];
	char *opt, *opteq;
	char *s;
	int val;
	int bg, soft, intr;
	int nocto, noac, unshared;
	int retry;
	int retval = EX_FAIL;
	time_t timeout, t;

	if (strlen(spec) >= sizeof(hostdir)) {
		nfs_error(_("%s: excessively long host:dir argument\n"),
				progname);
		goto fail;
	}
	strcpy(hostdir, spec);
	if (parse_devname(hostdir, &hostname, &dirname))
		goto fail;

	if (fill_ipv4_sockaddr(hostname, &server_addr))
		goto fail;
	if (get_my_ipv4addr(ip_addr, sizeof(ip_addr)))
		goto fail;

	/* add IP address to mtab options for use when unmounting */
	s = inet_ntoa(server_addr.sin_addr);
	old_opts = *extra_opts;
	if (!old_opts)
		old_opts = "";
	if (strlen(old_opts) + strlen(s) + 10 >= sizeof(new_opts)) {
		nfs_error(_("%s: excessively long option argument\n"),
				progname);
		goto fail;
	}
	snprintf(new_opts, sizeof(new_opts), "%s%saddr=%s",
		 old_opts, *old_opts ? "," : "", s);
	*extra_opts = xstrdup(new_opts);

	/* Set default options.
	 * rsize/wsize and timeo are left 0 in order to
	 * let the kernel decide.
	 */
	memset(&data, 0, sizeof(data));
	data.retrans	= 3;
	data.acregmin	= 3;
	data.acregmax	= 60;
	data.acdirmin	= 30;
	data.acdirmax	= 60;
	data.proto	= IPPROTO_TCP;

	bg = 0;
	soft = 0;
	intr = NFS4_MOUNT_INTR;
	nocto = 0;
	noac = 0;
	unshared = 0;
	retry = -1;

	/*
	 * NFSv4 specifies that the default port should be 2049
	 */
	server_addr.sin_port = htons(NFS_PORT);

	/* parse options */

	for (opt = strtok(old_opts, ","); opt; opt = strtok(NULL, ",")) {
		if ((opteq = strchr(opt, '='))) {
			val = atoi(opteq + 1);	
			*opteq = '\0';
			if (!strcmp(opt, "rsize"))
				data.rsize = val;
			else if (!strcmp(opt, "wsize"))
				data.wsize = val;
			else if (!strcmp(opt, "timeo"))
				data.timeo = val;
			else if (!strcmp(opt, "retrans"))
				data.retrans = val;
			else if (!strcmp(opt, "acregmin"))
				data.acregmin = val;
			else if (!strcmp(opt, "acregmax"))
				data.acregmax = val;
			else if (!strcmp(opt, "acdirmin"))
				data.acdirmin = val;
			else if (!strcmp(opt, "acdirmax"))
				data.acdirmax = val;
			else if (!strcmp(opt, "actimeo")) {
				data.acregmin = val;
				data.acregmax = val;
				data.acdirmin = val;
				data.acdirmax = val;
			}
			else if (!strcmp(opt, "retry"))
				retry = val;
			else if (!strcmp(opt, "port"))
				server_addr.sin_port = htons(val);
			else if (!strcmp(opt, "proto")) {
				if (!strncmp(opteq+1, "tcp", 3))
					data.proto = IPPROTO_TCP;
				else if (!strncmp(opteq+1, "udp", 3))
					data.proto = IPPROTO_UDP;
				else
					printf(_("Warning: Unrecognized proto= option.\n"));
			} else if (!strcmp(opt, "clientaddr")) {
				if (strlen(opteq+1) >= sizeof(ip_addr))
					printf(_("Invalid client address %s"),
								opteq+1);
				strncpy(ip_addr,opteq+1, sizeof(ip_addr));
				ip_addr[sizeof(ip_addr)-1] = '\0';
				ip_addr_in_opts = 1;
			} else if (!strcmp(opt, "sec")) {
				num_flavour = parse_sec(opteq+1, pseudoflavour);
				if (!num_flavour)
					goto fail;
			} else if (!strcmp(opt, "addr") || sloppy) {
				/* ignore */;
			} else {
				printf(_("unknown nfs mount parameter: "
					 "%s=%d\n"), opt, val);
				goto fail;
			}
		} else {
			val = 1;
			if (!strncmp(opt, "no", 2)) {
				val = 0;
				opt += 2;
			}
			if (!strcmp(opt, "bg"))
				bg = val;
			else if (!strcmp(opt, "fg"))
				bg = !val;
			else if (!strcmp(opt, "soft"))
				soft = val;
			else if (!strcmp(opt, "hard"))
				soft = !val;
			else if (!strcmp(opt, "intr"))
				intr = val;
			else if (!strcmp(opt, "cto"))
				nocto = !val;
			else if (!strcmp(opt, "ac"))
				noac = !val;
			else if (!strcmp(opt, "sharecache"))
				unshared = !val;
			else if (!sloppy) {
				printf(_("unknown nfs mount option: %s%s\n"),
						val ? "" : "no", opt);
				goto fail;
			}
		}
	}

	/* if retry is still -1, then it wasn't set via an option */
	if (retry == -1) {
		if (bg)
			retry = 10000;	/* 10000 mins == ~1 week */
		else
			retry = 2;	/* 2 min default on fg mounts */
	}

	data.flags = (soft ? NFS4_MOUNT_SOFT : 0)
		| (intr ? NFS4_MOUNT_INTR : 0)
		| (nocto ? NFS4_MOUNT_NOCTO : 0)
		| (noac ? NFS4_MOUNT_NOAC : 0)
		| (unshared ? NFS4_MOUNT_UNSHARED : 0);

	/*
	 * Give a warning if the rpc.idmapd daemon is not running
	 */
#if 0
	/* We shouldn't have these checks as nothing in this package
	 * creates the files that are checked
	 */
	idmapd_check();

	if (num_flavour == 0)
		pseudoflavour[num_flavour++] = AUTH_UNIX;
	else {
		/*
		 * ditto with rpc.gssd daemon
		 */
		gssd_check();
	}
#endif
	data.auth_flavourlen = num_flavour;
	data.auth_flavours = pseudoflavour;

	data.client_addr.data = ip_addr;
	data.client_addr.len = strlen(ip_addr);

	data.mnt_path.data = dirname;
	data.mnt_path.len = strlen(dirname);

	data.hostname.data = hostname;
	data.hostname.len = strlen(hostname);
	data.host_addr = (struct sockaddr *)&server_addr;
	data.host_addrlen = sizeof(server_addr);

#ifdef NFS_MOUNT_DEBUG
	printf(_("rsize = %d, wsize = %d, timeo = %d, retrans = %d\n"),
	       data.rsize, data.wsize, data.timeo, data.retrans);
	printf(_("acreg (min, max) = (%d, %d), acdir (min, max) = (%d, %d)\n"),
	       data.acregmin, data.acregmax, data.acdirmin, data.acdirmax);
	printf(_("port = %d, bg = %d, retry = %d, flags = %.8x\n"),
	       ntohs(server_addr.sin_port), bg, retry, data.flags);
	printf(_("soft = %d, intr = %d, nocto = %d, noac = %d, "
	       "nosharecache = %d\n"),
	       (data.flags & NFS4_MOUNT_SOFT) != 0,
	       (data.flags & NFS4_MOUNT_INTR) != 0,
	       (data.flags & NFS4_MOUNT_NOCTO) != 0,
	       (data.flags & NFS4_MOUNT_NOAC) != 0,
	       (data.flags & NFS4_MOUNT_UNSHARED) != 0);

	if (num_flavour > 0) {
		int pf_cnt, i;

		printf(_("sec = "));
		for (pf_cnt = 0; pf_cnt < num_flavour; pf_cnt++) {
			for (i = 0; i < flav_map_size; i++) {
				if (flav_map[i].fnum == pseudoflavour[pf_cnt]) {
					printf("%s", flav_map[i].flavour);
					break;
				}
			}
			printf("%s", (pf_cnt < num_flavour-1) ? ":" : "\n");
		}
	}
	printf(_("proto = %s\n"), (data.proto == IPPROTO_TCP) ? _("tcp") : _("udp"));
#endif

	timeout = time(NULL) + 60 * retry;
	data.version = NFS4_MOUNT_VERSION;
	for (;;) {
		if (verbose) {
			printf(_("%s: pinging: prog %d vers %d prot %s port %d\n"),
				progname, NFS_PROGRAM, 4,
				data.proto == IPPROTO_UDP ? "udp" : "tcp",
				ntohs(server_addr.sin_port));
		}
		client_addr.sin_family = 0;
		client_addr.sin_addr.s_addr = 0;
		clnt_ping(&server_addr, NFS_PROGRAM, 4, data.proto, &client_addr);
		if (rpc_createerr.cf_stat == RPC_SUCCESS) {
			if (!ip_addr_in_opts &&
			    client_addr.sin_family != 0 &&
			    client_addr.sin_addr.s_addr != 0) {
				snprintf(ip_addr, sizeof(ip_addr), "%s",
					 inet_ntoa(client_addr.sin_addr));
				data.client_addr.len = strlen(ip_addr);
			}
			break;
		}

		switch(rpc_createerr.cf_stat){
		case RPC_TIMEDOUT:
			break;
		case RPC_SYSTEMERROR:
			if (errno == ETIMEDOUT)
				break;
		default:
			rpc_mount_errors(hostname, 0, bg);
			goto fail;
		}

		if (bg && !running_bg) {
			if (retry > 0)
				retval = EX_BG;
			goto fail;
		}

		t = time(NULL);
		if (t >= timeout) {
			rpc_mount_errors(hostname, 0, bg);
			goto fail;
		}
		rpc_mount_errors(hostname, 1, bg);
		continue;
	}

	if (!fake) {
		if (mount(spec, node, "nfs4",
				flags & ~(MS_USER|MS_USERS), &data)) {
			mount_error(spec, node, errno);
			goto fail;
		}
	}

	return EX_SUCCESS;

fail:
	return retval;
}
Пример #19
0
int parse_timestamp(const char *t, usec_t *usec)
{
	 static const struct {
		const char *name;
		const int nr;
	 } day_nr[] = {
		{ "Sunday",	0 },
		{ "Sun",	0 },
		{ "Monday",	1 },
		{ "Mon",	1 },
		{ "Tuesday",	2 },
		{ "Tue",	2 },
		{ "Wednesday",	3 },
		{ "Wed",	3 },
		{ "Thursday",	4 },
		{ "Thu",	4 },
		{ "Friday",	5 },
		{ "Fri",	5 },
		{ "Saturday",	6 },
		{ "Sat",	6 },
	 };

	const char *k;
	struct tm tm, copy;
	time_t x;
	usec_t plus = 0, minus = 0, ret;
	int r, weekday = -1;
	unsigned i;

	/*
	 * Allowed syntaxes:
	 *
	 *   2012-09-22 16:34:22
	 *   2012-09-22 16:34	  (seconds will be set to 0)
	 *   2012-09-22		  (time will be set to 00:00:00)
	 *   16:34:22		  (date will be set to today)
	 *   16:34		  (date will be set to today, seconds to 0)
	 *   now
	 *   yesterday		  (time is set to 00:00:00)
	 *   today		  (time is set to 00:00:00)
	 *   tomorrow		  (time is set to 00:00:00)
	 *   +5min
	 *   -5days
	 *
	 */

	assert(t);
	assert(usec);

	x = time(NULL);
	localtime_r(&x, &tm);
	tm.tm_isdst = -1;

	if (streq(t, "now"))
		goto finish;

	else if (streq(t, "today")) {
		tm.tm_sec = tm.tm_min = tm.tm_hour = 0;
		goto finish;

	} else if (streq(t, "yesterday")) {
		tm.tm_mday--;
		tm.tm_sec = tm.tm_min = tm.tm_hour = 0;
		goto finish;

	} else if (streq(t, "tomorrow")) {
		tm.tm_mday++;
		tm.tm_sec = tm.tm_min = tm.tm_hour = 0;
		goto finish;

	} else if (t[0] == '+') {

		r = parse_sec(t + 1, &plus);
		if (r < 0)
			return r;

		goto finish;
	} else if (t[0] == '-') {

		r = parse_sec(t + 1, &minus);
		if (r < 0)
			return r;

		goto finish;

	} else if (endswith(t, " ago")) {
		char *z;

		z = strndup(t, strlen(t) - 4);
		if (!z)
			return -ENOMEM;

		r = parse_sec(z, &minus);
		if (r < 0)
			return r;

		goto finish;
	}

	for (i = 0; i < ARRAY_SIZE(day_nr); i++) {
		size_t skip;

		if (!startswith_no_case(t, day_nr[i].name))
			continue;

		skip = strlen(day_nr[i].name);
		if (t[skip] != ' ')
			continue;

		weekday = day_nr[i].nr;
		t += skip + 1;
		break;
	}

	copy = tm;
	k = strptime(t, "%y-%m-%d %H:%M:%S", &tm);
	if (k && *k == 0)
		goto finish;

	tm = copy;
	k = strptime(t, "%Y-%m-%d %H:%M:%S", &tm);
	if (k && *k == 0)
		goto finish;

	tm = copy;
	k = strptime(t, "%y-%m-%d %H:%M", &tm);
	if (k && *k == 0) {
		tm.tm_sec = 0;
		goto finish;
	}

	tm = copy;
	k = strptime(t, "%Y-%m-%d %H:%M", &tm);
	if (k && *k == 0) {
		tm.tm_sec = 0;
		goto finish;
	}

	tm = copy;
	k = strptime(t, "%y-%m-%d", &tm);
	if (k && *k == 0) {
		tm.tm_sec = tm.tm_min = tm.tm_hour = 0;
		goto finish;
	}

	tm = copy;
	k = strptime(t, "%Y-%m-%d", &tm);
	if (k && *k == 0) {
		tm.tm_sec = tm.tm_min = tm.tm_hour = 0;
		goto finish;
	}

	tm = copy;
	k = strptime(t, "%H:%M:%S", &tm);
	if (k && *k == 0)
		goto finish;

	tm = copy;
	k = strptime(t, "%H:%M", &tm);
	if (k && *k == 0) {
		tm.tm_sec = 0;
		goto finish;
	}

	tm = copy;
	k = strptime(t, "%Y%m%d%H%M%S", &tm);
	if (k && *k == 0) {
		tm.tm_sec = 0;
		goto finish;
	}

	return -EINVAL;

 finish:
	x = mktime(&tm);
	if (x == (time_t)-1)
		return -EINVAL;

	if (weekday >= 0 && tm.tm_wday != weekday)
		return -EINVAL;

	ret = (usec_t) x *USEC_PER_SEC;

	ret += plus;
	if (ret > minus)
		ret -= minus;
	else
		ret = 0;

	*usec = ret;

	return 0;
}
Пример #20
0
static void test_parse_sec(void) {
        usec_t u;

        log_info("/* %s */", __func__);

        assert_se(parse_sec("5s", &u) >= 0);
        assert_se(u == 5 * USEC_PER_SEC);
        assert_se(parse_sec("5s500ms", &u) >= 0);
        assert_se(u == 5 * USEC_PER_SEC + 500 * USEC_PER_MSEC);
        assert_se(parse_sec(" 5s 500ms  ", &u) >= 0);
        assert_se(u == 5 * USEC_PER_SEC + 500 * USEC_PER_MSEC);
        assert_se(parse_sec(" 5.5s  ", &u) >= 0);
        assert_se(u == 5 * USEC_PER_SEC + 500 * USEC_PER_MSEC);
        assert_se(parse_sec(" 5.5s 0.5ms ", &u) >= 0);
        assert_se(u == 5 * USEC_PER_SEC + 500 * USEC_PER_MSEC + 500);
        assert_se(parse_sec(" .22s ", &u) >= 0);
        assert_se(u == 220 * USEC_PER_MSEC);
        assert_se(parse_sec(" .50y ", &u) >= 0);
        assert_se(u == USEC_PER_YEAR / 2);
        assert_se(parse_sec("2.5", &u) >= 0);
        assert_se(u == 2500 * USEC_PER_MSEC);
        assert_se(parse_sec(".7", &u) >= 0);
        assert_se(u == 700 * USEC_PER_MSEC);
        assert_se(parse_sec("23us", &u) >= 0);
        assert_se(u == 23);
        assert_se(parse_sec("23µs", &u) >= 0);
        assert_se(u == 23);
        assert_se(parse_sec("infinity", &u) >= 0);
        assert_se(u == USEC_INFINITY);
        assert_se(parse_sec(" infinity ", &u) >= 0);
        assert_se(u == USEC_INFINITY);

        assert_se(parse_sec(" xyz ", &u) < 0);
        assert_se(parse_sec("", &u) < 0);
        assert_se(parse_sec(" . ", &u) < 0);
        assert_se(parse_sec(" 5. ", &u) < 0);
        assert_se(parse_sec(".s ", &u) < 0);
        assert_se(parse_sec(" infinity .7", &u) < 0);
        assert_se(parse_sec(".3 infinity", &u) < 0);
}
Пример #21
0
static int parse_argv(int argc, char *argv[]) {

        enum {
                ARG_VERSION = 0x100,
                ARG_DEPTH,
                ARG_CPU_TYPE,
                ARG_ORDER,
                ARG_RECURSIVE,
        };

        static const struct option options[] = {
                { "help",         no_argument,       NULL, 'h'           },
                { "version",      no_argument,       NULL, ARG_VERSION   },
                { "delay",        required_argument, NULL, 'd'           },
                { "iterations",   required_argument, NULL, 'n'           },
                { "batch",        no_argument,       NULL, 'b'           },
                { "raw",          no_argument,       NULL, 'r'           },
                { "depth",        required_argument, NULL, ARG_DEPTH     },
                { "cpu",          optional_argument, NULL, ARG_CPU_TYPE  },
                { "order",        required_argument, NULL, ARG_ORDER     },
                { "recursive",    required_argument, NULL, ARG_RECURSIVE },
                { "machine",      required_argument, NULL, 'M'           },
                {}
        };

        bool recursive_unset = false;
        int c, r;

        assert(argc >= 1);
        assert(argv);

        while ((c = getopt_long(argc, argv, "hptcmin:brd:kPM:", options, NULL)) >= 0)

                switch (c) {

                case 'h':
                        help();
                        return 0;

                case ARG_VERSION:
                        return version();

                case ARG_CPU_TYPE:
                        if (optarg) {
                                if (streq(optarg, "time"))
                                        arg_cpu_type = CPU_TIME;
                                else if (streq(optarg, "percentage"))
                                        arg_cpu_type = CPU_PERCENT;
                                else {
                                        log_error("Unknown argument to --cpu=: %s", optarg);
                                        return -EINVAL;
                                }
                        } else
                                arg_cpu_type = CPU_TIME;

                        break;

                case ARG_DEPTH:
                        r = safe_atou(optarg, &arg_depth);
                        if (r < 0) {
                                log_error("Failed to parse depth parameter.");
                                return -EINVAL;
                        }

                        break;

                case 'd':
                        r = parse_sec(optarg, &arg_delay);
                        if (r < 0 || arg_delay <= 0) {
                                log_error("Failed to parse delay parameter.");
                                return -EINVAL;
                        }

                        break;

                case 'n':
                        r = safe_atou(optarg, &arg_iterations);
                        if (r < 0) {
                                log_error("Failed to parse iterations parameter.");
                                return -EINVAL;
                        }

                        break;

                case 'b':
                        arg_batch = true;
                        break;

                case 'r':
                        arg_raw = true;
                        break;

                case 'p':
                        arg_order = ORDER_PATH;
                        break;

                case 't':
                        arg_order = ORDER_TASKS;
                        break;

                case 'c':
                        arg_order = ORDER_CPU;
                        break;

                case 'm':
                        arg_order = ORDER_MEMORY;
                        break;

                case 'i':
                        arg_order = ORDER_IO;
                        break;

                case ARG_ORDER:
                        if (streq(optarg, "path"))
                                arg_order = ORDER_PATH;
                        else if (streq(optarg, "tasks"))
                                arg_order = ORDER_TASKS;
                        else if (streq(optarg, "cpu"))
                                arg_order = ORDER_CPU;
                        else if (streq(optarg, "memory"))
                                arg_order = ORDER_MEMORY;
                        else if (streq(optarg, "io"))
                                arg_order = ORDER_IO;
                        else {
                                log_error("Invalid argument to --order=: %s", optarg);
                                return -EINVAL;
                        }
                        break;

                case 'k':
                        arg_count = COUNT_ALL_PROCESSES;
                        break;

                case 'P':
                        arg_count = COUNT_USERSPACE_PROCESSES;
                        break;

                case ARG_RECURSIVE:
                        r = parse_boolean(optarg);
                        if (r < 0) {
                                log_error("Failed to parse --recursive= argument: %s", optarg);
                                return r;
                        }

                        arg_recursive = r;
                        recursive_unset = r == 0;
                        break;

                case 'M':
                        arg_machine = optarg;
                        break;

                case '?':
                        return -EINVAL;

                default:
                        assert_not_reached("Unhandled option");
                }

        if (optind == argc-1) {
                if (arg_machine) {
                        log_error("Specifying a control group path together with the -M option is not allowed");
                        return -EINVAL;
                }
                arg_root = argv[optind];
        } else if (optind < argc) {
                log_error("Too many arguments.");
                return -EINVAL;
        }

        if (recursive_unset && arg_count == COUNT_PIDS) {
                log_error("Non-recursive counting is only supported when counting processes, not tasks. Use -P or -k.");
                return -EINVAL;
        }

        return 1;
}
Пример #22
0
int parse_timestamp(const char *t, usec_t *usec) {
        static const struct {
                const char *name;
                const int nr;
        } day_nr[] = {
                { "Sunday",    0 },
                { "Sun",       0 },
                { "Monday",    1 },
                { "Mon",       1 },
                { "Tuesday",   2 },
                { "Tue",       2 },
                { "Wednesday", 3 },
                { "Wed",       3 },
                { "Thursday",  4 },
                { "Thu",       4 },
                { "Friday",    5 },
                { "Fri",       5 },
                { "Saturday",  6 },
                { "Sat",       6 },
        };

        const char *k, *utc, *tzn = NULL;
        struct tm tm, copy;
        time_t x;
        usec_t x_usec, plus = 0, minus = 0, ret;
        int r, weekday = -1, dst = -1;
        unsigned i;

        /*
         * Allowed syntaxes:
         *
         *   2012-09-22 16:34:22
         *   2012-09-22 16:34     (seconds will be set to 0)
         *   2012-09-22           (time will be set to 00:00:00)
         *   16:34:22             (date will be set to today)
         *   16:34                (date will be set to today, seconds to 0)
         *   now
         *   yesterday            (time is set to 00:00:00)
         *   today                (time is set to 00:00:00)
         *   tomorrow             (time is set to 00:00:00)
         *   +5min
         *   -5days
         *   @2147483647          (seconds since epoch)
         *
         */

        assert(t);
        assert(usec);

        if (t[0] == '@')
                return parse_sec(t + 1, usec);

        ret = now(CLOCK_REALTIME);

        if (streq(t, "now"))
                goto finish;

        else if (t[0] == '+') {
                r = parse_sec(t+1, &plus);
                if (r < 0)
                        return r;

                goto finish;

        } else if (t[0] == '-') {
                r = parse_sec(t+1, &minus);
                if (r < 0)
                        return r;

                goto finish;

        } else if ((k = endswith(t, " ago"))) {
                t = strndupa(t, k - t);

                r = parse_sec(t, &minus);
                if (r < 0)
                        return r;

                goto finish;

        } else if ((k = endswith(t, " left"))) {
                t = strndupa(t, k - t);

                r = parse_sec(t, &plus);
                if (r < 0)
                        return r;

                goto finish;
        }

        /* See if the timestamp is suffixed with UTC */
        utc = endswith_no_case(t, " UTC");
        if (utc)
                t = strndupa(t, utc - t);
        else {
                const char *e = NULL;
                int j;

                tzset();

                /* See if the timestamp is suffixed by either the DST or non-DST local timezone. Note that we only
                 * support the local timezones here, nothing else. Not because we wouldn't want to, but simply because
                 * there are no nice APIs available to cover this. By accepting the local time zone strings, we make
                 * sure that all timestamps written by format_timestamp() can be parsed correctly, even though we don't
                 * support arbitrary timezone specifications.  */

                for (j = 0; j <= 1; j++) {

                        if (isempty(tzname[j]))
                                continue;

                        e = endswith_no_case(t, tzname[j]);
                        if (!e)
                                continue;
                        if (e == t)
                                continue;
                        if (e[-1] != ' ')
                                continue;

                        break;
                }

                if (IN_SET(j, 0, 1)) {
                        /* Found one of the two timezones specified. */
                        t = strndupa(t, e - t - 1);
                        dst = j;
                        tzn = tzname[j];
                }
        }

        x = (time_t) (ret / USEC_PER_SEC);
        x_usec = 0;

        if (!localtime_or_gmtime_r(&x, &tm, utc))
                return -EINVAL;

        tm.tm_isdst = dst;
        if (tzn)
                tm.tm_zone = tzn;

        if (streq(t, "today")) {
                tm.tm_sec = tm.tm_min = tm.tm_hour = 0;
                goto from_tm;

        } else if (streq(t, "yesterday")) {
                tm.tm_mday--;
                tm.tm_sec = tm.tm_min = tm.tm_hour = 0;
                goto from_tm;

        } else if (streq(t, "tomorrow")) {
                tm.tm_mday++;
                tm.tm_sec = tm.tm_min = tm.tm_hour = 0;
                goto from_tm;
        }

        for (i = 0; i < ELEMENTSOF(day_nr); i++) {
                size_t skip;

                if (!startswith_no_case(t, day_nr[i].name))
                        continue;

                skip = strlen(day_nr[i].name);
                if (t[skip] != ' ')
                        continue;

                weekday = day_nr[i].nr;
                t += skip + 1;
                break;
        }

        copy = tm;
        k = strptime(t, "%y-%m-%d %H:%M:%S", &tm);
        if (k) {
                if (*k == '.')
                        goto parse_usec;
                else if (*k == 0)
                        goto from_tm;
        }

        tm = copy;
        k = strptime(t, "%Y-%m-%d %H:%M:%S", &tm);
        if (k) {
                if (*k == '.')
                        goto parse_usec;
                else if (*k == 0)
                        goto from_tm;
        }

        tm = copy;
        k = strptime(t, "%y-%m-%d %H:%M", &tm);
        if (k && *k == 0) {
                tm.tm_sec = 0;
                goto from_tm;
        }

        tm = copy;
        k = strptime(t, "%Y-%m-%d %H:%M", &tm);
        if (k && *k == 0) {
                tm.tm_sec = 0;
                goto from_tm;
        }

        tm = copy;
        k = strptime(t, "%y-%m-%d", &tm);
        if (k && *k == 0) {
                tm.tm_sec = tm.tm_min = tm.tm_hour = 0;
                goto from_tm;
        }

        tm = copy;
        k = strptime(t, "%Y-%m-%d", &tm);
        if (k && *k == 0) {
                tm.tm_sec = tm.tm_min = tm.tm_hour = 0;
                goto from_tm;
        }

        tm = copy;
        k = strptime(t, "%H:%M:%S", &tm);
        if (k) {
                if (*k == '.')
                        goto parse_usec;
                else if (*k == 0)
                        goto from_tm;
        }

        tm = copy;
        k = strptime(t, "%H:%M", &tm);
        if (k && *k == 0) {
                tm.tm_sec = 0;
                goto from_tm;
        }

        return -EINVAL;

parse_usec:
        {
                unsigned add;

                k++;
                r = parse_fractional_part_u(&k, 6, &add);
                if (r < 0)
                        return -EINVAL;

                if (*k)
                        return -EINVAL;

                x_usec = add;
        }

from_tm:
        x = mktime_or_timegm(&tm, utc);
        if (x == (time_t) -1)
                return -EINVAL;

        if (weekday >= 0 && tm.tm_wday != weekday)
                return -EINVAL;

        ret = (usec_t) x * USEC_PER_SEC + x_usec;

finish:
        ret += plus;
        if (ret > minus)
                ret -= minus;
        else
                ret = 0;

        *usec = ret;

        return 0;
}