/* ausearch-options.c - parse commandline options and configure ausearch * Copyright 2005-08,2010-11,2014 Red Hat Inc., Durham, North Carolina. * Copyright (c) 2011 IBM Corp. * All Rights Reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Authors: * Debora Velarde * Steve Grubb * Marcelo Henrique Cerri */ #include "config.h" #include #include #include #include #include #include #include #include "ausearch-options.h" #include "ausearch-time.h" #include "ausearch-int.h" #include "libaudit.h" /* Global vars that will be accessed by the main program */ char *user_file = NULL; int force_logs = 0; /* Global vars that will be accessed by the match model */ unsigned int event_id = -1; gid_t event_gid = -1, event_egid = -1; ilist *event_type = NULL; pid_t event_pid = -1, event_ppid = -1; success_t event_success = S_UNSET; int event_exact_match = 0; uid_t event_uid = -1, event_euid = -1, event_loginuid = -2; int event_syscall = -1, event_machine = -1; int event_ua = 0, event_ga = 0, event_se = 0; int just_one = 0; uint32_t event_session_id = -2; long long event_exit = 0; int event_exit_is_set = 0; int line_buffered = 0; int event_debug = 0; int checkpt_timeonly = 0; const char *event_key = NULL; const char *event_filename = NULL; const char *event_exe = NULL; const char *event_comm = NULL; const char *event_hostname = NULL; const char *event_terminal = NULL; const char *event_subject = NULL; const char *event_object = NULL; const char *event_uuid = NULL; const char *event_vmname = NULL; const char *checkpt_filename = NULL; /* checkpoint filename if present */ report_t report_format = RPT_DEFAULT; ilist *event_type; slist *event_node_list = NULL; struct nv_pair { int value; const char *name; }; enum { S_EVENT, S_COMM, S_FILENAME, S_ALL_GID, S_EFF_GID, S_GID, S_HELP, S_HOSTNAME, S_INTERP, S_INFILE, S_MESSAGE_TYPE, S_PID, S_SYSCALL, S_OSUCCESS, S_TIME_END, S_TIME_START, S_TERMINAL, S_ALL_UID, S_EFF_UID, S_UID, S_LOGINID, S_VERSION, S_EXACT_MATCH, S_EXECUTABLE, S_CONTEXT, S_SUBJECT, S_OBJECT, S_PPID, S_KEY, S_RAW, S_NODE, S_IN_LOGS, S_JUST_ONE, S_SESSION, S_EXIT, S_LINEBUFFERED, S_UUID, S_VMNAME, S_DEBUG, S_CHECKPOINT, S_ARCH }; static struct nv_pair optiontab[] = { { S_EVENT, "-a" }, { S_ARCH, "--arch" }, { S_EVENT, "--event" }, { S_COMM, "-c" }, { S_COMM, "--comm" }, { S_CHECKPOINT, "--checkpoint" }, { S_DEBUG, "--debug" }, { S_EXIT, "-e" }, { S_EXIT, "--exit" }, { S_FILENAME, "-f" }, { S_FILENAME, "--file" }, { S_ALL_GID, "-ga" }, { S_ALL_GID, "--gid-all" }, { S_EFF_GID, "-ge" }, { S_EFF_GID, "--gid-effective" }, { S_GID, "-gi" }, { S_GID, "--gid" }, { S_HELP, "-h" }, { S_HELP, "--help" }, { S_HOSTNAME, "-hn" }, { S_HOSTNAME, "--host" }, { S_INTERP, "-i" }, { S_INTERP, "--interpret" }, { S_INFILE, "-if" }, { S_INFILE, "--input" }, { S_IN_LOGS, "--input-logs" }, { S_JUST_ONE, "--just-one" }, { S_KEY, "-k" }, { S_KEY, "--key" }, { S_LINEBUFFERED, "-l" }, { S_LINEBUFFERED, "--line-buffered" }, { S_MESSAGE_TYPE, "-m" }, { S_MESSAGE_TYPE, "--message" }, { S_NODE, "-n" }, { S_NODE, "--node" }, { S_OBJECT, "-o" }, { S_OBJECT, "--object" }, { S_PID, "-p" }, { S_PID, "--pid" }, { S_PPID, "-pp" }, { S_PPID, "--ppid" }, { S_RAW, "-r" }, { S_RAW, "--raw" }, { S_SYSCALL, "-sc" }, { S_SYSCALL, "--syscall" }, { S_CONTEXT, "-se" }, { S_CONTEXT, "--context" }, { S_SESSION, "--session" }, { S_SUBJECT, "-su" }, { S_SUBJECT, "--subject" }, { S_OSUCCESS, "-sv" }, { S_OSUCCESS, "--success" }, { S_TIME_END, "-te"}, { S_TIME_END, "--end"}, { S_TIME_START, "-ts" }, { S_TIME_START, "--start" }, { S_TERMINAL, "-tm" }, { S_TERMINAL, "--terminal" }, { S_ALL_UID, "-ua" }, { S_ALL_UID, "--uid-all" }, { S_EFF_UID, "-ue" }, { S_EFF_UID, "--uid-effective" }, { S_UID, "-ui" }, { S_UID, "--uid" }, { S_UUID, "-uu" }, { S_UUID, "--uuid" }, { S_LOGINID, "-ul" }, { S_LOGINID, "--loginuid" }, { S_VERSION, "-v" }, { S_VERSION, "--version" }, { S_VMNAME, "-vm" }, { S_VMNAME, "--vm-name" }, { S_EXACT_MATCH, "-w" }, { S_EXACT_MATCH, "--word" }, { S_EXECUTABLE, "-x" }, { S_EXECUTABLE, "--executable" } }; #define OPTION_NAMES (sizeof(optiontab)/sizeof(optiontab[0])) static int audit_lookup_option(const char *name) { int i; for (i = 0; i < OPTION_NAMES; i++) if (!strcmp(optiontab[i].name, name)) return optiontab[i].value; return -1; } static void usage(void) { printf("usage: ausearch [options]\n" "\t-a,--event \tsearch based on audit event id\n" "\t--arch \t\t\tsearch based on the CPU architecture\n" "\t-c,--comm \t\tsearch based on command line name\n" "\t--checkpoint \tsearch from last complete event\n" "\t--debug\t\t\tWrite malformed events that are skipped to stderr\n" "\t-e,--exit \tsearch based on syscall exit code\n" "\t-f,--file \t\tsearch based on file name\n" "\t-ga,--gid-all \tsearch based on All group ids\n" "\t-ge,--gid-effective search based on Effective\n\t\t\t\t\tgroup id\n" "\t-gi,--gid \t\tsearch based on group id\n" "\t-h,--help\t\t\thelp\n" "\t-hn,--host \t\tsearch based on remote host name\n" "\t-i,--interpret\t\t\tInterpret results to be human readable\n" "\t-if,--input \tuse this file instead of current logs\n" "\t--input-logs\t\t\tUse the logs even if stdin is a pipe\n" "\t--just-one\t\t\tEmit just one event\n" "\t-k,--key \t\tsearch based on key field\n" "\t-l, --line-buffered\t\tFlush output on every line\n" "\t-m,--message \tsearch based on message type\n" "\t-n,--node \t\tsearch based on machine's name\n" "\t-o,--object search based on context of object\n" "\t-p,--pid \t\tsearch based on process id\n" "\t-pp,--ppid \tsearch based on parent process id\n" "\t-r,--raw\t\t\toutput is completely unformatted\n" "\t-sc,--syscall \tsearch based on syscall name or number\n" "\t-se,--context search based on either subject or\n\t\t\t\t\t object\n" "\t--session \tsearch based on login session id\n" "\t-su,--subject search based on context of the Subject\n" "\t-sv,--success \tsearch based on syscall or event\n\t\t\t\t\tsuccess value\n" "\t-te,--end [end date] [end time]\tending date & time for search\n" "\t-ts,--start [start date] [start time]\tstarting data & time for search\n" "\t-tm,--terminal \tsearch based on terminal\n" "\t-ua,--uid-all \tsearch based on All user id's\n" "\t-ue,--uid-effective search based on Effective\n\t\t\t\t\tuser id\n" "\t-ui,--uid \t\tsearch based on user id\n" "\t-ul,--loginuid \tsearch based on the User's Login id\n" "\t-uu,--uuid \t\tsearch for events related to the virtual\n" "\t\t\t\t\tmachine with the given UUID.\n" "\t-v,--version\t\t\tversion\n" "\t-vm,--vm-name \tsearch for events related to the virtual\n" "\t\t\t\t\tmachine with the name.\n" "\t-w,--word\t\t\tstring matches are whole word\n" "\t-x,--executable search based on executable name\n" ); } static int convert_str_to_msg(const char *optarg) { int tmp, retval = 0; if (isdigit(optarg[0])) { errno = 0; tmp = strtoul(optarg, NULL, 10); if (errno) { fprintf(stderr, "Numeric message type conversion error (%s) for %s\n", strerror(errno), optarg); retval = -1; } } else { tmp = audit_name_to_msg_type(optarg); if (tmp < 0) retval = -1; } if (retval == 0) { if (event_type == NULL) { event_type = malloc(sizeof(ilist)); if (event_type == NULL) return -1; ilist_create(event_type); } ilist_append(event_type, tmp, 1, 0); } return retval; } static int parse_msg(const char *optarg) { int retval = 0; char *saved; if (strchr(optarg, ',')) { char *ptr, *tmp = strdup(optarg); if (tmp == NULL) return -1; ptr = strtok_r(tmp, ",", &saved); while (ptr) { retval = convert_str_to_msg(ptr); if (retval != 0) break; ptr = strtok_r(NULL, ",", &saved); } free(tmp); return retval; } return convert_str_to_msg(optarg); } /* * This function examines the commandline parameters and sets various * search options. It returns a 0 on success and < 0 on failure */ int check_params(int count, char *vars[]) { int c = 1; int retval = 0; const char *optarg; if (count < 2) { usage(); return -1; } while (c < count && retval == 0) { // Go ahead and point to the next argument if (c+1 < count) { if (vars[c+1][0] != '-') optarg = vars[c+1]; else optarg = NULL; } else optarg = NULL; switch (audit_lookup_option(vars[c])) { case S_EVENT: if (!optarg) { fprintf(stderr, "Argument is required for %s\n", vars[c]); retval = -1; break; } if (isdigit(optarg[0])) { errno = 0; event_id = strtoul(optarg, NULL, 10); if (errno) { fprintf(stderr, "Illegal value for audit event ID"); retval = -1; } c++; } else { fprintf(stderr, "Audit event id must be a numeric value, was %s\n", optarg); retval = -1; } break; case S_COMM: if (!optarg) { fprintf(stderr, "Argument is required for %s\n", vars[c]); retval = -1; break; } else { event_comm = strdup(optarg); if (event_comm == NULL) retval = -1; c++; } break; case S_FILENAME: if (!optarg) { fprintf(stderr, "Argument is required for %s\n", vars[c]); retval = -1; } else { event_filename = strdup(optarg); if (event_filename == NULL) retval = -1; c++; } break; case S_KEY: if (!optarg) { fprintf(stderr, "Argument is required for %s\n", vars[c]); retval = -1; } else { event_key = strdup(optarg); if (event_key == NULL) retval = -1; c++; } break; case S_ALL_GID: if (!optarg) { fprintf(stderr, "Argument is required for %s\n", vars[c]); retval = -1; break; } if (isdigit(optarg[0])) { errno = 0; event_gid = strtoul(optarg,NULL,10); if (errno) { fprintf(stderr, "Numeric group ID conversion error (%s) for %s\n", strerror(errno), optarg); retval = -1; } } else { struct group *gr ; gr = getgrnam(optarg) ; if (gr == NULL) { fprintf(stderr, "Group ID is non-numeric and unknown (%s)\n", optarg); retval = -1; break; } event_gid = gr->gr_gid; } event_egid = event_gid; event_ga = 1; c++; break; case S_EFF_GID: if (!optarg) { fprintf(stderr, "Argument is required for %s\n", vars[c]); retval = -1; break; } if (isdigit(optarg[0])) { errno = 0; event_egid = strtoul(optarg,NULL,10); if (errno) { fprintf(stderr, "Numeric group ID conversion error (%s) for %s\n", strerror(errno), optarg); retval = -1; } } else { struct group *gr ; gr = getgrnam(optarg) ; if (gr == NULL) { fprintf(stderr, "Effective group ID is non-numeric and unknown (%s)\n", optarg); retval = -1; break; } event_egid = gr->gr_gid; } c++; break; case S_GID: if (!optarg) { fprintf(stderr, "Argument is required for %s\n", vars[c]); retval = -1; break; } if (isdigit(optarg[0])) { errno = 0; event_gid = strtoul(optarg,NULL,10); if (errno) { fprintf(stderr, "Numeric group ID conversion error (%s) for %s\n", strerror(errno), optarg); retval = -1; } } else { struct group *gr ; gr = getgrnam(optarg) ; if (gr == NULL) { fprintf(stderr, "Group ID is non-numeric and unknown (%s)\n", optarg); retval = -1; break; } event_gid = gr->gr_gid; } c++; break; case S_HELP: usage(); exit(0); break; case S_HOSTNAME: if (!optarg) { fprintf(stderr, "Argument is required for %s\n", vars[c]); retval = -1; } else { event_hostname = strdup(optarg); if (event_hostname == NULL) retval = -1; c++; } break; case S_INTERP: if (report_format == RPT_DEFAULT) report_format = RPT_INTERP; else { fprintf(stderr, "Conflicting output format %s\n", vars[c]); retval = -1; } if (optarg) { fprintf(stderr, "Argument is NOT required for %s\n", vars[c]); retval = -1; } break; case S_INFILE: if (!optarg) { fprintf(stderr, "Argument is required for %s\n", vars[c]); retval = -1; } else { user_file = strdup(optarg); if (user_file == NULL) retval = -1; c++; } break; case S_MESSAGE_TYPE: if (!optarg) { fprintf(stderr, "Argument is required for %s\n", vars[c]); retval = -1; } else { if (strcasecmp(optarg, "ALL") != 0) { retval = parse_msg(optarg); } c++; } if (retval < 0) { int i; fprintf(stderr, "Valid message types are: ALL "); for (i=AUDIT_USER;i<=AUDIT_LAST_VIRT_MSG;i++){ const char *name; if (i == AUDIT_WATCH_INS) // Skip a few i = AUDIT_FIRST_USER_MSG; name = audit_msg_type_to_name(i); if (name) fprintf(stderr, "%s ", name); } fprintf(stderr, "\n"); } break; case S_OBJECT: if (!optarg) { fprintf(stderr, "Argument is required for %s\n", vars[c]); retval = -1; break; } else { event_object = strdup(optarg); if (event_object == NULL) retval = -1; c++; } break; case S_PPID: if (!optarg) { fprintf(stderr, "Argument is required for %s\n", vars[c]); retval = -1; break; } if (isdigit(optarg[0])) { errno = 0; event_ppid = strtol(optarg,NULL,10); if (errno) retval = -1; c++; } else { fprintf(stderr, "Parent process id must be a numeric value, was %s\n", optarg); retval = -1; } break; case S_PID: if (!optarg) { fprintf(stderr, "Argument is required for %s\n", vars[c]); retval = -1; break; } if (isdigit(optarg[0])) { errno = 0; event_pid = strtol(optarg,NULL,10); if (errno) retval = -1; c++; } else { fprintf(stderr, "Process id must be a numeric value, was %s\n", optarg); retval = -1; } break; case S_RAW: if (report_format == RPT_DEFAULT) report_format = RPT_RAW; else { fprintf(stderr, "Conflicting output format --raw\n"); retval = -1; } if (optarg) { fprintf(stderr, "Argument is NOT required for --raw\n"); retval = -1; } break; case S_NODE: if (!optarg) { fprintf(stderr, "Argument is required for %s\n", vars[c]); retval = -1; } else { snode sn; c++; if (!event_node_list) { event_node_list = malloc(sizeof (slist)); if (!event_node_list) { retval = -1; break; } slist_create(event_node_list); } sn.str = strdup(optarg); sn.key = NULL; sn.hits=0; slist_append(event_node_list, &sn); } break; case S_SYSCALL: if (!optarg) { fprintf(stderr, "Argument is required for %s\n", vars[c]); retval = -1; break; } if (isdigit(optarg[0])) { errno = 0; event_syscall = (int)strtoul(optarg, NULL, 10); if (errno) { fprintf(stderr, "Syscall numeric conversion error (%s) for %s\n", strerror(errno), optarg); retval = -1; } } else { if (event_machine == -1) { int machine; machine = audit_detect_machine(); if (machine < 0) { fprintf(stderr, "Error detecting machine type"); retval = -1; break; } event_machine = machine; } event_syscall = audit_name_to_syscall(optarg, event_machine); if (event_syscall == -1) { fprintf(stderr, "Syscall %s not found\n", optarg); retval = -1; } } c++; break; case S_CONTEXT: if (!optarg) { fprintf(stderr, "Argument is required for %s\n", vars[c]); retval = -1; break; } else { event_subject = strdup(optarg); if (event_subject == NULL) retval = -1; event_object = strdup(optarg); if (event_object == NULL) retval = -1; event_se = 1; c++; } break; case S_SUBJECT: if (!optarg) { fprintf(stderr, "Argument is required for %s\n", vars[c]); retval = -1; break; } else { event_subject = strdup(optarg); if (event_subject == NULL) retval = -1; c++; } break; case S_OSUCCESS: if (!optarg) { fprintf(stderr, "Argument is required for %s\n", vars[c]); retval = -1; break; } if ( (strstr(optarg, "yes")!=NULL) || (strstr(optarg, "no")!=NULL) ) { if (strcmp(optarg, "yes") == 0) event_success = S_SUCCESS; else event_success = S_FAILED; } else { fprintf(stderr, "Success must be 'yes' or 'no'.\n"); retval = -1; } c++; break; case S_SESSION: if (!optarg) { if ((c+1 < count) && vars[c+1]) optarg = vars[c+1]; else { fprintf(stderr, "Argument is required for %s\n", vars[c]); retval = -1; break; } } { size_t len = strlen(optarg); if (isdigit(optarg[0])) { errno = 0; event_session_id = strtoul(optarg,NULL,10); if (errno) retval = -1; c++; } else if (len >= 2 && *(optarg)=='-' && (isdigit(optarg[1]))) { errno = 0; event_session_id = strtoul(optarg, NULL, 0); if (errno) { retval = -1; fprintf(stderr, "Error converting %s\n", optarg); } c++; } else { fprintf(stderr, "Session id must be a numeric value, was %s\n", optarg); retval = -1; } } break; case S_EXIT: if (!optarg) { if ((c+1 < count) && vars[c+1]) optarg = vars[c+1]; else { fprintf(stderr, "Argument is required for %s\n", vars[c]); retval = -1; break; } } { size_t len = strlen(optarg); if (isdigit(optarg[0])) { errno = 0; event_exit = strtoll(optarg, NULL, 0); if (errno) { retval = -1; fprintf(stderr, "Error converting %s\n", optarg); } } else if (len >= 2 && *(optarg)=='-' && (isdigit(optarg[1]))) { errno = 0; event_exit = strtoll(optarg, NULL, 0); if (errno) { retval = -1; fprintf(stderr, "Error converting %s\n", optarg); } } else { event_exit = audit_name_to_errno(optarg); if (event_exit == 0) { retval = -1; fprintf(stderr, "Unknown errno, was %s\n", optarg); } } c++; if (retval != -1) event_exit_is_set = 1; } break; case S_TIME_END: if (optarg) { if ( (c+2 < count) && vars[c+2] && (vars[c+2][0] != '-') ) { /* Have both date and time - check order*/ if (strchr(optarg, ':')) { if (ausearch_time_end(vars[c+2], optarg) != 0) retval = -1; } else { if (ausearch_time_end(optarg, vars[c+2]) != 0) retval = -1; } c++; } else { // Check against recognized words int t = lookup_time(optarg); if (t >= 0) { if (ausearch_time_end(optarg, NULL) != 0) retval = -1; } else if ( (strchr(optarg, ':')) == NULL) { /* Only have date */ if (ausearch_time_end(optarg, NULL) != 0) retval = -1; } else { /* Only have time */ if (ausearch_time_end(NULL, optarg) != 0) retval = -1; } } c++; break; } fprintf(stderr, "%s requires either date and/or time\n", vars[c]); retval = -1; break; case S_TIME_START: if (optarg) { if ( (c+2 < count) && vars[c+2] && (vars[c+2][0] != '-') ) { /* Have both date and time - check order */ if (strchr(optarg, ':')) { if (ausearch_time_start( vars[c+2], optarg) != 0) retval = -1; } else { if (ausearch_time_start(optarg, vars[c+2]) != 0) retval = -1; } c++; } else { // Check against recognized words int t = lookup_time(optarg); if (t >= 0) { if (ausearch_time_start(optarg, "00:00:00") != 0) retval = -1; } else if (strcmp(optarg, "checkpoint") == 0) { // Only use the timestamp from within // the checkpoint file checkpt_timeonly++; } else if (strchr(optarg, ':') == NULL){ /* Only have date */ if (ausearch_time_start(optarg, "00:00:00") != 0) retval = -1; } else { /* Only have time */ if (ausearch_time_start(NULL, optarg) != 0) retval = -1; } } c++; break; } fprintf(stderr, "%s requires either date and/or time\n", vars[c]); retval = -1; break; case S_TERMINAL: if (!optarg) { fprintf(stderr, "Argument is required for %s\n", vars[c]); retval = -1; } else { event_terminal = strdup(optarg); if (event_terminal == NULL) retval = -1; c++; } break; case S_UID: if (!optarg) { fprintf(stderr, "Argument is required for %s\n", vars[c]); retval = -1; break; } if (isdigit(optarg[0])) { errno = 0; event_uid = strtoul(optarg,NULL,10); if (errno) { fprintf(stderr, "Numeric user ID conversion error (%s) for %s\n", strerror(errno), optarg); retval = -1; } } else { struct passwd *pw; pw = getpwnam(optarg); if (pw == NULL) { fprintf(stderr, "Effective user ID is non-numeric and unknown (%s)\n", optarg); retval = -1; break; } event_uid = pw->pw_uid; } c++; break; case S_EFF_UID: if (!optarg) { fprintf(stderr, "Argument is required for %s\n", vars[c]); retval = -1; break; } if (isdigit(optarg[0])) { errno = 0; event_euid = strtoul(optarg,NULL,10); if (errno) { fprintf(stderr, "Numeric user ID conversion error (%s) for %s\n", strerror(errno), optarg); retval = -1; } } else { struct passwd *pw ; pw = getpwnam(optarg) ; if (pw == NULL) { fprintf(stderr, "User ID is non-numeric and unknown (%s)\n", optarg); retval = -1; break; } event_euid = pw->pw_uid; } c++; break; case S_ALL_UID: if (!optarg) { fprintf(stderr, "Argument is required for %s\n", vars[c]); retval = -1; break; } if (isdigit(optarg[0])) { errno = 0; event_uid = strtoul(optarg,NULL,10); if (errno) { fprintf(stderr, "Numeric user ID conversion error (%s) for %s\n", strerror(errno), optarg); retval = -1; } } else { struct passwd *pw ; pw = getpwnam(optarg) ; if (pw == NULL) { fprintf(stderr, "User ID is non-numeric and unknown (%s)\n", optarg); retval = -1; break; } event_uid = pw->pw_uid; } event_ua = 1; event_euid = event_uid; event_loginuid = event_uid; c++; break; case S_LOGINID: if (!optarg) { if ((c+1 < count) && vars[c+1]) optarg = vars[c+1]; else { fprintf(stderr, "Argument is required for %s\n", vars[c]); retval = -1; break; } } { size_t len = strlen(optarg); if (isdigit(optarg[0])) { errno = 0; event_loginuid = strtoul(optarg,NULL,10); if (errno) { fprintf(stderr, "Numeric user ID conversion error (%s) for %s\n", strerror(errno), optarg); retval = -1; } } else if (len >= 2 && *(optarg)=='-' && (isdigit(optarg[1]))) { errno = 0; event_loginuid = strtol(optarg, NULL, 0); if (errno) { retval = -1; fprintf(stderr, "Error converting %s\n", optarg); } } else { struct passwd *pw ; pw = getpwnam(optarg) ; if (pw == NULL) { fprintf(stderr, "Login user ID is non-numeric and unknown (%s)\n", optarg); retval = -1; break; } event_loginuid = pw->pw_uid; } } c++; break; case S_UUID: if (!optarg) { fprintf(stderr, "Argument is required for %s\n", vars[c]); retval = -1; } else { event_uuid = strdup(optarg); if (event_uuid == NULL) { retval = -1; } c++; } break; case S_VMNAME: if (!optarg) { fprintf(stderr, "Argument is required for %s\n", vars[c]); retval = -1; } else { event_vmname= strdup(optarg); if (event_vmname == NULL) { retval = -1; } c++; } break; case S_VERSION: printf("ausearch version %s\n", VERSION); exit(0); break; case S_EXACT_MATCH: event_exact_match=1; break; case S_IN_LOGS: force_logs = 1; break; case S_JUST_ONE: just_one = 1; break; case S_EXECUTABLE: if (!optarg) { fprintf(stderr, "Argument is required for %s\n", vars[c]); retval = -1; } else { event_exe = strdup(optarg); if (event_exe == NULL) retval = -1; c++; } break; case S_LINEBUFFERED: line_buffered = 1; break; case S_DEBUG: event_debug = 1; break; case S_CHECKPOINT: if (!optarg) { fprintf(stderr, "Argument is required for %s\n", vars[c]); retval = -1; } else { checkpt_filename = strdup(optarg); if (checkpt_filename == NULL) retval = -1; c++; } break; case S_ARCH: if (!optarg) { fprintf(stderr, "Argument is required for %s\n", vars[c]); retval = -1; break; } if (event_machine != -1) { if (event_syscall != -1) fprintf(stderr, "Arch needs to be defined before the syscall\n"); else fprintf(stderr, "Arch is already defined\n"); retval = -1; break; } else { int machine = audit_determine_machine(optarg); if (machine < 0) { fprintf(stderr, "Unknown arch %s\n", optarg); retval = -1; } event_machine = machine; } c++; break; default: fprintf(stderr, "%s is an unsupported option\n", vars[c]); retval = -1; break; } c++; } return retval; }