/*
 * $Header: /home/gene/library/website/docsrc/wel/src/RCS/insert-log.c,v 395.1 2008/04/20 17:25:48 gene Exp $
 *
 * Copyright (c) 2005 Gene Michael Stover.  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., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301
 * USA
 */

#include "this.h"

/*
 */
enum { ACTION_HELP, ACTION_RUN };
static int S_action = ACTION_RUN;

/*
 */
static char *S_source = "Application";
static WORD S_eventType = EVENTLOG_INFORMATION_TYPE;
static WORD S_category = 0;
static DWORD S_eventId = 0;

/*
 */
static int
S_CommandLine (int argc, char *argv[])
{
  int rc = 0, c;
  unsigned u;
  unsigned long ul;

  while (rc == 0 && (c = getopt (argc, argv, "c:hi:s:t:")) != EOF) {
    switch (c) {
    case 'c':
      if (sscanf (optarg, "%u", &u) == 1) {
	S_category = (WORD) u;
      } else {
	fprintf (stderr, "\n%s:%d:", __FILE__, __LINE__);
	fprintf (stderr, " Cannot parse \"%s\" into an", optarg);
	fprintf (stderr, " unsigned integer to be the event category.");
	rc = 38;
      }
      break;
    case 'h':
      S_action = ACTION_HELP;
      break;
    case 'i':
      if (sscanf (optarg, "%lu", &ul) == 1) {
	S_eventId = ul;
      } else {
	fprintf (stderr, "\n%s:%d:", __FILE__, __LINE__);
	fprintf (stderr, " Cannot parse \"%s\" into an", optarg);
	fprintf (stderr, " unsigned long integer to be the event id.");
	rc = 38;
      }
      break;
    case 's':
      S_source = optarg;
      break;
    case 't':
      if (stricmp (optarg, "EVENTLOG_SUCCESS") == 0) {
	S_eventType = EVENTLOG_SUCCESS;
      } else if (stricmp (optarg, "EVENTLOG_AUDIT_FAILURE") == 0) {
	S_eventType = EVENTLOG_AUDIT_FAILURE;
      } else if (stricmp (optarg, "EVENTLOG_AUDIT_SUCCESS") == 0) {
	S_eventType = EVENTLOG_AUDIT_SUCCESS;
      } else if (stricmp (optarg, "EVENTLOG_ERROR_TYPE") == 0) {
	S_eventType = EVENTLOG_ERROR_TYPE;
      } else if (stricmp (optarg, "EVENTLOG_INFORMATION_TYPE") == 0) {
	S_eventType = EVENTLOG_INFORMATION_TYPE;
      } else if (stricmp (optarg, "EVENTLOG_WARNING_TYPE") == 0) {
	S_eventType = EVENTLOG_WARNING_TYPE;
      } else {
	fprintf (stderr, "\n%s:%d:", __FILE__, __LINE__);
	fprintf (stderr, " Unknown event type, \"%s\".", optarg);
	rc = -33;
      }
      break;
    case ':':
      fprintf (stderr, "\n%s:%d:", __FILE__, __LINE__);
      fprintf (stderr, " getopt returned '%c'.", c);
      fprintf (stderr, "  Missing argument to an option which requires");
      fprintf (stderr, " an argument?");
      rc = 101;
      break;
    case '?':
      fprintf (stderr, "\n%s:%d:", __FILE__, __LINE__);
      fprintf (stderr, " getopt returned '%c'.", c);
      fprintf (stderr, "  Unrecognized command line option?");
      rc = -54;
      break;
    default:
      fprintf (stderr, "\n%s:%d:", __FILE__, __LINE__);
      fprintf (stderr, " getopt returned '%c'.", c);
      fprintf (stderr, "  This is a really weird error.");
      rc = 22;
      break;
    }
  }
  if (rc == 0) {
    while (optind < argc) {
      fprintf (stderr, "\n%s:%d:", __FILE__, __LINE__);
      fprintf (stderr, " Ignoring argv[%d] \"%s\"", optind, argv[optind]);
      ++optind;
    }
  }
  return rc;
}

