/*
- * $Id: dsi_getsess.c,v 1.5 2001-09-06 19:04:40 rufustfirefly Exp $
+ * $Id: dsi_getsess.c,v 1.7 2005-04-28 20:50:02 bfernhomberg Exp $
*
* Copyright (c) 1997 Adrian Sun (asun@zoology.washington.edu)
* All rights reserved. See COPYRIGHT.
#include <stdlib.h>
#include <string.h>
#include <errno.h>
-#ifdef HAVE_UNISTD_H
#include <unistd.h>
-#endif /* HAVE_UNISTD_H */
#include <signal.h>
+#include <sys/types.h>
+#include <sys/socket.h>
/* POSIX.1 sys/wait.h check */
#include <sys/types.h>
#endif /* ! WIFEXITED */
#include <sys/time.h>
-#include <syslog.h>
+#include <atalk/logger.h>
+#include <atalk/util.h>
#include <atalk/dsi.h>
#include <atalk/server_child.h>
-static server_child *children = NULL;
-
-void dsi_kill(int sig)
-{
- if (children)
- server_child_kill(children, CHILD_DSIFORK, sig);
-}
-
/* hand off the command. return child connection to the main program */
-DSI *dsi_getsession(DSI *dsi, server_child *serv_children,
- const int tickleval)
+afp_child_t *dsi_getsession(DSI *dsi, server_child *serv_children, int tickleval)
{
pid_t pid;
-
- /* do a couple things on first entry */
- if (!dsi->inited) {
- if (!(children = serv_children))
- return NULL;
- dsi->inited = 1;
+ unsigned int ipc_fds[2];
+ afp_child_t *child;
+
+ if (socketpair(PF_UNIX, SOCK_STREAM, 0, ipc_fds) < 0) {
+ LOG(log_error, logtype_dsi, "dsi_getsess: %s", strerror(errno));
+ exit( EXITERR_CLNT );
}
-
- switch (pid = dsi->proto_open(dsi)) {
+
+ if (setnonblock(ipc_fds[0], 1) != 0 || setnonblock(ipc_fds[1], 1) != 0) {
+ LOG(log_error, logtype_dsi, "dsi_getsess: setnonblock: %s", strerror(errno));
+ exit(EXITERR_CLNT);
+ }
+
+ switch (pid = dsi->proto_open(dsi)) { /* in libatalk/dsi/dsi_tcp.c */
case -1:
/* if we fail, just return. it might work later */
- syslog(LOG_ERR, "dsi_getsess: %s", strerror(errno));
- return dsi;
+ LOG(log_error, logtype_dsi, "dsi_getsess: %s", strerror(errno));
+ return NULL;
case 0: /* child. mostly handled below. */
- dsi->child = 1;
break;
default: /* parent */
/* using SIGQUIT is hokey, but the child might not have
* re-established its signal handler for SIGTERM yet. */
- if (server_child_add(children, CHILD_DSIFORK, pid) < 0) {
- syslog(LOG_ERR, "dsi_getsess: %s", strerror(errno));
+ if ((child = server_child_add(serv_children, CHILD_DSIFORK, pid, ipc_fds[0])) == NULL) {
+ LOG(log_error, logtype_dsi, "dsi_getsess: %s", strerror(errno));
dsi->header.dsi_flags = DSIFL_REPLY;
dsi->header.dsi_code = DSIERR_SERVBUSY;
dsi_send(dsi);
dsi->header.dsi_code = DSIERR_OK;
kill(pid, SIGQUIT);
}
-
+ close(ipc_fds[1]);
dsi->proto_close(dsi);
- return dsi;
+ return child;
}
/* child: check number of open connections. this is one off the
* actual count. */
- if ((children->count >= children->nsessions) &&
+ if ((serv_children->count >= serv_children->nsessions) &&
(dsi->header.dsi_command == DSIFUNC_OPEN)) {
- syslog(LOG_INFO, "dsi_getsess: too many connections");
+ LOG(log_info, logtype_dsi, "dsi_getsess: too many connections");
dsi->header.dsi_flags = DSIFL_REPLY;
dsi->header.dsi_code = DSIERR_TOOMANY;
dsi_send(dsi);
- exit(1);
+ exit(EXITERR_CLNT);
}
/* get rid of some stuff */
close(dsi->serversock);
- server_child_free(children);
- children = NULL;
+ server_child_free(serv_children);
switch (dsi->header.dsi_command) {
case DSIFUNC_STAT: /* send off status and return */
dsi->timer.it_interval.tv_usec = dsi->timer.it_value.tv_usec = 0;
signal(SIGPIPE, SIG_IGN); /* we catch these ourselves */
dsi_opensession(dsi);
- return dsi;
+ if ((child = calloc(1, sizeof(afp_child_t))) == NULL)
+ exit(EXITERR_SYS);
+ child->ipc_fds[1] = ipc_fds[1];
+ return child;
break;
default: /* just close */
- syslog(LOG_INFO, "DSIUnknown %d", dsi->header.dsi_command);
+ LOG(log_info, logtype_dsi, "DSIUnknown %d", dsi->header.dsi_command);
dsi->proto_close(dsi);
- exit(1);
+ exit(EXITERR_CLNT);
}
}