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 #endif /* HAVE_UNISTD_H */
21 /* POSIX.1 sys/wait.h check */
22 #include <sys/types.h>
23 #ifdef HAVE_SYS_WAIT_H
25 #endif /* HAVE_SYS_WAIT_H */
27 #define WEXITSTATUS(stat_val) ((unsigned)(stat_val) >> 8)
28 #endif /* ! WEXITSTATUS */
30 #define WIFEXITED(stat_val) (((stat_val) & 255) == 0)
31 #endif /* ! WIFEXITED */
34 #include <atalk/logger.h>
35 #include <atalk/util.h>
37 #include <atalk/dsi.h>
38 #include <atalk/server_child.h>
40 static server_child *children = NULL;
42 void dsi_kill(int sig)
45 server_child_kill(children, CHILD_DSIFORK, sig);
48 /* hand off the command. return child connection to the main program */
49 DSI *dsi_getsession(DSI *dsi, server_child *serv_children,
54 /* do a couple things on first entry */
56 if (!(children = serv_children))
61 switch (pid = dsi->proto_open(dsi)) {
63 /* if we fail, just return. it might work later */
64 LOG(log_error, logtype_default, "dsi_getsess: %s", strerror(errno));
67 case 0: /* child. mostly handled below. */
72 /* using SIGQUIT is hokey, but the child might not have
73 * re-established its signal handler for SIGTERM yet. */
74 if (server_child_add(children, CHILD_DSIFORK, pid) < 0) {
75 LOG(log_error, logtype_default, "dsi_getsess: %s", strerror(errno));
76 dsi->header.dsi_flags = DSIFL_REPLY;
77 dsi->header.dsi_code = DSIERR_SERVBUSY;
79 dsi->header.dsi_code = DSIERR_OK;
83 dsi->proto_close(dsi);
87 /* child: check number of open connections. this is one off the
89 if ((children->count >= children->nsessions) &&
90 (dsi->header.dsi_command == DSIFUNC_OPEN)) {
91 LOG(log_info, logtype_default, "dsi_getsess: too many connections");
92 dsi->header.dsi_flags = DSIFL_REPLY;
93 dsi->header.dsi_code = DSIERR_TOOMANY;
98 /* get rid of some stuff */
99 close(dsi->serversock);
100 server_child_free(children);
103 switch (dsi->header.dsi_command) {
104 case DSIFUNC_STAT: /* send off status and return */
106 /* OpenTransport 1.1.2 bug workaround:
108 * OT code doesn't currently handle close sockets well. urk.
109 * the workaround: wait for the client to close its
110 * side. timeouts prevent indefinite resource use.
113 static struct timeval timeout = {120, 0};
119 FD_SET(dsi->socket, &readfds);
121 select(FD_SETSIZE, &readfds, NULL, NULL, &timeout);
126 case DSIFUNC_OPEN: /* setup session */
127 /* set up the tickle timer */
128 dsi->timer.it_interval.tv_sec = dsi->timer.it_value.tv_sec = tickleval;
129 dsi->timer.it_interval.tv_usec = dsi->timer.it_value.tv_usec = 0;
130 signal(SIGPIPE, SIG_IGN); /* we catch these ourselves */
131 dsi_opensession(dsi);
135 default: /* just close */
136 LOG(log_info, logtype_default, "DSIUnknown %d", dsi->header.dsi_command);
137 dsi->proto_close(dsi);