Пример #1
0
static void test_parse_nice(void) {
        int n;

        assert_se(parse_nice("0", &n) >= 0 && n == 0);
        assert_se(parse_nice("+0", &n) >= 0 && n == 0);
        assert_se(parse_nice("-1", &n) >= 0 && n == -1);
        assert_se(parse_nice("-2", &n) >= 0 && n == -2);
        assert_se(parse_nice("1", &n) >= 0 && n == 1);
        assert_se(parse_nice("2", &n) >= 0 && n == 2);
        assert_se(parse_nice("+1", &n) >= 0 && n == 1);
        assert_se(parse_nice("+2", &n) >= 0 && n == 2);
        assert_se(parse_nice("-20", &n) >= 0 && n == -20);
        assert_se(parse_nice("19", &n) >= 0 && n == 19);
        assert_se(parse_nice("+19", &n) >= 0 && n == 19);


        assert_se(parse_nice("", &n) == -EINVAL);
        assert_se(parse_nice("-", &n) == -EINVAL);
        assert_se(parse_nice("+", &n) == -EINVAL);
        assert_se(parse_nice("xx", &n) == -EINVAL);
        assert_se(parse_nice("-50", &n) == -ERANGE);
        assert_se(parse_nice("50", &n) == -ERANGE);
        assert_se(parse_nice("+50", &n) == -ERANGE);
        assert_se(parse_nice("-21", &n) == -ERANGE);
        assert_se(parse_nice("20", &n) == -ERANGE);
        assert_se(parse_nice("+20", &n) == -ERANGE);
}
Пример #2
0
static int parse_argv(int argc, char *argv[]) {

    enum {
        ARG_VERSION = 0x100,
        ARG_USER,
        ARG_SYSTEM,
        ARG_SCOPE,
        ARG_UNIT,
        ARG_DESCRIPTION,
        ARG_SLICE,
        ARG_SEND_SIGHUP,
        ARG_SERVICE_TYPE,
        ARG_EXEC_USER,
        ARG_EXEC_GROUP,
        ARG_NICE,
        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,
        ARG_NO_ASK_PASSWORD,
        ARG_WAIT,
    };

    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     },
        { "wait",              no_argument,       NULL, ARG_WAIT             },
        { "uid",               required_argument, NULL, ARG_EXEC_USER        },
        { "gid",               required_argument, NULL, ARG_EXEC_GROUP       },
        { "nice",              required_argument, NULL, ARG_NICE             },
        { "setenv",            required_argument, NULL, 'E'                  },
        { "property",          required_argument, NULL, 'p'                  },
        { "tty",               no_argument,       NULL, 't'                  }, /* deprecated */
        { "pty",               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:E:p:tq", options, NULL)) >= 0)

        switch (c) {

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

        case ARG_VERSION:
            return version();

        case ARG_NO_ASK_PASSWORD:
            arg_ask_password = false;
            break;

        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 = parse_nice(optarg, &arg_nice);
            if (r < 0)
                return log_error_errno(r, "Failed to parse nice value: %s", optarg);

            arg_nice_set = true;
            break;

        case 'E':
            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 ARG_WAIT:
            arg_wait = 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;
    }

    if (arg_wait) {
        if (arg_no_block) {
            log_error("--wait may not be combined with --no-block.");
            return -EINVAL;
        }

        if (with_timer()) {
            log_error("--wait may not be combined with timer operations.");
            return -EINVAL;
        }

        if (arg_scope) {
            log_error("--wait may not be combined with --scope.");
            return -EINVAL;
        }
    }

    return 1;
}