/*
 * rlogger.c 
 *
 * log a msg to a remote syslog daemon
 *
 * rlogger [destip] [facility] [level] [ident] ["message"]
 *
 * see /usr/include/sys/syslog.h for facility and priority codes.
 *
 * jeff murphy (jcmurphy@smurfland.cit.buffalo.edu)
 * 110494
 */
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <sys/syslog.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>

void Usage(char *);
int  LogCode(char *, char*);

#ifndef LOG_NPRIORITIES
#define LOG_NPRIORITIES 7
#endif

struct {
  char *word;
  int   level;
} sl_levs[] = { 
  "LOG_EMERG", 0, 
  "LOG_ALERT", 1,
  "LOG_CRIT", 2,
  "LOG_ERR", 3,
  "LOG_WARNING", 4, 
  "LOG_NOTICE", 5,
  "LOG_INFO", 6,
  "LOG_DEBUG", 7, 
  "", -1
};

struct {
  char *word;
  int   level;
} sl_facs[] = { 
 "LOG_KERN", 0,
 "LOG_USER", 1,
 "LOG_MAIL", 2, 
 "LOG_DAEMON", 3,
 "LOG_AUTH", 4, 
 "LOG_SYSLOG", 5, 
 "LOG_LPR", 6, 
 "LOG_NEWS", 7, 
 "LOG_UUCP", 8, 
 "LOG_CRON", 15,
 "LOG_LOCAL0", 16,
 "LOG_LOCAL1", 17,
 "LOG_LOCAL2", 18,
 "LOG_LOCAL3", 19,
 "LOG_LOCAL4", 20,
 "LOG_LOCAL5", 21,
 "LOG_LOCAL6", 22,
 "LOG_LOCAL7", 23, 
 "", -1
};

void Usage(char *pname) {
  printf("Usage: %s [dest] [facility] [level] [ident] [message]\n", pname);
  exit(1);
}


int main(int ac, char **av)
{
  int                 s, code;
  char                buf[256], *dest, *fac, *lvl, *id, *msg;
  struct sockaddr_in  sin;
  struct servent     *srvc;
  
  
  if(--ac != 5) 
    Usage(av[0]);

  dest = av[1];
  fac  = av[2];
  lvl  = av[3];
  id   = av[4];
  msg  = av[5];
  code = LogCode(fac, lvl);
  
  if((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
    perror("socket(AF_INET, SOCK_DGRAM, 0)");
    exit(1);
  }
  sprintf(buf, "<%d>%s: %s\0", code, id, msg);
  
  memset(&sin, 0, sizeof(struct sockaddr_in));
  sin.sin_family      = AF_INET;
  sin.sin_addr.s_addr = inet_addr(dest);

  if(srvc = getservbyname("syslog", 0)) {
    sin.sin_port        = htons(srvc->s_port);
    
    if(connect(s, (struct sockaddr *)(&sin), sizeof(sin)) < 0) {
      perror("connect()");
      exit(1);
    }
    
    send(s, buf, strlen(buf), 0);
    close(s);
  } else 
    perror("getservbyname");
  
  return 0;
}

int LogCode(register char *f, register char *l)
{
  register int fc = -1, lc = -1, i;

  for(i=0;(i<strlen(f)) && (isdigit(f[i])); i++);
  
  if(strlen(f)-i) {
    for(i=0; sl_facs[i].level != -1; i++)
      if(strcasecmp(f, sl_facs[i].word) == 0)
	fc = sl_facs[i].level;
    if(fc == -1) {
      printf("Error: could not determine facility: %s\n", f);
      exit(1);
    }
  } else
    fc = atoi(f);

  for(i=0;(i<strlen(l)) && (isdigit(l[i])); i++);
  if(strlen(l)-i) {
    for(i=0; sl_levs[i].level != -1; i++) 
      if(strcasecmp(l, sl_levs[i].word) == 0)
	lc = sl_levs[i].level;
    if(lc == -1) {
      printf("Error: could not determine priority: %s\n", l);
      exit(1);
    }
  } else
    lc = atoi(l);
  
  return ((fc<<3) + lc);
}
