2 * $Id: dsi_getsess.c,v 1.7 2005-04-28 20:50:02 bfernhomberg Exp $
4 * Copyright (c) 1997 Adrian Sun (asun@zoology.washington.edu)
5 * All rights reserved. See COPYRIGHT.
10 #endif /* HAVE_CONFIG_H */
18 #include <sys/types.h>
19 #include <sys/socket.h>
21 #include <sys/types.h>
24 #include <atalk/logger.h>
25 #include <atalk/util.h>
27 #include <atalk/dsi.h>
28 #include <atalk/server_child.h>
30 /* hand off the command. return child connection to the main program */
31 afp_child_t *dsi_getsession(DSI *dsi, server_child *serv_children, int tickleval)
34 unsigned int ipc_fds[2];
37 if (socketpair(PF_UNIX, SOCK_STREAM, 0, ipc_fds) < 0) {
38 LOG(log_error, logtype_dsi, "dsi_getsess: %s", strerror(errno));
42 if (setnonblock(ipc_fds[0], 1) != 0 || setnonblock(ipc_fds[1], 1) != 0) {
43 LOG(log_error, logtype_dsi, "dsi_getsess: setnonblock: %s", strerror(errno));
47 switch (pid = dsi->proto_open(dsi)) { /* in libatalk/dsi/dsi_tcp.c */
49 /* if we fail, just return. it might work later */
50 LOG(log_error, logtype_dsi, "dsi_getsess: %s", strerror(errno));
53 case 0: /* child. mostly handled below. */
57 /* using SIGQUIT is hokey, but the child might not have
58 * re-established its signal handler for SIGTERM yet. */
59 if ((child = server_child_add(serv_children, CHILD_DSIFORK, pid, ipc_fds)) == NULL) {
60 LOG(log_error, logtype_dsi, "dsi_getsess: %s", strerror(errno));
61 dsi->header.dsi_flags = DSIFL_REPLY;
62 dsi->header.dsi_code = DSIERR_SERVBUSY;
64 dsi->header.dsi_code = DSIERR_OK;
67 dsi->proto_close(dsi);
71 /* child: check number of open connections. this is one off the
73 if ((serv_children->count >= serv_children->nsessions) &&
74 (dsi->header.dsi_command == DSIFUNC_OPEN)) {
75 LOG(log_info, logtype_dsi, "dsi_getsess: too many connections");
76 dsi->header.dsi_flags = DSIFL_REPLY;
77 dsi->header.dsi_code = DSIERR_TOOMANY;
82 /* get rid of some stuff */
83 close(dsi->serversock);
84 server_child_free(serv_children);
86 switch (dsi->header.dsi_command) {
87 case DSIFUNC_STAT: /* send off status and return */
89 /* OpenTransport 1.1.2 bug workaround:
91 * OT code doesn't currently handle close sockets well. urk.
92 * the workaround: wait for the client to close its
93 * side. timeouts prevent indefinite resource use.
96 static struct timeval timeout = {120, 0};
102 FD_SET(dsi->socket, &readfds);
104 select(FD_SETSIZE, &readfds, NULL, NULL, &timeout);
109 case DSIFUNC_OPEN: /* setup session */
110 /* set up the tickle timer */
111 dsi->timer.it_interval.tv_sec = dsi->timer.it_value.tv_sec = tickleval;
112 dsi->timer.it_interval.tv_usec = dsi->timer.it_value.tv_usec = 0;
113 signal(SIGPIPE, SIG_IGN); /* we catch these ourselves */
114 dsi_opensession(dsi);
115 if ((child = calloc(1, sizeof(afp_child_t))) == NULL)
118 child->ipc_fds[0] = -1;
119 child->ipc_fds[1] = ipc_fds[1];
123 default: /* just close */
124 LOG(log_info, logtype_dsi, "DSIUnknown %d", dsi->header.dsi_command);
125 dsi->proto_close(dsi);