/* *************************************************************************** * Read stats for current activity from file and print them. * Display at most <count> lines of stats (and possibly comments inserted * in file) located between two LINUX RESTART messages. * * IN: * @ifd File descriptor of input file. * @fpos Position in file where reading must start. * @curr Index in array for current sample statistics. * @act_id Activity to display, or ~0 for all. * @file_actlst List of (known or unknown) activities in file. * @cpu_nr Number of processors for current activity data file. * @rectime Structure where timestamp (expressed in local time or in UTC * depending on whether options -T/-t have been used or not) can * be saved for current record. * @loctime Structure where timestamp (expressed in local time) can be * saved for current record. * @file Name of file being read. * @file_magic file_magic structure filled with file magic header data. * * OUT: * @curr Index in array for next sample statistics. * @cnt Number of lines of stats remaining to write. * @eosaf Set to TRUE if EOF (end of file) has been reached. * @reset Set to TRUE if last_uptime variable should be * reinitialized (used in next_slice() function). *************************************************************************** */ void rw_curr_act_stats(int ifd, off_t fpos, int *curr, long *cnt, int *eosaf, unsigned int act_id, int *reset, struct file_activity *file_actlst, __nr_t cpu_nr, struct tm *rectime, struct tm *loctime, char *file, struct file_magic *file_magic) { int rtype; int next, reset_cd; if (lseek(ifd, fpos, SEEK_SET) < fpos) { perror("lseek"); exit(2); } if (DISPLAY_FIELD_LIST(fmt[f_position]->options)) { /* Print field list */ list_fields(act_id); } /* * Restore the first stats collected. * Used to compute the rate displayed on the first line. */ copy_structures(act, id_seq, record_hdr, !*curr, 2); *cnt = count; reset_cd = 1; do { /* Display <count> lines of stats */ *eosaf = read_next_sample(ifd, IGNORE_RESTART | DONT_READ_VOLATILE, *curr, file, &rtype, 0, file_magic, file_actlst, rectime, loctime); if (!*eosaf && (rtype != R_RESTART) && (rtype != R_COMMENT)) { next = logic2_write_stats(*curr, *reset, cnt, tm_start.use, tm_end.use, act_id, cpu_nr, rectime, loctime, reset_cd); reset_cd = 0; if (next) { /* * next is set to 1 when we were close enough to desired interval. * In this case, the call to logic2_write_stats() has actually * displayed a line of stats. */ *curr ^= 1; if (*cnt > 0) { (*cnt)--; } } *reset = FALSE; } } while (*cnt && !*eosaf && (rtype != R_RESTART)); *reset = TRUE; }
int main(int argc, char **argv) { int c; struct varnish_stats *VSL_stats; int delay = 1, once = 0, xml = 0; const char *n_arg = NULL; const char *fields = NULL; while ((c = getopt(argc, argv, "1f:ln:Vw:x")) != -1) { switch (c) { case '1': once = 1; break; case 'f': fields = optarg; break; case 'l': list_fields(); exit(0); case 'n': n_arg = optarg; break; case 'V': varnish_version("varnishstat"); exit(0); case 'w': delay = atoi(optarg); break; case 'x': xml = 1; break; default: usage(); } } if ((VSL_stats = VSL_OpenStats(n_arg)) == NULL) exit(1); if (fields != NULL && !valid_fields(fields)) { usage(); exit(1); } if (xml) do_xml(VSL_stats, fields); else if (once) do_once(VSL_stats, fields); else do_curses(VSL_stats, delay, fields); exit(0); }
int main(int argc, char * const *argv) { int c; struct VSM_data *vd; int delay = 1, once = 0, xml = 0, json = 0, do_repeat = 0; vd = VSM_New(); while ((c = getopt(argc, argv, VSC_ARGS "1f:lVw:xjt:")) != -1) { switch (c) { case '1': once = 1; break; case 'l': list_fields(vd); exit(0); case 'V': VCS_Message("varnishstat"); exit(0); case 'w': do_repeat = 1; delay = atoi(optarg); break; case 'x': xml = 1; break; case 'j': json = 1; break; default: if (VSC_Arg(vd, c, optarg) > 0) break; usage(); } } if (VSM_Open(vd)) { fprintf(stderr, "%s\n", VSM_Error(vd)); exit(1); } if (!(xml || json || once)) { do_curses(vd, delay); exit(0); } while (1) { if (xml) do_xml(vd); else if (json) do_json(vd); else if (once) do_once(vd, VSC_Main(vd, NULL)); else { assert(0); } if (!do_repeat) break; // end of output block marker. printf("\n"); sleep(delay); } exit(0); }
// // ARGUMENT PARSING AND PROGRAM SETUP // sysdig_init_res sysdig_init(int argc, char **argv) { sysdig_init_res res; sinsp* inspector = NULL; vector<string> infiles; string outfile; int op; uint64_t cnt = -1; bool quiet = false; bool is_filter_display = false; bool verbose = false; bool list_flds = false; bool list_flds_markdown = false; bool print_progress = false; bool compress = false; sinsp_evt::param_fmt event_buffer_format = sinsp_evt::PF_NORMAL; sinsp_filter* display_filter = NULL; double duration = 1; int duration_to_tot = 0; captureinfo cinfo; string output_format; uint32_t snaplen = 0; int long_index = 0; int32_t n_filterargs = 0; int cflag = 0; bool jflag = false; bool unbuf_flag = false; bool filter_proclist_flag = false; string cname; vector<summary_table_entry>* summary_table = NULL; string* k8s_api = 0; string* k8s_api_cert = 0; string* mesos_api = 0; // These variables are for the cycle_writer engine int duration_seconds = 0; int rollover_mb = 0; int file_limit = 0; unsigned long event_limit = 0L; static struct option long_options[] = { {"print-ascii", no_argument, 0, 'A' }, {"print-base64", no_argument, 0, 'b' }, #ifdef HAS_CHISELS {"chisel", required_argument, 0, 'c' }, {"list-chisels", no_argument, &cflag, 1 }, #endif {"displayflt", no_argument, 0, 'd' }, {"debug", no_argument, 0, 'D'}, {"exclude-users", no_argument, 0, 'E' }, {"event-limit", required_argument, 0, 'e'}, {"fatfile", no_argument, 0, 'F'}, {"filter-proclist", no_argument, 0, 0 }, {"seconds", required_argument, 0, 'G' }, {"help", no_argument, 0, 'h' }, #ifdef HAS_CHISELS {"chisel-info", required_argument, 0, 'i' }, #endif {"file-size", required_argument, 0, 'C' }, {"json", no_argument, 0, 'j' }, {"k8s-api", required_argument, 0, 'k'}, {"k8s-api-cert", required_argument, 0, 'K' }, {"list", no_argument, 0, 'l' }, {"list-events", no_argument, 0, 'L' }, {"list-markdown", no_argument, 0, 0 }, {"mesos-api", required_argument, 0, 'm'}, {"numevents", required_argument, 0, 'n' }, {"progress", required_argument, 0, 'P' }, {"print", required_argument, 0, 'p' }, {"quiet", no_argument, 0, 'q' }, {"readfile", required_argument, 0, 'r' }, {"snaplen", required_argument, 0, 's' }, {"summary", no_argument, 0, 'S' }, {"timetype", required_argument, 0, 't' }, {"unbuffered", no_argument, 0, 0 }, {"verbose", no_argument, 0, 'v' }, {"version", no_argument, 0, 0 }, {"writefile", required_argument, 0, 'w' }, {"limit", required_argument, 0, 'W' }, {"print-hex", no_argument, 0, 'x'}, {"print-hex-ascii", no_argument, 0, 'X'}, {"compress", no_argument, 0, 'z' }, {0, 0, 0, 0} }; output_format = "*%evt.num %evt.outputtime %evt.cpu %proc.name (%thread.tid) %evt.dir %evt.type %evt.info"; try { inspector = new sinsp(); #ifdef HAS_CHISELS add_chisel_dirs(inspector); #endif // // Parse the args // while((op = getopt_long(argc, argv, "Abc:" "C:" "dDEe:F" "G:" "hi:jk:K:lLm:M:Nn:Pp:qr:Ss:t:v" "W:" "w:xXz", long_options, &long_index)) != -1) { switch(op) { case 'A': if(event_buffer_format != sinsp_evt::PF_NORMAL) { fprintf(stderr, "you cannot specify more than one output format\n"); delete inspector; return sysdig_init_res(EXIT_SUCCESS); } event_buffer_format = sinsp_evt::PF_EOLS; break; case 'b': if(event_buffer_format != sinsp_evt::PF_NORMAL) { fprintf(stderr, "you cannot specify more than one output format\n"); delete inspector; return sysdig_init_res(EXIT_SUCCESS); } event_buffer_format = sinsp_evt::PF_BASE64; break; case 0: if(cflag != 1 && cflag != 2) { break; } if(cflag == 2) { cname = optarg; } #ifdef HAS_CHISELS case 'c': { if(cflag == 0) { string ostr(optarg); if(ostr.size() >= 1) { if(ostr == "l") { cflag = 1; } } } if(cflag == 1) { vector<chisel_desc> chlist; sinsp_chisel::get_chisel_list(&chlist); list_chisels(&chlist, true); delete inspector; return sysdig_init_res(EXIT_SUCCESS); } sinsp_chisel* ch = new sinsp_chisel(inspector, optarg); parse_chisel_args(ch, inspector, optind, argc, argv, &n_filterargs); g_chisels.push_back(ch); } #endif break; // File-size case 'C': rollover_mb = atoi(optarg); if(rollover_mb <= 0) { throw sinsp_exception(string("invalid file size") + optarg); res.m_res = EXIT_FAILURE; goto exit; } break; case 'D': inspector->set_debug_mode(true); inspector->set_log_stderr(); break; case 'E': inspector->set_import_users(false); break; case 'e': event_limit = strtoul(optarg, NULL, 0); if(event_limit <= 0) { throw sinsp_exception(string("invalid parameter 'number of events' ") + optarg); res.m_res = EXIT_FAILURE; goto exit; } break; case 'F': inspector->set_fatfile_dump_mode(true); break; // Number of seconds between roll-over case 'G': duration_seconds = atoi(optarg); if(duration_seconds <= 0) { throw sinsp_exception(string("invalid duration") + optarg); res.m_res = EXIT_FAILURE; goto exit; } break; #ifdef HAS_CHISELS // --chisel-info and -i case 'i': { cname = optarg; vector<chisel_desc> chlist; sinsp_chisel::get_chisel_list(&chlist); for(uint32_t j = 0; j < chlist.size(); j++) { if(chlist[j].m_name == cname) { print_chisel_info(&chlist[j]); delete inspector; return sysdig_init_res(EXIT_SUCCESS); } } throw sinsp_exception("chisel " + cname + " not found - use -cl to list them."); } break; #endif case 'd': is_filter_display = true; break; case 'j': // // set the json flag to 1 for now, the data format will depend from the print format parameters // jflag = true; break; case 'k': k8s_api = new string(optarg); break; case 'K': k8s_api_cert = new string(optarg); break; case 'h': usage(); delete inspector; return sysdig_init_res(EXIT_SUCCESS); case 'l': list_flds = true; break; case 'L': list_events(inspector); delete inspector; return sysdig_init_res(EXIT_SUCCESS); case 'm': mesos_api = new string(optarg); break; case 'M': duration_to_tot = atoi(optarg); if(duration_to_tot <= 0) { throw sinsp_exception(string("invalid duration") + optarg); res.m_res = EXIT_FAILURE; goto exit; } break; case 'N': inspector->set_hostname_and_port_resolution_mode(false); break; case 'n': try { cnt = sinsp_numparser::parseu64(optarg); } catch(...) { throw sinsp_exception("can't parse the -n argument, make sure it's a number"); } if(cnt <= 0) { throw sinsp_exception(string("invalid event count ") + optarg); res.m_res = EXIT_FAILURE; goto exit; } break; case 'P': print_progress = true; break; case 'p': if(string(optarg) == "p") { // -pp shows the default output format, useful if the user wants to tweak it. printf("%s\n", output_format.c_str()); delete inspector; return sysdig_init_res(EXIT_SUCCESS); } else if(string(optarg) == "c" || string(optarg) == "container") { output_format = "*%evt.num %evt.outputtime %evt.cpu %container.name (%container.id) %proc.name (%thread.tid:%thread.vtid) %evt.dir %evt.type %evt.info"; // This enables chisels to determine if they should print container information if(inspector != NULL) { inspector->set_print_container_data(true); } } else if(string(optarg) == "k" || string(optarg) == "kubernetes") { output_format = "*%evt.num %evt.outputtime %evt.cpu %k8s.pod.name (%container.id) %proc.name (%thread.tid:%thread.vtid) %evt.dir %evt.type %evt.info"; // This enables chisels to determine if they should print container information if(inspector != NULL) { inspector->set_print_container_data(true); } } else if(string(optarg) == "m" || string(optarg) == "mesos") { output_format = "*%evt.num %evt.outputtime %evt.cpu %mesos.task.name (%container.id) %proc.name (%thread.tid:%thread.vtid) %evt.dir %evt.type %evt.info"; // This enables chisels to determine if they should print container information if(inspector != NULL) { inspector->set_print_container_data(true); } } else { output_format = optarg; } break; case 'q': quiet = true; break; case 'r': infiles.push_back(optarg); k8s_api = new string(); mesos_api = new string(); break; case 'S': summary_table = new vector<summary_table_entry>; for(uint32_t j = 0; j < PPM_EVENT_MAX; j++) { summary_table->push_back(summary_table_entry(j, false)); } for(uint32_t j = 0; j < PPM_SC_MAX * 2; j++) { summary_table->push_back(summary_table_entry(j, true)); } break; case 's': snaplen = atoi(optarg); break; case 't': { string tms(optarg); if(tms == "h" || tms == "a" || tms == "r" || tms == "d" || tms == "D") { inspector->set_time_output_mode(tms.c_str()[0]); } else { fprintf(stderr, "invalid modifier for flag -t\n"); delete inspector; return sysdig_init_res(EXIT_FAILURE); } } break; case 'v': verbose = true; break; case 'w': outfile = optarg; quiet = true; break; // Number of capture files to cycle through case 'W': file_limit = atoi(optarg); if(file_limit <= 0) { throw sinsp_exception(string("invalid file limit") + optarg); res.m_res = EXIT_FAILURE; goto exit; } break; case 'x': if(event_buffer_format != sinsp_evt::PF_NORMAL) { fprintf(stderr, "you cannot specify more than one output format\n"); delete inspector; return sysdig_init_res(EXIT_FAILURE); } event_buffer_format = sinsp_evt::PF_HEX; break; case 'X': if(event_buffer_format != sinsp_evt::PF_NORMAL) { fprintf(stderr, "you cannot specify more than one output format\n"); delete inspector; return sysdig_init_res(EXIT_FAILURE); } event_buffer_format = sinsp_evt::PF_HEXASCII; break; case 'z': compress = true; break; // getopt_long : '?' for an ambiguous match or an extraneous parameter case '?': delete inspector; return sysdig_init_res(EXIT_FAILURE); break; default: break; } if(string(long_options[long_index].name) == "version") { printf("sysdig version %s\n", SYSDIG_VERSION); delete inspector; return sysdig_init_res(EXIT_SUCCESS); } if(string(long_options[long_index].name) == "unbuffered") { unbuf_flag = true; } if(string(long_options[long_index].name) == "filter-proclist") { filter_proclist_flag = true; } if(string(long_options[long_index].name) == "list-markdown") { list_flds = true; list_flds_markdown = true; } } // // If -j was specified the event_buffer_format must be rewritten to account for it // if(jflag) { switch (event_buffer_format) { case sinsp_evt::PF_NORMAL: event_buffer_format = sinsp_evt::PF_JSON; break; case sinsp_evt::PF_EOLS: event_buffer_format = sinsp_evt::PF_JSONEOLS; break; case sinsp_evt::PF_HEX: event_buffer_format = sinsp_evt::PF_JSONHEX; break; case sinsp_evt::PF_HEXASCII: event_buffer_format = sinsp_evt::PF_JSONHEXASCII; break; case sinsp_evt::PF_BASE64: event_buffer_format = sinsp_evt::PF_JSONBASE64; break; default: // do nothing break; } } inspector->set_buffer_format(event_buffer_format); // // If -l was specified, print the fields and exit // if(list_flds) { if(verbose) { // // -ll shows the fields verbosely, i.e. with more information // like the type // list_fields(true, list_flds_markdown); } else { list_fields(false, list_flds_markdown); } res.m_res = EXIT_SUCCESS; goto exit; } string filter; // // the filter is at the end of the command line // if(optind + n_filterargs < argc) { #ifdef HAS_FILTERING for(int32_t j = optind + n_filterargs; j < argc; j++) { filter += argv[j]; if(j < argc - 1) { filter += " "; } } if(is_filter_display) { sinsp_filter_compiler compiler(inspector, filter); display_filter = compiler.compile(); } #else fprintf(stderr, "filtering not compiled.\n"); res.m_res = EXIT_FAILURE; goto exit; #endif } if(signal(SIGINT, signal_callback) == SIG_ERR) { fprintf(stderr, "An error occurred while setting SIGINT signal handler.\n"); res.m_res = EXIT_FAILURE; goto exit; } if(signal(SIGTERM, signal_callback) == SIG_ERR) { fprintf(stderr, "An error occurred while setting SIGTERM signal handler.\n"); res.m_res = EXIT_FAILURE; goto exit; } // // Create the event formatter // sinsp_evt_formatter formatter(inspector, output_format); // // Set output buffers len // if(!verbose && g_chisels.size() == 0) { inspector->set_max_evt_output_len(80); } // // Determine if we need to filter when dumping to file // if(filter_proclist_flag) { if(filter != "") { if(infiles.size() == 0) { fprintf(stderr, "--filter-proclist not supported with live captures.\n"); res.m_res = EXIT_FAILURE; goto exit; } inspector->filter_proc_table_when_saving(true); } else { fprintf(stderr, "you must specify a filter if you use --filter-proclist.\n"); res.m_res = EXIT_FAILURE; goto exit; } } for(uint32_t j = 0; j < infiles.size() || infiles.size() == 0; j++) { #ifdef HAS_FILTERING if(filter.size() && !is_filter_display) { inspector->set_filter(filter); } #endif // // Launch the capture // if(infiles.size() != 0) { initialize_chisels(); // // We have a file to open // inspector->open(infiles[j]); } else { if(j > 0) { break; } initialize_chisels(); // // No file to open, this is a live capture // #if defined(HAS_CAPTURE) bool open_success = true; if(print_progress) { fprintf(stderr, "the -P flag cannot be used with live captures.\n"); res.m_res = EXIT_FAILURE; goto exit; } try { inspector->open(""); } catch(sinsp_exception e) { open_success = false; } // // Starting the live capture failed, try to load the driver with // modprobe. // if(!open_success) { open_success = true; if(system("modprobe " PROBE_NAME " > /dev/null 2> /dev/null")) { fprintf(stderr, "Unable to load the driver\n"); } inspector->open(""); } #else // // Starting live capture // If this fails on Windows and OSX, don't try with any driver // inspector->open(""); #endif // // Enable gathering the CPU from the kernel module // inspector->set_get_procs_cpu_from_driver(true); } if(snaplen != 0) { inspector->set_snaplen(snaplen); } duration = ((double)clock()) / CLOCKS_PER_SEC; if(outfile != "") { inspector->setup_cycle_writer(outfile, rollover_mb, duration_seconds, file_limit, event_limit, compress); inspector->autodump_next_file(); } // // Notify the chisels that the capture is starting // chisels_on_capture_start(); // // run k8s, if required // if(k8s_api) { if(!k8s_api_cert) { if(char* k8s_cert_env = getenv("SYSDIG_K8S_API_CERT")) { k8s_api_cert = new string(k8s_cert_env); } } inspector->init_k8s_client(k8s_api, k8s_api_cert, verbose); k8s_api = 0; k8s_api_cert = 0; } else if(char* k8s_api_env = getenv("SYSDIG_K8S_API")) { if(k8s_api_env != NULL) { if(!k8s_api_cert) { if(char* k8s_cert_env = getenv("SYSDIG_K8S_API_CERT")) { k8s_api_cert = new string(k8s_cert_env); } } k8s_api = new string(k8s_api_env); inspector->init_k8s_client(k8s_api, k8s_api_cert, verbose); } else { delete k8s_api; delete k8s_api_cert; } k8s_api = 0; k8s_api_cert = 0; } // // run mesos, if required // if(mesos_api) { inspector->init_mesos_client(mesos_api, verbose); } else if(char* mesos_api_env = getenv("SYSDIG_MESOS_API")) { if(mesos_api_env != NULL) { mesos_api = new string(mesos_api_env); inspector->init_mesos_client(mesos_api, verbose); } } delete mesos_api; mesos_api = 0; cinfo = do_inspect(inspector, cnt, duration_to_tot, quiet, jflag, unbuf_flag, print_progress, display_filter, summary_table, &formatter); duration = ((double)clock()) / CLOCKS_PER_SEC - duration; scap_stats cstats; inspector->get_capture_stats(&cstats); if(verbose) { fprintf(stderr, "Driver Events:%" PRIu64 "\nDriver Drops:%" PRIu64 "\n", cstats.n_evts, cstats.n_drops); fprintf(stderr, "Elapsed time: %.3lf, Captured Events: %" PRIu64 ", %.2lf eps\n", duration, cinfo.m_nevts, (double)cinfo.m_nevts / duration); } // // Done. Close the capture. // inspector->close(); } } catch(sinsp_capture_interrupt_exception&) { handle_end_of_file(print_progress); } catch(sinsp_exception& e) { cerr << e.what() << endl; handle_end_of_file(print_progress); res.m_res = EXIT_FAILURE; } catch(...) { handle_end_of_file(print_progress); res.m_res = EXIT_FAILURE; } exit: // // If any of the chisels is requesting another run, // for(vector<sinsp_chisel*>::iterator it = g_chisels.begin(); it != g_chisels.end(); ++it) { string na; if((*it)->get_nextrun_args(&na)) { res.m_next_run_args = sinsp_split(na, ' '); } } // // If there's a summary table, sort and print it // if(summary_table != NULL) { print_summary_table(inspector, summary_table, 100); } // // Free all the stuff that was allocated // free_chisels(); if(inspector) { delete inspector; } if(display_filter) { delete display_filter; } return res; }
// // MAIN // int main(int argc, char **argv) { int res = EXIT_SUCCESS; sinsp* inspector = NULL; vector<string> infiles; string outfile; int op; uint64_t cnt = -1; bool quiet = false; bool absolute_times = false; bool is_filter_display = false; bool verbose = false; bool list_flds = false; bool print_progress = false; bool compress = false; sinsp_evt::param_fmt event_buffer_format = sinsp_evt::PF_NORMAL; sinsp_filter* display_filter = NULL; double duration = 1; captureinfo cinfo; string output_format; uint32_t snaplen = 0; int long_index = 0; int32_t n_filterargs = 0; int cflag = 0; string cname; vector<summary_table_entry>* summary_table = NULL; string timefmt = "%evt.time"; static struct option long_options[] = { {"print-ascii", no_argument, 0, 'A' }, {"abstimes", no_argument, 0, 'a' }, #ifdef HAS_CHISELS {"chisel", required_argument, 0, 'c' }, {"list-chisels", no_argument, &cflag, 1 }, #endif {"compress", no_argument, 0, 'z' }, {"displayflt", no_argument, 0, 'd' }, {"debug", no_argument, 0, 'D'}, {"help", no_argument, 0, 'h' }, #ifdef HAS_CHISELS {"chisel-info", required_argument, 0, 'i' }, #endif {"json", no_argument, 0, 'j' }, {"list", no_argument, 0, 'l' }, {"list-events", no_argument, 0, 'L' }, {"numevents", required_argument, 0, 'n' }, {"progress", required_argument, 0, 'P' }, {"print", required_argument, 0, 'p' }, {"quiet", no_argument, 0, 'q' }, {"readfile", required_argument, 0, 'r' }, {"snaplen", required_argument, 0, 's' }, {"summary", no_argument, 0, 'S' }, {"timetype", required_argument, 0, 't' }, {"verbose", no_argument, 0, 'v' }, {"writefile", required_argument, 0, 'w' }, {"print-hex", no_argument, 0, 'x'}, {"print-hex-ascii", no_argument, 0, 'X'}, {0, 0, 0, 0} }; output_format = "*%evt.num <TIME> %evt.cpu %proc.name (%thread.tid) %evt.dir %evt.type %evt.args"; // output_format = DEFAULT_OUTPUT_STR; try { inspector = new sinsp(); #ifdef HAS_CHISELS add_chisel_dirs(inspector); #endif // // Parse the args // while((op = getopt_long(argc, argv, "Aac:dDhi:jlLn:Pp:qr:Ss:t:vw:xXz", long_options, &long_index)) != -1) { switch(op) { case 'A': if(event_buffer_format != sinsp_evt::PF_NORMAL) { fprintf(stderr, "you cannot specify more than one output format\n"); delete inspector; return EXIT_SUCCESS; } event_buffer_format = sinsp_evt::PF_EOLS; break; case 'a': absolute_times = true; break; case 0: if(cflag != 1 && cflag != 2) { break; } if(cflag == 2) { cname = optarg; } #ifdef HAS_CHISELS case 'c': { if(cflag == 0) { string ostr(optarg); if(ostr.size() >= 1) { if(ostr == "l") { cflag = 1; } } } if(cflag == 1) { vector<chisel_desc> chlist; sinsp_chisel::get_chisel_list(&chlist); list_chisels(&chlist, true); delete inspector; return EXIT_SUCCESS; } sinsp_chisel* ch = new sinsp_chisel(inspector, optarg); parse_chisel_args(ch, inspector, optind, argc, argv, &n_filterargs); g_chisels.push_back(ch); } #endif break; case 'D': inspector->set_debug_mode(true); break; #ifdef HAS_CHISELS // --chisel-info and -i case 'i': { cname = optarg; vector<chisel_desc> chlist; sinsp_chisel::get_chisel_list(&chlist); for(uint32_t j = 0; j < chlist.size(); j++) { if(chlist[j].m_name == cname) { print_chisel_info(&chlist[j]); delete inspector; return EXIT_SUCCESS; } } throw sinsp_exception("chisel " + cname + " not found - use -cl to list them."); } break; #endif case 'd': is_filter_display = true; break; case 'j': // throw sinsp_exception("json output not yet implemented"); if(event_buffer_format != sinsp_evt::PF_NORMAL) { fprintf(stderr, "you cannot specify more than one output format\n"); delete inspector; return EXIT_SUCCESS; } event_buffer_format = sinsp_evt::PF_JSON; break; case 'h': usage(); delete inspector; return EXIT_SUCCESS; case 'l': list_flds = true; break; case 'L': list_events(inspector); delete inspector; return EXIT_SUCCESS; case 'n': cnt = atoi(optarg); if(cnt <= 0) { throw sinsp_exception(string("invalid packet count") + optarg); res = EXIT_FAILURE; goto exit; } break; case 'P': print_progress = true; break; case 'p': if(string(optarg) == "p") { // // -pp shows the default output format, useful if the user wants to tweak it. // replace_in_place(output_format, "<TIME>", timefmt); printf("%s\n", output_format.c_str()); delete inspector; return EXIT_SUCCESS; } else { output_format = optarg; } break; case 'q': quiet = true; break; case 'r': infiles.push_back(optarg); break; case 'S': summary_table = new vector<summary_table_entry>; for(uint32_t j = 0; j < PPM_EVENT_MAX; j++) { summary_table->push_back(summary_table_entry(j, false)); } for(uint32_t j = 0; j < PPM_SC_MAX * 2; j++) { summary_table->push_back(summary_table_entry(j, true)); } break; case 's': snaplen = atoi(optarg); break; case 't': { string tms(optarg); if(tms == "h") { timefmt = "%evt.time"; } else if(tms == "a") { timefmt = "%evt.rawtime.s.%evt.rawtime.ns"; } else if(tms == "r") { timefmt = "%evt.reltime.s.%evt.reltime.ns"; } else if(tms == "d") { timefmt = "%evt.latency.s.%evt.latency.ns"; } } break; case 'v': verbose = true; break; case 'w': outfile = optarg; quiet = true; break; case 'x': if(event_buffer_format != sinsp_evt::PF_NORMAL) { fprintf(stderr, "you cannot specify more than one output format\n"); delete inspector; return EXIT_SUCCESS; } event_buffer_format = sinsp_evt::PF_HEX; break; case 'X': if(event_buffer_format != sinsp_evt::PF_NORMAL) { fprintf(stderr, "you cannot specify more than one output format\n"); delete inspector; return EXIT_SUCCESS; } event_buffer_format = sinsp_evt::PF_HEXASCII; break; case 'z': compress = true; break; default: break; } } inspector->set_buffer_format(event_buffer_format); // // If -l was specified, print the fields and exit // if(list_flds) { if(verbose) { // // -ll shows the fields verbosely, i.e. with more information // like the type // list_fields(true); } else { list_fields(false); } res = EXIT_SUCCESS; goto exit; } string filter; // // the filter is at the end of the command line // if(optind + n_filterargs < argc) { #ifdef HAS_FILTERING for(int32_t j = optind + n_filterargs; j < argc; j++) { filter += argv[j]; if(j < argc) { filter += " "; } } if(is_filter_display) { display_filter = new sinsp_filter(inspector, filter); } #else fprintf(stderr, "filtering not compiled.\n"); res = EXIT_FAILURE; goto exit; #endif } if(signal(SIGINT, signal_callback) == SIG_ERR) { fprintf(stderr, "An error occurred while setting SIGINT signal handler.\n"); res = EXIT_FAILURE; goto exit; } if(signal(SIGTERM, signal_callback) == SIG_ERR) { fprintf(stderr, "An error occurred while setting SIGTERM signal handler.\n"); res = EXIT_FAILURE; goto exit; } // // Insert the right time format based on the -t flag // replace_in_place(output_format, "<TIME>", timefmt); // // Create the event formatter // sinsp_evt_formatter formatter(inspector, output_format); for(uint32_t j = 0; j < infiles.size() || infiles.size() == 0; j++) { #ifdef HAS_FILTERING if(filter.size() && !is_filter_display) { inspector->set_filter(filter); } #endif // // Launch the capture // bool open_success = true; if(infiles.size() != 0) { initialize_chisels(); // // We have a file to open // inspector->open(infiles[j]); } else { if(j > 0) { break; } initialize_chisels(); // // No file to open, this is a live capture // #if defined(HAS_CAPTURE) if(print_progress) { fprintf(stderr, "the -P flag cannot be used with live captures.\n"); res = EXIT_FAILURE; goto exit; } try { inspector->open(""); } catch(sinsp_exception e) { open_success = false; } #else // // Starting live capture // If this fails on Windows and OSX, don't try with any driver // inspector->open(""); #endif // // Starting the live capture failed, try to load the driver with // modprobe. // if(!open_success) { open_success = true; system("modprobe sysdig-probe > /dev/null 2> /dev/null"); inspector->open(""); } } if(snaplen != 0) { inspector->set_snaplen(snaplen); } duration = ((double)clock()) / CLOCKS_PER_SEC; if(outfile != "") { inspector->autodump_start(outfile, compress); } // // Notify the chisels that the capture is starting // chisels_on_capture_start(); cinfo = do_inspect(inspector, cnt, quiet, absolute_times, print_progress, display_filter, summary_table, &formatter); duration = ((double)clock()) / CLOCKS_PER_SEC - duration; scap_stats cstats; inspector->get_capture_stats(&cstats); if(verbose) { fprintf(stderr, "Driver Events:%" PRIu64 "\nDriver Drops:%" PRIu64 "\n", cstats.n_evts, cstats.n_drops); fprintf(stderr, "Elapsed time: %.3lf, Captured Events: %" PRIu64 ", %.2lf eps\n", duration, cinfo.m_nevts, (double)cinfo.m_nevts / duration); } // // Done. Close the capture. // inspector->close(); } } catch(sinsp_exception& e) { cerr << e.what() << endl; handle_end_of_file(print_progress); res = EXIT_FAILURE; } catch(...) { handle_end_of_file(print_progress); res = EXIT_FAILURE; } exit: // // If there's a summary table, sort and print it // if(summary_table != NULL) { print_summary_table(inspector, summary_table, 100); } free_chisels(); if(inspector) { delete inspector; } if(display_filter) { delete display_filter; } #ifdef _WIN32 _CrtDumpMemoryLeaks(); #endif return res; }
int main (int argc, char **argv) { const struct spwd *sp; uid_t ruid; gid_t rgid; const struct passwd *pw; /* * Get the program name so that error messages can use it. */ Prog = Basename (argv[0]); sanitize_env (); (void) setlocale (LC_ALL, ""); (void) bindtextdomain (PACKAGE, LOCALEDIR); (void) textdomain (PACKAGE); process_root_flag ("-R", argc, argv); #ifdef WITH_AUDIT audit_help_open (); #endif OPENLOG ("chage"); ruid = getuid (); rgid = getgid (); amroot = (ruid == 0); #ifdef WITH_SELINUX if (amroot && (is_selinux_enabled () > 0)) { amroot = (selinux_check_passwd_access (PASSWD__ROOTOK) == 0); } #endif process_flags (argc, argv); check_perms (); if (!spw_file_present ()) { fprintf (stderr, _("%s: the shadow password file is not present\n"), Prog); SYSLOG ((LOG_WARN, "can't find the shadow password file")); closelog (); exit (E_SHADOW_NOTFOUND); } open_files (lflg); /* Drop privileges */ if (lflg && ( (setregid (rgid, rgid) != 0) || (setreuid (ruid, ruid) != 0))) { fprintf (stderr, _("%s: failed to drop privileges (%s)\n"), Prog, strerror (errno)); fail_exit (E_NOPERM); } pw = pw_locate (argv[optind]); if (NULL == pw) { fprintf (stderr, _("%s: user '%s' does not exist in %s\n"), Prog, argv[optind], pw_dbname ()); closelog (); fail_exit (E_NOPERM); } STRFCPY (user_name, pw->pw_name); #ifdef WITH_TCB if (shadowtcb_set_user (pw->pw_name) == SHADOWTCB_FAILURE) { fail_exit (E_NOPERM); } #endif user_uid = pw->pw_uid; sp = spw_locate (argv[optind]); get_defaults (sp); /* * Print out the expiration fields if the user has requested the * list option. */ if (lflg) { if (!amroot && (ruid != user_uid)) { fprintf (stderr, _("%s: Permission denied.\n"), Prog); fail_exit (E_NOPERM); } #ifdef WITH_AUDIT audit_logger (AUDIT_USER_CHAUTHTOK, Prog, "display aging info", user_name, (unsigned int) user_uid, 1); #endif list_fields (); fail_exit (E_SUCCESS); } /* * If none of the fields were changed from the command line, let the * user interactively change them. */ if (!mflg && !Mflg && !dflg && !Wflg && !Iflg && !Eflg) { printf (_("Changing the aging information for %s\n"), user_name); if (new_fields () == 0) { fprintf (stderr, _("%s: error changing fields\n"), Prog); fail_exit (E_NOPERM); } #ifdef WITH_AUDIT else { audit_logger (AUDIT_USER_CHAUTHTOK, Prog, "change all aging information", user_name, (unsigned int) user_uid, 1); } #endif } else { #ifdef WITH_AUDIT if (Mflg) { audit_logger (AUDIT_USER_CHAUTHTOK, Prog, "change max age", user_name, (unsigned int) user_uid, 1); } if (mflg) { audit_logger (AUDIT_USER_CHAUTHTOK, Prog, "change min age", user_name, (unsigned int) user_uid, 1); } if (dflg) { audit_logger (AUDIT_USER_CHAUTHTOK, Prog, "change last change date", user_name, (unsigned int) user_uid, 1); } if (Wflg) { audit_logger (AUDIT_USER_CHAUTHTOK, Prog, "change passwd warning", user_name, (unsigned int) user_uid, 1); } if (Iflg) { audit_logger (AUDIT_USER_CHAUTHTOK, Prog, "change inactive days", user_name, (unsigned int) user_uid, 1); } if (Eflg) { audit_logger (AUDIT_USER_CHAUTHTOK, Prog, "change passwd expiration", user_name, (unsigned int) user_uid, 1); } #endif } update_age (sp, pw); close_files (); SYSLOG ((LOG_INFO, "changed password expiry for %s", user_name)); closelog (); exit (E_SUCCESS); }
int main(int argc, char **argv) { int error; my_bool first_argument_uses_wildcards=0; char *wild; MYSQL mysql; MY_INIT(argv[0]); sf_leaking_memory=1; /* don't report memory leaks on early exits */ if (load_defaults("my",load_default_groups,&argc,&argv)) exit(1); get_options(&argc,&argv); sf_leaking_memory=0; /* from now on we cleanup properly */ wild=0; if (argc) { char *pos= argv[argc-1], *to; for (to= pos ; *pos ; pos++, to++) { switch (*pos) { case '*': *pos= '%'; first_argument_uses_wildcards= 1; break; case '?': *pos= '_'; first_argument_uses_wildcards= 1; break; case '%': case '_': first_argument_uses_wildcards= 1; break; case '\\': pos++; default: break; } *to= *pos; } *to= *pos; /* just to copy a '\0' if '\\' was used */ } if (first_argument_uses_wildcards) wild= argv[--argc]; else if (argc == 3) /* We only want one field */ wild= argv[--argc]; if (argc > 2) { fprintf(stderr,"%s: Too many arguments\n",my_progname); exit(1); } mysql_init(&mysql); if (opt_compress) mysql_options(&mysql,MYSQL_OPT_COMPRESS,NullS); #ifdef HAVE_OPENSSL if (opt_use_ssl) mysql_ssl_set(&mysql, opt_ssl_key, opt_ssl_cert, opt_ssl_ca, opt_ssl_capath, opt_ssl_cipher); mysql_options(&mysql,MYSQL_OPT_SSL_VERIFY_SERVER_CERT, (char*)&opt_ssl_verify_server_cert); #endif if (opt_protocol) mysql_options(&mysql,MYSQL_OPT_PROTOCOL,(char*)&opt_protocol); #ifdef HAVE_SMEM if (shared_memory_base_name) mysql_options(&mysql,MYSQL_SHARED_MEMORY_BASE_NAME,shared_memory_base_name); #endif mysql_options(&mysql, MYSQL_SET_CHARSET_NAME, default_charset); if (opt_plugin_dir && *opt_plugin_dir) mysql_options(&mysql, MYSQL_PLUGIN_DIR, opt_plugin_dir); if (opt_default_auth && *opt_default_auth) mysql_options(&mysql, MYSQL_DEFAULT_AUTH, opt_default_auth); if (!(mysql_real_connect(&mysql,host,user,opt_password, (first_argument_uses_wildcards) ? "" : argv[0],opt_mysql_port,opt_mysql_unix_port, 0))) { fprintf(stderr,"%s: %s\n",my_progname,mysql_error(&mysql)); exit(1); } mysql.reconnect= 1; switch (argc) { case 0: error=list_dbs(&mysql,wild); break; case 1: if (opt_status) error=list_table_status(&mysql,argv[0],wild); else error=list_tables(&mysql,argv[0],wild); break; default: if (opt_status && ! wild) error=list_table_status(&mysql,argv[0],argv[1]); else error=list_fields(&mysql,argv[0],argv[1],wild); break; } mysql_close(&mysql); /* Close & free connection */ my_free(opt_password); #ifdef HAVE_SMEM my_free(shared_memory_base_name); #endif my_end(my_end_arg); exit(error ? 1 : 0); return 0; /* No compiler warnings */ }
sysdig_init_res csysdig_init(int argc, char **argv) { sysdig_init_res res; sinsp* inspector = NULL; vector<string> infiles; int op; uint64_t cnt = -1; uint32_t snaplen = 0; int long_index = 0; int32_t n_filterargs = 0; captureinfo cinfo; string errorstr; string display_view; bool print_containers = false; uint64_t refresh_interval_ns = 2000000000; bool list_flds = false; bool m_raw_output = false; static struct option long_options[] = { {"delay", required_argument, 0, 'd' }, {"exclude-users", no_argument, 0, 'E' }, {"help", no_argument, 0, 'h' }, {"list", optional_argument, 0, 'l' }, {"numevents", required_argument, 0, 'n' }, {"print", required_argument, 0, 'p' }, {"readfile", required_argument, 0, 'r' }, {"raw", no_argument, 0, 0 }, {"snaplen", required_argument, 0, 's' }, {"logfile", required_argument, 0, 0 }, {"view", required_argument, 0, 'v' }, {"version", no_argument, 0, 0 }, {0, 0, 0, 0} }; // // Parse the arguments // try { inspector = new sinsp(); #ifdef HAS_CHISELS add_chisel_dirs(inspector); #endif // // Parse the args // while((op = getopt_long(argc, argv, "d:EhlNn:p:r:s:v:", long_options, &long_index)) != -1) { switch(op) { case '?': // // Command line error // throw sinsp_exception("command line error"); break; case 'd': try { refresh_interval_ns = sinsp_numparser::parseu64(optarg) * 1000000; } catch(...) { throw sinsp_exception("can't parse the -d argument, make sure it's a number"); } if(refresh_interval_ns < 100000000) { throw sinsp_exception("Period must be bigger then 100ms"); } break; case 'E': inspector->set_import_users(false); break; case 'h': usage(); delete inspector; return sysdig_init_res(EXIT_SUCCESS); case 'l': list_flds = true; break; case 'N': inspector->set_hostname_and_port_resolution_mode(false); break; case 'n': try { cnt = sinsp_numparser::parseu64(optarg); } catch(...) { throw sinsp_exception("can't parse the -n argument, make sure it's a number"); } if(cnt <= 0) { throw sinsp_exception(string("invalid event count ") + optarg); res.m_res = EXIT_FAILURE; goto exit; } break; case 'p': if(string(optarg) == "c" || string(optarg) == "container") { inspector->set_print_container_data(true); print_containers = true; } break; case 'r': infiles.push_back(optarg); break; case 's': snaplen = atoi(optarg); break; case 'v': display_view = optarg; break; case 0: { if(long_options[long_index].flag != 0) { break; } string optname = string(long_options[long_index].name); if(optname == "version") { printf("sysdig version %s\n", SYSDIG_VERSION); delete inspector; return sysdig_init_res(EXIT_SUCCESS); } else if(optname == "logfile") { inspector->set_log_file(optarg); } else if(optname == "raw") { m_raw_output = true; } } break; default: break; } } string filter; // // If -l was specified, print the fields and exit // if(list_flds) { list_fields(false); res.m_res = EXIT_SUCCESS; goto exit; } // // the filter is at the end of the command line // if(optind + n_filterargs < argc) { #ifdef HAS_FILTERING for(int32_t j = optind + n_filterargs; j < argc; j++) { filter += argv[j]; if(j < argc) { filter += " "; } } #else fprintf(stderr, "filtering not compiled.\n"); res.m_res = EXIT_FAILURE; goto exit; #endif } if(signal(SIGINT, signal_callback) == SIG_ERR) { fprintf(stderr, "An error occurred while setting SIGINT signal handler.\n"); res.m_res = EXIT_FAILURE; goto exit; } if(signal(SIGTERM, signal_callback) == SIG_ERR) { fprintf(stderr, "An error occurred while setting SIGTERM signal handler.\n"); res.m_res = EXIT_FAILURE; goto exit; } // // Initialize ncurses // #ifndef NOCURSESUI if(!m_raw_output) { (void) initscr(); // initialize the curses library (void) nonl(); // tell curses not to do NL->CR/NL on output intrflush(stdscr, false); keypad(stdscr, true); curs_set(0); if (has_colors()) { start_color(); } use_default_colors(); mousemask(ALL_MOUSE_EVENTS, NULL); noecho(); timeout(0); // If this is uncommented, it's possible to natively handle stuff like CTRL+c //raw(); } #endif // // Create the list of views // sinsp_view_manager view_manager; // // Scan the chisel list to load the Lua views, and add them to the list // vector<chisel_desc> chlist; sinsp_chisel::get_chisel_list(&chlist); for(auto it : chlist) { if(it.m_viewinfo.m_valid) { if(print_containers) { it.m_viewinfo.apply_tag("containers"); } else { it.m_viewinfo.apply_tag("default"); } if(it.m_viewinfo.m_tags.size() != 0) { if(it.m_viewinfo.m_tags[0] == "Containers") { continue; } } view_manager.add(&it.m_viewinfo); } } // // Set the initial disply view // view_manager.set_selected_view(display_view); // // Go through the input sources and apply the processing to all of them // for(uint32_t j = 0; j < infiles.size() || infiles.size() == 0; j++) { // // Initialize the UI // sinsp_cursesui ui(inspector, (infiles.size() != 0)? infiles[0] : "", (filter.size() != 0)? filter : "", refresh_interval_ns, print_containers, m_raw_output); ui.configure(&view_manager); ui.start(false, false); // // Launch the capture // bool open_success = true; if(infiles.size() != 0) { // // We have a file to open // inspector->open(infiles[j]); } else { if(j > 0) { break; } // // No file to open, this is a live capture // #if defined(HAS_CAPTURE) try { inspector->open(""); } catch(sinsp_exception e) { open_success = false; } #else // // Starting live capture // If this fails on Windows and OSX, don't try with any driver // inspector->open(""); #endif // // Starting the live capture failed, try to load the driver with // modprobe. // if(!open_success) { open_success = true; if(system("modprobe sysdig-probe > /dev/null 2> /dev/null")) { fprintf(stderr, "Unable to load the driver\n"); } inspector->open(""); } // // Enable gathering the CPU from the kernel module // inspector->set_get_procs_cpu_from_driver(true); } // // If required, set the snaplen // if(snaplen != 0) { inspector->set_snaplen(snaplen); } // // Start the capture loop // cinfo = do_inspect(inspector, cnt, &ui); // // Done. Close the capture. // inspector->close(); } } catch(sinsp_capture_interrupt_exception&) { } catch(sinsp_exception& e) { errorstr = e.what(); res.m_res = EXIT_FAILURE; } catch(...) { errorstr = "uncatched exception"; res.m_res = EXIT_FAILURE; } exit: if(inspector) { delete inspector; } // // Restore the original screen // #ifndef NOCURSESUI if(!m_raw_output) { endwin(); } #endif if(errorstr != "") { cerr << errorstr << endl; } return res; }
/* *************************************************************************** * Read stats for current activity from file and write them. * * IN: * @ifd File descriptor of input file. * @fpos Position in file where reading must start. * @curr Index in array for current sample statistics. * @act_id Activity to display, or ~0 for all. * @file_actlst List of (known or unknown) activities in file. * @cpu_nr Number of processors for current activity data file. * @rectime Structure where timestamp (expressed in local time or in UTC * depending on whether option -t has been used or not) can be * saved for current record. * @loctime Structure where timestamp (expressed in local time) can be * saved for current record. * * OUT: * @curr Index in array for next sample statistics. * @cnt Number of lines of stats remaining to write. * @eosaf Set to TRUE if EOF (end of file) has been reached. * @reset Set to TRUE if last_uptime variable should be * reinitialized (used in next_slice() function). *************************************************************************** */ void rw_curr_act_stats(int ifd, off_t fpos, int *curr, long *cnt, int *eosaf, unsigned int act_id, int *reset, struct file_activity *file_actlst, __nr_t cpu_nr, struct tm *rectime, struct tm *loctime) { unsigned char rtype; int next; if (lseek(ifd, fpos, SEEK_SET) < fpos) { perror("lseek"); exit(2); } if (DISPLAY_FIELD_LIST(fmt[f_position]->options)) { /* Print field list */ list_fields(act_id); } /* * Restore the first stats collected. * Used to compute the rate displayed on the first line. */ copy_structures(act, id_seq, record_hdr, !*curr, 2); *cnt = count; do { /* Display <count> lines of stats */ *eosaf = sa_fread(ifd, &record_hdr[*curr], RECORD_HEADER_SIZE, SOFT_SIZE); rtype = record_hdr[*curr].record_type; if (!*eosaf && (rtype != R_RESTART) && (rtype != R_COMMENT)) { /* Read the extra fields since it's not a RESTART record */ read_file_stat_bunch(act, *curr, ifd, file_hdr.sa_nr_act, file_actlst); } if (!*eosaf && (rtype != R_RESTART)) { if (rtype == R_COMMENT) { sadf_print_special(*curr, tm_start.use, tm_end.use, R_COMMENT, ifd, rectime, loctime); continue; } next = write_parsable_stats(*curr, *reset, cnt, tm_start.use, tm_end.use, act_id, cpu_nr, rectime, loctime); if (next) { /* * next is set to 1 when we were close enough to desired interval. * In this case, the call to write_parsable_stats() has actually * displayed a line of stats. */ *curr ^=1; if (*cnt > 0) { (*cnt)--; } } *reset = FALSE; } } while (*cnt && !*eosaf && (rtype != R_RESTART)); *reset = TRUE; }
// // ARGUMENT PARSING AND PROGRAM SETUP // sysdig_init_res sysdig_init(int argc, char **argv) { sysdig_init_res res; sinsp* inspector = NULL; vector<string> infiles; string outfile; int op; uint64_t cnt = -1; bool quiet = false; bool is_filter_display = false; bool verbose = false; bool list_flds = false; bool print_progress = false; bool compress = false; sinsp_evt::param_fmt event_buffer_format = sinsp_evt::PF_NORMAL; sinsp_filter* display_filter = NULL; double duration = 1; captureinfo cinfo; string output_format; uint32_t snaplen = 0; int long_index = 0; int32_t n_filterargs = 0; int cflag = 0; bool jflag = false; string cname; vector<summary_table_entry>* summary_table = NULL; string timefmt = "%evt.time"; // These variables are for the cycle_writer engine int duration_seconds = 0; int rollover_mb = 0; int file_limit = 0; bool do_cycle = false; static struct option long_options[] = { {"print-ascii", no_argument, 0, 'A' }, {"print-base64", no_argument, 0, 'b' }, #ifdef HAS_CHISELS {"chisel", required_argument, 0, 'c' }, {"list-chisels", no_argument, &cflag, 1 }, #endif {"compress", no_argument, 0, 'z' }, {"displayflt", no_argument, 0, 'd' }, {"debug", no_argument, 0, 'D'}, {"fatfile", no_argument, 0, 'F'}, #ifndef DISABLE_CGW {"seconds", required_argument, 0, 'G' }, #endif {"help", no_argument, 0, 'h' }, #ifdef HAS_CHISELS {"chisel-info", required_argument, 0, 'i' }, #endif #ifndef DISABLE_CGW {"file-size", required_argument, 0, 'C' }, #endif {"json", no_argument, 0, 'j' }, {"list", no_argument, 0, 'l' }, {"list-events", no_argument, 0, 'L' }, {"numevents", required_argument, 0, 'n' }, {"progress", required_argument, 0, 'P' }, {"print", required_argument, 0, 'p' }, {"quiet", no_argument, 0, 'q' }, {"readfile", required_argument, 0, 'r' }, {"snaplen", required_argument, 0, 's' }, {"summary", no_argument, 0, 'S' }, {"timetype", required_argument, 0, 't' }, {"verbose", no_argument, 0, 'v' }, {"version", no_argument, 0, 0 }, {"writefile", required_argument, 0, 'w' }, #ifndef DISABLE_CGW {"limit", required_argument, 0, 'W' }, #endif {"print-hex", no_argument, 0, 'x'}, {"print-hex-ascii", no_argument, 0, 'X'}, {0, 0, 0, 0} }; output_format = "*%evt.num <TIME> %evt.cpu %proc.name (%thread.tid) %evt.dir %evt.type %evt.info"; // output_format = DEFAULT_OUTPUT_STR; try { inspector = new sinsp(); #ifdef HAS_CHISELS add_chisel_dirs(inspector); #endif // // Parse the args // while((op = getopt_long(argc, argv, "Abc:" #ifndef DISABLE_CGW "C:" #endif "dDF" #ifndef DISABLE_CGW "G:" #endif "hi:jlLn:Pp:qr:Ss:t:v" #ifndef DISABLE_CGW "W:" #endif "w:xXz", long_options, &long_index)) != -1) { switch(op) { case 'A': if(event_buffer_format != sinsp_evt::PF_NORMAL) { fprintf(stderr, "you cannot specify more than one output format\n"); delete inspector; return sysdig_init_res(EXIT_SUCCESS); } event_buffer_format = sinsp_evt::PF_EOLS; break; case 'b': if(event_buffer_format != sinsp_evt::PF_NORMAL) { fprintf(stderr, "you cannot specify more than one output format\n"); delete inspector; return sysdig_init_res(EXIT_SUCCESS); } event_buffer_format = sinsp_evt::PF_BASE64; break; case 0: if(cflag != 1 && cflag != 2) { break; } if(cflag == 2) { cname = optarg; } #ifdef HAS_CHISELS case 'c': { if(cflag == 0) { string ostr(optarg); if(ostr.size() >= 1) { if(ostr == "l") { cflag = 1; } } } if(cflag == 1) { vector<chisel_desc> chlist; sinsp_chisel::get_chisel_list(&chlist); list_chisels(&chlist, true); delete inspector; return sysdig_init_res(EXIT_SUCCESS); } sinsp_chisel* ch = new sinsp_chisel(inspector, optarg); parse_chisel_args(ch, inspector, optind, argc, argv, &n_filterargs); g_chisels.push_back(ch); } #endif break; #ifndef DISABLE_CGW // File-size case 'C': rollover_mb = atoi(optarg); if(rollover_mb <= 0) { throw sinsp_exception(string("invalid file size") + optarg); res.m_res = EXIT_FAILURE; goto exit; } // -C always implicates a cycle do_cycle = true; break; #endif case 'D': inspector->set_debug_mode(true); break; case 'F': inspector->set_fatfile_dump_mode(true); break; #ifndef DISABLE_CGW // Number of seconds between roll-over case 'G': duration_seconds = atoi(optarg); if(duration_seconds <= 0) { throw sinsp_exception(string("invalid duration") + optarg); res.m_res = EXIT_FAILURE; goto exit; } break; #endif #ifdef HAS_CHISELS // --chisel-info and -i case 'i': { cname = optarg; vector<chisel_desc> chlist; sinsp_chisel::get_chisel_list(&chlist); for(uint32_t j = 0; j < chlist.size(); j++) { if(chlist[j].m_name == cname) { print_chisel_info(&chlist[j]); delete inspector; return sysdig_init_res(EXIT_SUCCESS); } } throw sinsp_exception("chisel " + cname + " not found - use -cl to list them."); } break; #endif case 'd': is_filter_display = true; break; case 'j': // // set the json flag to 1 for now, the data format will depend from the print format parameters // jflag = true; break; case 'h': usage(); delete inspector; return sysdig_init_res(EXIT_SUCCESS); case 'l': list_flds = true; break; case 'L': list_events(inspector); delete inspector; return sysdig_init_res(EXIT_SUCCESS); case 'n': cnt = atoi(optarg); if(cnt <= 0) { throw sinsp_exception(string("invalid event count ") + optarg); res.m_res = EXIT_FAILURE; goto exit; } break; case 'P': print_progress = true; break; case 'p': if(string(optarg) == "p") { // // -pp shows the default output format, useful if the user wants to tweak it. // replace_in_place(output_format, "<TIME>", timefmt); printf("%s\n", output_format.c_str()); delete inspector; return sysdig_init_res(EXIT_SUCCESS); } else { output_format = optarg; } break; case 'q': quiet = true; break; case 'r': infiles.push_back(optarg); break; case 'S': summary_table = new vector<summary_table_entry>; for(uint32_t j = 0; j < PPM_EVENT_MAX; j++) { summary_table->push_back(summary_table_entry(j, false)); } for(uint32_t j = 0; j < PPM_SC_MAX * 2; j++) { summary_table->push_back(summary_table_entry(j, true)); } break; case 's': snaplen = atoi(optarg); break; case 't': { string tms(optarg); if(tms == "h") { timefmt = "%evt.time"; } else if(tms == "a") { timefmt = "%evt.rawtime.s.%evt.rawtime.ns"; } else if(tms == "r") { timefmt = "%evt.reltime.s.%evt.reltime.ns"; } else if(tms == "d") { timefmt = "%evt.latency.s.%evt.latency.ns"; } else if(tms == "D") { timefmt = "%evt.deltatime.s.%evt.deltatime.ns"; } else { fprintf(stderr, "invalid modifier for flag -t\n"); delete inspector; return sysdig_init_res(EXIT_FAILURE); } } break; case 'v': verbose = true; break; case 'w': outfile = optarg; quiet = true; break; #ifndef DISABLE_CGW // Number of capture files to cycle through case 'W': file_limit = atoi(optarg); if(file_limit <= 0) { throw sinsp_exception(string("invalid file limit") + optarg); res.m_res = EXIT_FAILURE; goto exit; } break; #endif case 'x': if(event_buffer_format != sinsp_evt::PF_NORMAL) { fprintf(stderr, "you cannot specify more than one output format\n"); delete inspector; return sysdig_init_res(EXIT_FAILURE); } event_buffer_format = sinsp_evt::PF_HEX; break; case 'X': if(event_buffer_format != sinsp_evt::PF_NORMAL) { fprintf(stderr, "you cannot specify more than one output format\n"); delete inspector; return sysdig_init_res(EXIT_FAILURE); } event_buffer_format = sinsp_evt::PF_HEXASCII; break; case 'z': compress = true; break; default: break; } if(string(long_options[long_index].name) == "version") { printf("sysdig version %s\n", SYSDIG_VERSION); delete inspector; return sysdig_init_res(EXIT_SUCCESS); } } // // If -j was specified the event_buffer_format must be rewritten to account for it // if(jflag) { switch (event_buffer_format) { case sinsp_evt::PF_NORMAL: event_buffer_format = sinsp_evt::PF_JSON; break; case sinsp_evt::PF_EOLS: event_buffer_format = sinsp_evt::PF_JSONEOLS; break; case sinsp_evt::PF_HEX: event_buffer_format = sinsp_evt::PF_JSONHEX; break; case sinsp_evt::PF_HEXASCII: event_buffer_format = sinsp_evt::PF_JSONHEXASCII; break; case sinsp_evt::PF_BASE64: event_buffer_format = sinsp_evt::PF_JSONBASE64; break; default: // do nothing break; } } inspector->set_buffer_format(event_buffer_format); // // If -l was specified, print the fields and exit // if(list_flds) { if(verbose) { // // -ll shows the fields verbosely, i.e. with more information // like the type // list_fields(true); } else { list_fields(false); } res.m_res = EXIT_SUCCESS; goto exit; } string filter; // // the filter is at the end of the command line // if(optind + n_filterargs < argc) { #ifdef HAS_FILTERING for(int32_t j = optind + n_filterargs; j < argc; j++) { filter += argv[j]; if(j < argc) { filter += " "; } } if(is_filter_display) { display_filter = new sinsp_filter(inspector, filter); } #else fprintf(stderr, "filtering not compiled.\n"); res.m_res = EXIT_FAILURE; goto exit; #endif } if(signal(SIGINT, signal_callback) == SIG_ERR) { fprintf(stderr, "An error occurred while setting SIGINT signal handler.\n"); res.m_res = EXIT_FAILURE; goto exit; } if(signal(SIGTERM, signal_callback) == SIG_ERR) { fprintf(stderr, "An error occurred while setting SIGTERM signal handler.\n"); res.m_res = EXIT_FAILURE; goto exit; } // // Insert the right time format based on the -t flag // replace_in_place(output_format, "<TIME>", timefmt); // // Create the event formatter // sinsp_evt_formatter formatter(inspector, output_format); for(uint32_t j = 0; j < infiles.size() || infiles.size() == 0; j++) { #ifdef HAS_FILTERING if(filter.size() && !is_filter_display) { inspector->set_filter(filter); } #endif // // Launch the capture // bool open_success = true; if(infiles.size() != 0) { initialize_chisels(); // // We have a file to open // inspector->open(infiles[j]); } else { if(j > 0) { break; } initialize_chisels(); // // No file to open, this is a live capture // #if defined(HAS_CAPTURE) if(print_progress) { fprintf(stderr, "the -P flag cannot be used with live captures.\n"); res.m_res = EXIT_FAILURE; goto exit; } try { inspector->open(""); } catch(sinsp_exception e) { open_success = false; } #else // // Starting live capture // If this fails on Windows and OSX, don't try with any driver // inspector->open(""); #endif // // Starting the live capture failed, try to load the driver with // modprobe. // if(!open_success) { open_success = true; system("modprobe sysdig-probe > /dev/null 2> /dev/null"); inspector->open(""); } } if(snaplen != 0) { inspector->set_snaplen(snaplen); } duration = ((double)clock()) / CLOCKS_PER_SEC; if(outfile != "") { inspector->setup_cycle_writer(outfile, rollover_mb, duration_seconds, file_limit, do_cycle, compress); inspector->autodump_next_file(); } // // Notify the chisels that the capture is starting // chisels_on_capture_start(); cinfo = do_inspect(inspector, cnt, quiet, jflag, print_progress, display_filter, summary_table, &formatter); duration = ((double)clock()) / CLOCKS_PER_SEC - duration; scap_stats cstats; inspector->get_capture_stats(&cstats); if(verbose) { fprintf(stderr, "Driver Events:%" PRIu64 "\nDriver Drops:%" PRIu64 "\n", cstats.n_evts, cstats.n_drops); fprintf(stderr, "Elapsed time: %.3lf, Captured Events: %" PRIu64 ", %.2lf eps\n", duration, cinfo.m_nevts, (double)cinfo.m_nevts / duration); } // // Done. Close the capture. // inspector->close(); } } catch(sinsp_capture_interrupt_exception&) { handle_end_of_file(print_progress); } catch(sinsp_exception& e) { cerr << e.what() << endl; handle_end_of_file(print_progress); res.m_res = EXIT_FAILURE; } catch(...) { handle_end_of_file(print_progress); res.m_res = EXIT_FAILURE; } exit: // // If any of the chisels is requesting another run, // for(vector<sinsp_chisel*>::iterator it = g_chisels.begin(); it != g_chisels.end(); ++it) { string na; if((*it)->get_nextrun_args(&na)) { res.m_next_run_args = sinsp_split(na, ' '); } } // // If there's a summary table, sort and print it // if(summary_table != NULL) { print_summary_table(inspector, summary_table, 100); } // // Free all the stuff that was allocated // free_chisels(); if(inspector) { delete inspector; } if(display_filter) { delete display_filter; } return res; }
int main(int argc, char * const *argv) { struct VSM_data *vd; double t_arg = 5.0, t_start = NAN; int once = 0, xml = 0, json = 0, f_list = 0, curses = 0; signed char opt; int i; VUT_Init(progname, argc, argv, &vopt_spec); vd = VSM_New(); AN(vd); while ((opt = getopt(argc, argv, vopt_spec.vopt_optstring)) != -1) { switch (opt) { case '1': once = 1; break; case 'h': /* Usage help */ usage(0); case 'l': f_list = 1; break; case 't': if (!strcasecmp(optarg, "off")) t_arg = -1.; else { t_arg = VNUM(optarg); if (isnan(t_arg)) VUT_Error(1, "-t: Syntax error"); if (t_arg < 0.) VUT_Error(1, "-t: Range error"); } break; case 'V': VCS_Message("varnishstat"); exit(0); case 'x': xml = 1; break; case 'j': json = 1; break; default: i = VSC_Arg(vd, opt, optarg); if (i < 0) VUT_Error(1, "%s", VSM_Error(vd)); if (!i) usage(1); } } if (optind != argc) usage(1); if (!(xml || json || once || f_list)) curses = 1; while (1) { i = VSM_Open(vd); if (!i) break; if (isnan(t_start) && t_arg > 0.) { fprintf(stderr, "Can't open log -" " retrying for %.0f seconds\n", t_arg); t_start = VTIM_real(); } if (t_arg <= 0.) break; if (VTIM_real() - t_start > t_arg) break; VSM_ResetError(vd); VTIM_sleep(0.5); } if (curses) { if (i && t_arg >= 0.) VUT_Error(1, "%s", VSM_Error(vd)); do_curses(vd, 1.0); exit(0); } if (i) VUT_Error(1, "%s", VSM_Error(vd)); if (xml) do_xml(vd); else if (json) do_json(vd); else if (once) do_once(vd); else if (f_list) list_fields(vd); else assert(0); exit(0); }