#ifndef LINT
static char *rcsid="$Id: serv_unixd.c,v 1.5 2001/07/20 07:35:54 crosser Exp $";
#endif
/*
$Log: serv_unixd.c,v $
Revision 1.5 2001/07/20 07:35:54 crosser
more tuning of AF_UNIX address size, now works on FreeBSD
Revision 1.4 2001/07/20 05:48:59 crosser
address bug with AF_UNIX address size
fix permissions of unix datagram socket (on Linux, honors umask)
Revision 1.3 1999/10/03 21:18:04 crosser
First (probably) working version with new run time config parser.
Also added listenq parameter (backlog size for listen()) and
renamed wtest to whoson (and with man page). Release 2.00beta1.
Revision 1.2 1999/08/19 17:22:16 crosser
Move to new config scheme (does not work yet)
Revision 1.1 1999/01/30 15:43:40 crosser
Initial revision
*/
/*
WHAT IS IT:
Implementation of experimental "whoson" protocol
AUTHOR:
Eugene G. Crosser <crosser@average.org>
COPYRIGHT:
Public domain
*/
#include "config.h"
#include <sys/types.h>
#include <sys/stat.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/un.h>
#include <netdb.h>
#ifdef HAVE_SYS_SELECT_H
#include <sys/select.h>
#endif
#include <unistd.h>
#include <errno.h>
#include <signal.h>
#include <setjmp.h>
#include <stdio.h>
#include <ctype.h>
#include "whosond.h"
#include "rtconfig.h"
#include "serv_common.h"
#include "checkperm.h"
#include "report.h"
#include "rtc_begin.h"
#include "serv_unixd_cfg.h"
#include "rtc_middle.h"
#include "serv_unixd_cfg.h"
#include "rtc_end.h"
struct _unixd_data_rec {
char buf[512];
};
static struct _evdesc unixd_read_evproc(int fd,void *priv)
{
struct _unixd_data_rec *data=(struct _unixd_data_rec *)priv;
struct _evdesc evdesc;
int len,slen;
struct sockaddr_un fromunix;
char retbuf[512];
DPRINT(("unixd_read_evproc(%d,%p)\n",fd,priv))
memset(&evdesc,0,sizeof(struct _evdesc));
evdesc.fd=-1;
if (fd < 0) {
fd=-fd;
close(fd);
free(data);
} else {
slen = sizeof(fromunix);
if ((len=recvfrom(fd,data->buf,sizeof(data->buf)-1,
0,(struct sockaddr *)&fromunix,&slen)) > 0) {
DPRINT(("UNIX DGRAM message (%d bytes) from %s\n",len,fromunix.sun_path))
retbuf[0]='\0';
do_request(data->buf,retbuf,sizeof(retbuf));
len=strlen(retbuf);
if (sendto(fd,retbuf,len,0,
(struct sockaddr *)&fromunix,slen) != len) {
ERRLOG((LOG_ERR,"sendto: %m"))
}
} else {
ERRLOG((LOG_ERR,"recvfrom: %m"))
}
}
DPRINT(("unixd_read_evproc returns fd=%d evproc=%p\n",evdesc.fd,evdesc.evproc))
return evdesc;
}
struct _evdesc unixd_serv_init(void *priv)
{
wso_serv_unixd_cfg *rec=(wso_serv_unixd_cfg *)priv;
struct _evdesc evdesc;
struct _unixd_data_rec *data;
struct sockaddr_un server;
int msgsock=-1;
int tries,on=1;
mode_t savemask;
DPRINT(("unixd_serv_init(%p)\n",priv))
memset((char *)&server,0,sizeof(server));
server.sun_family = AF_UNIX;
strncpy(server.sun_path,rec->port,sizeof(server.sun_path)-1);
server.sun_path[sizeof(server.sun_path)-1]='\0';
(void)unlink(server.sun_path);
if ((msgsock=socket(AF_UNIX,SOCK_DGRAM,0)) < 0) {
ERRLOG((LOG_ERR,"socket: %m"))
goto exit;
}
if (setsockopt(msgsock,SOL_SOCKET,SO_REUSEADDR,
(char*)&on,sizeof(on)) < 0) {
ERRLOG((LOG_ERR,"setsockopt: %m"))
msgsock=-1;
goto exit;
}
savemask=umask(0);
for (tries=0;;tries++) {
if (bind(msgsock,(struct sockaddr*)&server,sizeof(server)-
sizeof(server.sun_path)+strlen(server.sun_path)+1) < 0) {
if ((errno == EADDRINUSE) && (tries < 10)) {
sleep(tries);
continue;
}
(void)umask(savemask);
ERRLOG((LOG_ERR,"bind: %m"))
msgsock=-1;
goto exit;
} else break;
}
(void)umask(savemask);
exit:
memset(&evdesc,0,sizeof(struct _evdesc));
evdesc.fd=msgsock;
evdesc.evproc=unixd_read_evproc;
evdesc.ttl=0;
evdesc.priv=priv;
if ((data=(struct _unixd_data_rec *)malloc
(sizeof(struct _unixd_data_rec)))) {
memset(data,0,sizeof(struct _unixd_data_rec));
evdesc.priv=data;
} else {
ERRLOG((LOG_ERR,"allocating struct _unixd_data_rec: %m"))
evdesc.fd=-1;
evdesc.evproc=NULL;
}
DPRINT(("unixd_serv_init returns fd=%d evproc=%p\n",evdesc.fd,evdesc.evproc))
return evdesc;
}
syntax highlighted by Code2HTML, v. 0.9.1