#ifndef lint
static char *RCSid = "$Header: /source/users/msg/msgd/RCS/msgd.c,v 1.3 91/08/14 00:00:14 jmsellens Exp $";
#endif

#if 0
/*
 * $Log:	msgd.c,v $
 * Revision 1.3  91/08/14  00:00:14  jmsellens
 * s/eprintf/errprintf/ to avoid libuw clash
 * 
 * Revision 1.2  90/12/29  22:03:50  jmsellen
 * VARARGS and logging changes
 * 
 * Revision 1.1  87/08/06  19:06:38  sahayman
 * Initial revision
 * 
 */
#endif

/* msgd.c
   msg daemon
   John Sellens, University of Waterloo
*/

#include "msg.h"
#include <signal.h>

char *syserr();
#if vms
struct netdisc {
        int size;
        char *ptr;
} inetd = {10, "SYS$INPUT:"};
#else
extern int errno;
#endif

char *progname;
char hostname[BUFSIZ];
int client;

main( argc, argv )
int argc;
char *argv[];
{
    
    progname = argv[0];
    if ( gethostname( hostname, sizeof(hostname) ) )
	fatal( "Couldn't gethostname(): %s", syserr() );
    (void) signal( SIGHUP, SIG_IGN );
    (void) signal( SIGINT, SIG_IGN );
    (void) signal( SIGALRM, SIG_IGN );
    (void) signal( SIGTTIN, SIG_IGN );
    (void) signal( SIGTTOU, SIG_IGN );
#ifdef INETD
#if vms
    sys$assign(&inetd, &client, 0, 0);
#else
     /* Inetd provides the client connection on fd 0. */
    client = 0;
#endif
    server();
    exit(0);
#else
{
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#if vms
#include "twg$tcp:[netdist.include.arpa]inet.h"
#else
#include <arpa/inet.h>
#endif
#include <errno.h>
#include <sys/ioctl.h>

    struct servent *serv;
    struct sockaddr_in	sin;
    int i, sock;
    
    if ( argc != 1 )
	errprintf( "all arguments ignored" );
    serv = getservbyname( "msg", "tcp" );
    if ( serv == (struct servent *)0 )
	fatal( "msg/tcp not defined in services file" );

#if vms
#else
#ifndef DEBUG
    /* disconnect from tty */
    switch ( fork() ) {
	case 0:	/* child */
	    break;
	case -1:
	    fatal( "couldn't fork (%s), message daemon not started", syserr() );
	    break;
	default:	/* parent */
	    exit( 0 );
    }
    for (i = 0; i < 10; i++)
	close(i);
    (void) open("/", 0);
    dup2(0, 1);
    dup2(0, 2);
    i = open("/dev/tty", 2);
    if (i >= 0) {
	ioctl(i, TIOCNOTTY, (char *)0);
        close(i);
    }
#endif
#endif
    sin.sin_port = serv->s_port;
    sock = socket( AF_INET, SOCK_STREAM, 0 );
    if ( sock == -1 )
	fatal( "couldn't create socket: %s", syserr() );
    if ( bind( sock, (caddr_t)&sin, sizeof(sin) ) == -1 )
	fatal( "couldn't bind socket: %s", syserr() );
    if ( listen( sock, 5 ) == -1 )
	fatal( "couldn't listen to socket: %s", syserr() );
    
    for ( ;; ) {
	client = accept(sock, (struct sockaddr *)0, (int *)0);
	if ( client < 0 ) {
	    if ( errno != EINTR ) {
		errprintf( "accept: %s", syserr() );
		sleep(5);
	    }
	    continue;
	}
	server();
	(void) close( client );
    }
    /* NOTREACHED */
    }
#endif /* INETD */
}

#include <syslog.h>

static int loglevel = LOG_WARNING;

static
#ifdef VARARGS
doerror( s, ap )
char *s;
va_list ap;
#else
doerror( a, b, c, d, e, f, g, h, i, j, k )
char *a;
#endif
{
#ifdef DEBUG
#ifdef VARARGS
    vfprintf(stderr, s, ap);
#else
    fprintf(stderr, a, b, c, d, e, f, g, h, i, j, k);
#endif
    putc('\n', stderr);		/* syslog will add this */
#else
    static int first = 1;

    if (first) {
#ifdef LOG_DAEMON
    	openlog(progname, LOG_PID, LOG_DAEMON);
#else
    	openlog(progname, LOG_PID);
#endif
    	first = 0;
    }
#ifdef VARARGS
    {
	char buf[BUFSIZ];
	vsprintf( buf, s, ap );
	syslog( loglevel, buf );
    }
#else
    syslog(loglevel, a, b, c, d, e, f, g, h, i, j, k);
#endif
#endif
}

/*VARARGS1*/
#ifdef VARARGS
errprintf( s, va_alist )
char *s;
va_dcl
{
    va_list ap;
    va_start( ap );
    doerror( s, ap );
    va_end( ap );
}
#else
errprintf( a, b, c, d, e, f, g, h, i, j, k )
char *a;
{
    doerror(a, b, c, d, e, f, g, h, i, j, k);
}
#endif

/*VARARGS1*/
#ifdef VARARGS
fatal( s, va_alist )
char *s;
va_dcl
{
    va_list ap;
    loglevel = LOG_ERR;
    va_start( ap );
    doerror( s, ap );
    va_end( ap );
    exit( FATAL );
}
#else
fatal( a, b, c, d, e, f, g, h, i, j, k )
char *a;
{
    loglevel = LOG_ERR;
    doerror( a, b, c, d, e, f, g, h, i, j, k );
    exit( FATAL );
}
#endif
