/* Editor Settings: expandtabs and use 4 spaces for indentation * ex: set softtabstop=4 tabstop=8 expandtab shiftwidth=4: * * -*- mode: c, c-basic-offset: 4 -*- */ /* * Copyright Likewise Software 2004-2008 * 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, see * . * * LIKEWISE SOFTWARE MAKES THIS SOFTWARE AVAILABLE UNDER OTHER LICENSING * TERMS AS WELL. IF YOU HAVE ENTERED INTO A SEPARATE LICENSE AGREEMENT * WITH LIKEWISE SOFTWARE, THEN YOU MAY ELECT TO USE THE SOFTWARE UNDER THE * TERMS OF THAT SOFTWARE LICENSE AGREEMENT INSTEAD OF THE TERMS OF THE GNU * GENERAL PUBLIC LICENSE, NOTWITHSTANDING THE ABOVE NOTICE. IF YOU * HAVE QUESTIONS, OR WISH TO REQUEST A COPY OF THE ALTERNATE LICENSING * TERMS OFFERED BY LIKEWISE SOFTWARE, PLEASE CONTACT LIKEWISE SOFTWARE AT * license@likewisesoftware.com */ /* * Copyright (C) Centeris Corporation 2004-2007 * Copyright (C) Likewise Software 2007 * All rights reserved. * * Authors: Krishna Ganugapati (krishnag@likewisesoftware.com) * Sriram Nambakam (snambakam@likewisesoftware.com) * * Eventlog utility that retrieves events over RPC from the Eventlog service. * */ #include "includes.h" #ifndef _POSIX_PTHREAD_SEMANTICS #define _POSIX_PTHREAD_SEMANTICS 1 #endif #define ACTION_NONE 0 #define ACTION_SHOW 1 #define ACTION_TABLE 2 #define ACTION_COUNT 3 #define ACTION_EXPORT 4 #define ACTION_DELETE 5 #define ACTION_LAST 6 #define TRY DCETHREAD_TRY #define CATCH_ALL DCETHREAD_CATCH_ALL(THIS_CATCH) #define ENDTRY DCETHREAD_ENDTRY static void ShowUsage() { printf("Usage: lw-eventlog-cli [-h] | { [-s [|-]] | [-c [|-]] | [-t [ | -]]\n"); printf(" | [-e [|-]] | [-d [|-]] } \n\n"); printf("\t-h\tShow help\n"); printf("\t-s\tShows a detailed, human-readable listing of the records matching sql_filter, or - for all records.\n"); printf("\t-t\tShows a summary table of the records matching sql_filter, or - for all records.\n"); printf("\t-c\tShows a count of the number of records matching sql_filter, or - for all records.\n"); printf("\t-e\tExports CSV data from the database to the given path, or - to print to the command line\n"); printf("\t-d\tDeletes the records matching sql_filter, or - to delete all records, re-initializing the database\n"); printf("\nExamples:\n"); printf("\tPrints details for events 1-10:\n"); printf("\tlw-eventlog-cli -s 1-10 127.0.0.1\n\n"); printf("\tPrints table for all events:\n"); printf("\tlw-eventlog-cli -t - 127.0.0.1\n\n"); printf("\tCount all events matching the SQL WHILE expression:\n"); printf("\tlw-eventlog-cli -c \"(EventRecordId < 1000) AND (EventType = 'Warning')\" 127.0.0.1\n"); printf("\n"); printf("Valid Field Names:\n"); printf("\tEventTableCategoryId (integer)\n"); printf("\tEventRecordId (integer)\n"); printf("\tEventType (varchar(128))\n"); printf("\tEventTime (integer - seconds since Jan. 1 1970)\n"); printf("\tEventSource (varchar(256))\n"); printf("\tEventCategory (varchar(128))\n"); printf("\tEventSourceId (integer)\n"); printf("\tUser (varchar(128))\n"); printf("\tComputer (varchar(128))\n"); printf("\tDescription (TEXT))\n\n"); printf("\tData (varchar(128))\n\n"); } DWORD AddEventRecord( PEVENT_LOG_HANDLE pEventLogHandle, EVENT_LOG_RECORD eventRecord ) { return LWIWriteEventLogBase((HANDLE)pEventLogHandle, eventRecord); } static DWORD ParseArgs( int argc, char* argv[], PDWORD action, char** pstrArgCopy, PSTR ipAddress, PSTR *ppszEventTableCategoryId, PBOOLEAN pbEventTableCategoryIdInCSV) { int iArg = 1; DWORD maxIndex = argc-1; PSTR pszArg = NULL; PSTR pstrArgLocal = NULL; DWORD dwError = 0; DWORD actionLocal = 0; PSTR pszEventTableCategoryId = 0; BOOLEAN bEventTableCategoryIdInCSV = TRUE; if (iArg > maxIndex || maxIndex > 8) { ShowUsage(); exit(0); } pszArg = argv[iArg++]; if (pszArg == NULL || *pszArg == '\0') { ShowUsage(); exit(0); } else if ((strcmp(pszArg, "--help") == 0) || (strcmp(pszArg, "-h") == 0)) { ShowUsage(); exit(0); } else if (strcmp(pszArg, "-s") == 0) { actionLocal = ACTION_SHOW; } else if (strcmp(pszArg, "-t") == 0) { actionLocal = ACTION_TABLE; } else if (strcmp(pszArg, "-c") == 0) { actionLocal = ACTION_COUNT; } else if (strcmp(pszArg, "-e") == 0) { actionLocal = ACTION_EXPORT; } else if (strcmp(pszArg, "-d") == 0) { actionLocal = ACTION_DELETE; } else { ShowUsage(); exit(0); } if (iArg > maxIndex) { ShowUsage(); exit(0); } pszArg = argv[iArg++]; if (pszArg == NULL || *pszArg == '\0') { ShowUsage(); exit(0); } else { dwError = EVTAllocateMemory(strlen(pszArg)+1, (PVOID*)(&pstrArgLocal)); BAIL_ON_EVT_ERROR(dwError); strcpy(pstrArgLocal, pszArg); } while (iArg+2 <= maxIndex) { pszArg = argv[iArg++]; if (pszArg == NULL || *pszArg == '\0') { ShowUsage(); exit(0); } else { ShowUsage(); exit(0); } } pszArg = argv[iArg++]; if (pszArg == NULL || *pszArg == '\0') { ShowUsage(); exit(0); } else { strcpy(ipAddress, pszArg); } *action = actionLocal; *pstrArgCopy = pstrArgLocal; *ppszEventTableCategoryId = pszEventTableCategoryId; *pbEventTableCategoryIdInCSV = bEventTableCategoryIdInCSV; error: return dwError; } int main( int argc, char* argv[] ) { DWORD dwError = 0; PEVENT_LOG_HANDLE pEventLogHandle = NULL; EVENT_LOG_RECORD* eventRecords = NULL; DWORD nRecords = 0; DWORD currentRecord = 0; DWORD nRecordsPerPage = 500; PSTR pszEventTableCategoryId = NULL; BOOLEAN bEventTableCategoryIdInCSV = FALSE; char ipAddress[256]; char* sqlFilterChar = NULL; char* sqlFilterCharDefault = "eventRecordId >= 0"; PSTR argCopy = NULL; DWORD action = ACTION_NONE; dwError = EVTInitLoggingToFile( LOG_LEVEL_ERROR, NULL); BAIL_ON_EVT_ERROR(dwError); dwError = ParseArgs( argc, argv, &action, &argCopy, ipAddress, &pszEventTableCategoryId, &bEventTableCategoryIdInCSV); BAIL_ON_EVT_ERROR(dwError); if (action <= ACTION_NONE || action > ACTION_LAST) { EVT_LOG_VERBOSE("Invalid action: %d\n", action); ShowUsage(); exit(0); } TRY { dwError = LWIOpenEventLog(ipAddress, (PHANDLE)&pEventLogHandle); BAIL_ON_EVT_ERROR(dwError); if (action == ACTION_EXPORT) { FILE* fpExport = NULL; if (strcmp(argCopy, "-") == 0) { fpExport = stdout; } else { fpExport = fopen(argCopy, "w"); } if (fpExport != NULL) { dwError = ReadAndExportEvents(pEventLogHandle, fpExport); } else { dwError = -1; EVT_LOG_VERBOSE("Unable to open file %s for writing.\n", argCopy); } BAIL_ON_EVT_ERROR(dwError); } else { if (argCopy == NULL || *argCopy == '\0' || strcmp(argCopy, "-") == 0) { sqlFilterChar = sqlFilterCharDefault; } else { DWORD startID = 0; DWORD endID = 0; int nRead = 0; nRead = sscanf(argCopy, "%d-%d", &startID, &endID); if ((nRead == 0) || (nRead == EOF)) { printf("Error: An invalid event record range [%s] " "was specified.\n", argCopy); dwError = EVT_ERROR_INVALID_PARAMETER; BAIL_ON_EVT_ERROR(dwError); } if (startID > 0) { dwError = EVTAllocateMemory(256, (PVOID*)(&sqlFilterChar)); BAIL_ON_EVT_ERROR(dwError); if (endID > 0 && endID > startID) { sprintf(sqlFilterChar, "EventRecordId >= %d AND EventRecordID <= %d", startID, endID); } else { sprintf(sqlFilterChar, "EventRecordId = %d", startID); } } else { sqlFilterChar = argCopy; } } wchar16_t* sqlFilter = NULL; dwError = EVTAllocateMemory(sizeof(wchar16_t)*(1+strlen(sqlFilterChar)), (PVOID*)(&sqlFilter)); BAIL_ON_EVT_ERROR(dwError); sw16printf(sqlFilter, "%s", sqlFilterChar); if (action == ACTION_COUNT) { dwError = LWICountEventLog((HANDLE)pEventLogHandle, sqlFilter, &nRecords); BAIL_ON_EVT_ERROR(dwError); printf("%d records found in database\n", nRecords); } else if (action == ACTION_SHOW) { do { dwError = LWIReadEventLog((HANDLE)pEventLogHandle, currentRecord, nRecordsPerPage, sqlFilter, &nRecords, &eventRecords); BAIL_ON_EVT_ERROR(dwError); PrintEventRecords(stdout, eventRecords, nRecords, ¤tRecord); } while (nRecords == nRecordsPerPage && nRecords > 0); } else if (action == ACTION_TABLE) { do { dwError = LWIReadEventLog((HANDLE)pEventLogHandle, currentRecord, nRecordsPerPage, sqlFilter, &nRecords, &eventRecords); BAIL_ON_EVT_ERROR(dwError); PrintEventRecordsTable(stdout, eventRecords, nRecords, ¤tRecord); } while (nRecords == nRecordsPerPage && nRecords > 0); } else if (action == ACTION_DELETE) { if (strcmp(sqlFilterChar, sqlFilterCharDefault) == 0) { //This is probably a faster way of deleting //everything, because it drops the //table instead of running an SQL DELETE dwError = LWIClearEventLog((HANDLE)pEventLogHandle); } else { dwError = LWIDeleteFromEventLog( (HANDLE)pEventLogHandle, sqlFilter ); } BAIL_ON_EVT_ERROR(dwError); } else { EVT_LOG_VERBOSE("Invalid action: %d\n", action); ShowUsage(); exit(0); } } //end else } //end TRY CATCH_ALL { dwError = dcethread_exc_getstatus (THIS_CATCH); EVT_LOG_ERROR("Invalid Operation: %d\n", dwError); } ENDTRY; error: if (dwError != 0) { EVT_LOG_ERROR("The operation failed with error code [%d]\n", dwError); } if (sqlFilterChar != NULL && sqlFilterChar != sqlFilterCharDefault) { EVTFreeMemory(sqlFilterChar); } if (pEventLogHandle) { LWICloseEventLog((HANDLE)pEventLogHandle); } if (eventRecords) { RPCFreeMemory(eventRecords); EVTFreeMemory(eventRecords); } return dwError; }