/* $Header: /home/aggarwal/lsrc/nocol/src/lib/RCS/eventlog.c,v 3.4 1993/11/03 20:51:03 aggarwal Exp $ */ /* * DESCRIPTION * A small library of functions for use in connecting to the * NOCOL event logging daemon (noclogd). * * Caveats: * * The server host is hardcoded (NLOG_HOST) */ /* * AUTHOR * David Wagner, wagner@jvnc.net * * Modified by: vikas@jvnc.net */ /*+ * $Log: eventlog.c,v $ * Revision 3.4 1993/11/03 20:51:03 aggarwal * Added ifdef for h_addr (defined in netdb.h) in case its defined. * * Revision 3.3 1993/11/02 21:20:15 aggarwal * Did not need the htons in front of the sp->s_port on line 134 * * Revision 3.2 1993/10/30 03:23:17 aggarwal * Fixed the ntohs and htons mixup * * Revision 3.1 1993/10/11 20:49:19 aggarwal * Fixed bug in converting gethostname() output to inaddr. * Also reduced the delaycount to 50 instead of 100 and sleep(1). * * Revision 3.0 1993/09/21 20:20:08 aggarwal * Deleted the Unix socket feature entirely. Tested, and seems ready * to go. * * Revision 2.0 1993/09/18 21:52:18 aggarwal * This version 2.0 tries to use stream Unix sockets and dgram inet * sockets. This is not workable, see comments in noclogd.c for more * details. * * This file is checked in just to record the way something like this * 'could' be done. * * Revision 1.4 1993/09/14 21:45:59 aggarwal * Put detailed fail message between ifdef DEBUG since we normally * don't want to see this message. * * Revision 1.3 1993/09/14 15:34:45 aggarwal * Does a sizeof(v) instead of sizeof(EVENT) * * Revision 1.2 1993/09/14 12:59:36 aggarwal * Cleaned up and made more robust. * * Revision 1.1 1993/09/13 13:31:22 aggarwal * Initial revision * */ #ifndef lint static char rcsid[] = "$Id: eventlog.c,v 3.4 1993/11/03 20:51:03 aggarwal Exp $" ; #endif #include "noclogd.h" #include /* * The logfile descriptor: -2 if it hasn't been opened at all, and * -1 if openeventlog() failed. */ static int logfd= -2; /* global in this module */ static int delaycount; /* to prevent overrunning the dgram server */ static time_t closetime; /* * Opens a socket to the nocol logging daemon. * Returns 0 on success, or prints an error message to stderr * and returns -1 on failure. ON failure, it MUST change logfd * to a value of -1. */ int openeventlog() { struct sockaddr_in sin; struct servent *sp; char *s ; /* Silently fail if there's already a connection open */ if (logfd >= 0) return(-1); /* * Try to open a connection to the log address over the network. */ logfd = socket(AF_INET, SOCK_DGRAM, 0); if (logfd < 0) { perror("openeventlog: AF_INET socket() failed"); logfd = -1 ; return(-1); } /* Got a socket, now assign family, server_addr, dest port */ bzero(&sin, sizeof(sin)); sin.sin_family = AF_INET; s = NLOG_HOST ; if (isdigit(*s)) /* given an address, not a name */ sin.sin_addr.s_addr = inet_addr(s); else { struct hostent *hp ; /* gethostbyname returns in_addr structures */ if ((hp = gethostbyname(NLOG_HOST)) == NULL) { perror("openeventlog"); fprintf(stderr, "gethostbyname() failed for %s\n", NLOG_HOST); logfd = -1 ; return(-1); } #ifdef h_addr /* in netdb.h */ bcopy((char *)hp->h_addr, (char *)&sin.sin_addr,hp->h_length); #else bcopy((char *)hp->h_addr_list[0], (char *)&sin.sin_addr,hp->h_length); #endif } #ifdef DEBUG fprintf(stderr, "openeventlog: logging to %s\n", inet_ntoa(sin.sin_addr)) ; #endif if (sin.sin_addr.s_addr == -1) /* error */ { perror("openeventlog: inet_addr() failed"); logfd = -1 ; return(-1); } /* Figure out what port number to use */ if ((sp = getservbyname(NLOG_SERVICE, "udp")) == NULL) sin.sin_port = htons(NLOG_PORT); else sin.sin_port = sp->s_port; if (connect(logfd, (struct sockaddr *)&sin, sizeof(sin)) < 0) { perror("client: AF_INET connect() failed"); logfd = -1; return(-1); } #ifdef DEBUG fprintf(stderr, "openeventlog: opened INET socket %d\n", logfd); #endif return(0); } /* * Writes an EVENT structure to the nocol logging daemon. * The connection must have been already created with openeventlog(). * If logfd = -2, then assumes that the user erred and never called * openeventlog(), so it does it for him. * Returns 0 on success, or prints an error message to stderr * and returns -1 on failure. * * NOTE: since the socket is of the connectionless type, logfd might actually * be okay, but the logging daemon might not be up. There is no * way to tell since a connection is not established with the logging * daemon. */ #define RETRY_REOPEN 1*60 /* seconds before trying to reopen logfd */ int eventlog(v) EVENT *v; { int bytesleft, retval; if (logfd == -2) /* Never been tried, try to open if RETRY_REOPEN */ { time_t curtime = time((time_t *) NULL); if ((curtime - closetime) > RETRY_REOPEN) openeventlog(); } if (logfd < 0) /* Silently fail if no connection could be opened */ return(-1); for (bytesleft=sizeof(*v); bytesleft > 0; bytesleft-=retval) if ((retval=write(logfd, (char *)v, bytesleft)) < 0) { #ifdef DEBUG perror("eventlog: write() failed"); #endif /* DEBUG */ closeeventlog(); /* no point keeping it open */ return(-1); } if ((++delaycount % 50) == 0) /* small delay after X loggings */ { delaycount = 0 ; sleep(1); } return(0); } /* * Closes the current connection to the nocol logging daemon. */ int closeeventlog() { /* Silently fail if no connection has been opened yet */ if (logfd < 0) return(-1); if (close(logfd) < 0) { perror("closeeventlog: close() failed"); return(-1); } /* * Reset things cleanly so we can call openeventlog() later if we want. * Store the time that we closed the file desc so that we don't try * and reopen too many times in 'openeventlog' */ closetime = time((time_t *) NULL); logfd = -2; return(0); }