/*
 * Read one line from standard input.  Return it in a dynamically
 * allocated string.  Remove end-of-line character(s) from the
 * string.
 */
static char *
S_ReadLine ()
{
  char *line;
  int count, sz;

  count = 1024;                         /* character count */
  sz = count * sizeof *line;            /* octets */
  line = (char *) xmalloc (sz);
  if (fgets (line, sz, stdin) == line) {
    /* Remove end-of-line character(s). */
    while (strlen(line) > 0 &&
           (line[strlen(line)-1] == '\n' || line[strlen(line)-1] == '\r')) {
      line[strlen(line)-1] = '\0';
    }
  } else {
    line = (char *) xfree (line);
  }
  return line;
}

/*
 */
static int
S_Insert (HANDLE hnd)
{
  int rc = 0;
  SID *sid = NULL;
  char *line;

  line = S_ReadLine ();
  if (line != NULL) {
    if (ReportEvent (hnd, S_eventType, S_category, S_eventId, sid,
		     1,               /* number of strings, always 1 for now */
		     0,
		     &line,
		     NULL)) {
      /* good */
    } else {
      LOG_LastError ("ReportEvent", __FILE__, __LINE__);
      fprintf (stderr, "\n%s:%d: ReportEvent failed", __FILE__, __LINE__);
      rc = 43;
    }
    line = (char *) xfree (line);
  } else {
    fprintf (stderr, "\n%s:%d: Can't read string from stdin", __FILE__,
	     __LINE__);
    rc = 46;
  }
  return rc;
}

/*
 */
static int
S_Run ()
{
  int rc = 0;
  HANDLE hnd;

  hnd = RegisterEventSource (NULL, S_source);
  if (hnd != NULL) {
    if (S_Insert (hnd) == 0) {
      /* good */
    } else {
      fprintf (stderr, "\n%s:%d: S_Insert failed", __FILE__, __LINE__);
      rc = 33;
    }
    CloseEventLog (hnd);
  } else {
    LOG_LastError ("RegisterEventSource", __FILE__, __LINE__);
    fprintf (stderr, "\n%s:%d:", __FILE__, __LINE__);
    fprintf (stderr, "RegisterEventSource failed.  Source is");
    fprintf (stderr, " \"%s\".", S_source);
    rc = -37;
  }
  return rc;
}

/*
 */
static void
S_Help (char progname[])
{
  printf ("\n   %s",
          "$Id: insert-log.c,v 395.1 2008/04/20 17:25:48 gene Exp $");
  printf ("\n   Copyright (c) 2005 Gene Michael Stover.  All rights");
  printf (" reserved.");
  printf ("\n");
  printf ("\n%s : insert a simple record into the Windows Event Log",
          progname == NULL ? "insert-log" : progname);
  printf ("\n%s [-c CATEGORY] [-h] [-i EVENTID] [-s SOURCE] [-t EVENTTYPE]",
          progname == NULL ? "insert-log" : progname);
  printf ("\nComplete instructions, executable files, & source code are at");
  printf ("\n<http://cybertiggyr.com/gene/wel/>.");
  printf ("\n");
}

/*
 */
static int
S_Dispatch (int action, char progname[])
{
  int rc = 0;

  switch (action) {
  case ACTION_HELP: S_Help (progname); break;
  case ACTION_RUN: rc = S_Run (); break;
  default:
    fprintf (stderr, "\n%s:%d:", __FILE__, __LINE__);
    fprintf (stderr, " Action is %d. ", action);
    fprintf (stderr, " This should never happen.");
    rc = 3;
  }
  return rc;
}

/*
 */
int
main (int argc, char *argv[])
{
  int rc = 0;

  if (S_CommandLine (argc, argv) == 0) {
    if (S_Dispatch (S_action, argv[0]) == 0) {
      /* good */
    } else {
      fprintf (stderr, "\n%s:%d: S_Dispatch failed", __FILE__, __LINE__);
      rc = 234;
    }
  } else {
    fprintf (stderr, "\n%s:%d: S_CommandLine failed", __FILE__, __LINE__);
    rc = 23;
  }
  return rc == 0 ? EXIT_SUCCESS : EXIT_FAILURE;
}

/* --- end of file --- */
