From: Art Cancro Date: Sun, 5 Mar 2000 07:33:23 +0000 (+0000) Subject: * Added support for protocols over Unix domain sockets. X-Git-Tag: v7.86~7277 X-Git-Url: https://code.citadel.org/?p=citadel.git;a=commitdiff_plain;h=c42cce6bb0142d9fd234896dc95ef93a0d8a39f2 * Added support for protocols over Unix domain sockets. --- diff --git a/citadel/ChangeLog b/citadel/ChangeLog index db126f049..fd02984d3 100644 --- a/citadel/ChangeLog +++ b/citadel/ChangeLog @@ -1,4 +1,7 @@ $Log$ +Revision 1.478 2000/03/05 07:33:23 ajc +* Added support for protocols over Unix domain sockets. + Revision 1.477 2000/03/04 22:36:23 ajc * Remove nulls appended to editor files during replace, edit, and print operations. Truncate temp files during same operations. @@ -1696,4 +1699,3 @@ Sat Jul 11 00:20:48 EDT 1998 Nathan Bryant Fri Jul 10 1998 Art Cancro * Initial CVS import - diff --git a/citadel/ipc_c_tcp.c b/citadel/ipc_c_tcp.c index d9545d75c..4be220227 100644 --- a/citadel/ipc_c_tcp.c +++ b/citadel/ipc_c_tcp.c @@ -20,6 +20,7 @@ #include #include #include +#include #include #include #include @@ -72,8 +73,34 @@ int connectsock(char *host, char *service, char *protocol) struct servent *pse; struct protoent *ppe; struct sockaddr_in sin; + struct sockaddr_un sun; int s, type; + + if ( (!strcmp(protocol, "unix")) || (atoi(service)<0) ) { + memset(&sun, 0, sizeof(sun)); + sun.sun_family = AF_UNIX; + sprintf(sun.sun_path, USOCKPATH, 0-atoi(service) ); + + s = socket(AF_UNIX, SOCK_STREAM, 0); + if (s < 0) { + fprintf(stderr, "Can't create socket: %s\n", + strerror(errno)); + logoff(3); + } + + if (connect(s, (struct sockaddr *) &sun, sizeof(sun)) < 0) { + fprintf(stderr, "can't connect: %s\n", + strerror(errno)); + logoff(3); + } + + return s; + } + + + /* otherwise it's a network connection */ + memset(&sin, 0, sizeof(sin)); sin.sin_family = AF_INET; diff --git a/citadel/sysconfig.h b/citadel/sysconfig.h index 7b749753a..70e2162d8 100644 --- a/citadel/sysconfig.h +++ b/citadel/sysconfig.h @@ -97,6 +97,12 @@ #define SMTP_GIVE_UP 259200 /* give up after 3 days */ +/* + * Pathname template to use for Unix domain sockets + */ +#define USOCKPATH "/tmp/citadel%04x" + + /* * The names of rooms which are automatically created by the system */ diff --git a/citadel/sysdep.c b/citadel/sysdep.c index 6bb0720e5..59de2f8b5 100644 --- a/citadel/sysdep.c +++ b/citadel/sysdep.c @@ -26,6 +26,7 @@ #include #include #include +#include #include #include #include @@ -259,24 +260,40 @@ void end_critical_section(int which_one) /* * This is a generic function to set up a master socket for listening on * a TCP port. The server shuts down if the bind fails. + * + * If a negative number is specified, a Unix domain socket is created. */ int ig_tcp_server(int port_number, int queue_len) { struct sockaddr_in sin; + struct sockaddr_un addr; int s, i; + int is_unix = 0; - memset(&sin, 0, sizeof(sin)); - sin.sin_family = AF_INET; - sin.sin_addr.s_addr = INADDR_ANY; + if (port_number < 0) { + is_unix = 1; + } - if (port_number == 0) { - lprintf(1, "citserver: illegal port number specified\n"); - return(-1); + if (is_unix) { + memset(&addr, 0, sizeof(addr)); + addr.sun_family = AF_UNIX; + sprintf(addr.sun_path, USOCKPATH, 0-port_number); + } + else { + memset(&sin, 0, sizeof(sin)); + sin.sin_family = AF_INET; + sin.sin_addr.s_addr = INADDR_ANY; + sin.sin_port = htons((u_short)port_number); + } + + if (is_unix) { + s = socket(AF_UNIX, SOCK_STREAM, 0); + } + else { + s = socket(PF_INET, SOCK_STREAM, + (getprotobyname("tcp")->p_proto)); } - - sin.sin_port = htons((u_short)port_number); - s = socket(PF_INET, SOCK_STREAM, (getprotobyname("tcp")->p_proto)); if (s < 0) { lprintf(1, "citserver: Can't create a socket: %s\n", strerror(errno)); @@ -284,12 +301,24 @@ int ig_tcp_server(int port_number, int queue_len) } /* Set the SO_REUSEADDR socket option, because it makes sense. */ - i = 1; - setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &i, sizeof(i)); + if (!is_unix) { + i = 1; + setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &i, sizeof(i)); + } - if (bind(s, (struct sockaddr *)&sin, sizeof(sin)) < 0) { - lprintf(1, "citserver: Can't bind: %s\n", strerror(errno)); - return(-1); + if (is_unix) { + if (bind(s, (struct sockaddr *)&addr, sizeof(addr)) < 0) { + lprintf(1, "citserver: Can't bind: %s\n", + strerror(errno)); + return(-1); + } + } + else { + if (bind(s, (struct sockaddr *)&sin, sizeof(sin)) < 0) { + lprintf(1, "citserver: Can't bind: %s\n", + strerror(errno)); + return(-1); + } } if (listen(s, queue_len) < 0) { @@ -502,6 +531,7 @@ int client_gets(char *buf) */ void sysdep_master_cleanup(void) { struct ServiceFunctionHook *serviceptr; + char sockpath[256]; /* * close all protocol master sockets @@ -511,6 +541,13 @@ void sysdep_master_cleanup(void) { lprintf(3, "Closing listener on port %d\n", serviceptr->tcp_port); close(serviceptr->msock); + + /* If it's a Unix domain socket, remove the file. */ + if (serviceptr->tcp_port < 0) { + sprintf(sockpath, USOCKPATH, 0-(serviceptr->tcp_port)); + lprintf(9, "Removing <%s>\n", sockpath); + unlink(sockpath); + } } } @@ -829,7 +866,10 @@ int main(int argc, char **argv) /* * Bind the server to our favorite ports. */ - CtdlRegisterServiceHook(config.c_port_number, + CtdlRegisterServiceHook(config.c_port_number, /* TCP */ + citproto_begin_session, + do_command_loop); + CtdlRegisterServiceHook(0-config.c_port_number, /* Unix */ citproto_begin_session, do_command_loop);