2 * $Id: asp_getsess.c,v 1.4.2.1 2002-02-08 00:02:11 srittau Exp $
4 * Copyright (c) 1990,1996 Regents of The University of Michigan.
5 * All Rights Reserved. See COPYRIGHT.
10 #endif /* HAVE_CONFIG_H */
21 #endif /* HAVE_UNISTD_H */
23 #include <sys/types.h>
26 #include <sys/socket.h>
27 #include <sys/param.h>
28 #ifdef HAVE_SYS_WAIT_H
30 #endif /* HAVE_SYS_WAIT_H */
32 #include <netatalk/at.h>
33 #include <atalk/compat.h>
34 #include <atalk/atp.h>
35 #include <atalk/asp.h>
37 #include <atalk/server_child.h>
39 #include "asp_child.h"
42 #define WEXITSTATUS(stat_val) ((unsigned)(stat_val) >> 8)
43 #endif /* ! WEXITSTATUS */
45 #define WIFEXITED(stat_val) (((stat_val) & 255) == 0)
46 #endif /* ! WIFEXITED */
48 static ASP server_asp;
49 static struct server_child *children = NULL;
50 static struct asp_child **asp_ac = NULL;
52 /* send tickles and check tickle status of connections
53 * thoughts on using a hashed list:
54 * + child_cleanup, finding slots
55 * - tickle_handler, freeing, tickles
56 * if setup for a large number of connections,
57 * + space: if actual connections < potential
58 * - space: actual connections ~ potential
60 static void tickle_handler()
65 for (sid = 0; sid < children->nsessions; sid++) {
66 if (asp_ac[sid] == NULL || asp_ac[sid]->ac_state == ACSTATE_DEAD)
69 if (++asp_ac[sid]->ac_state >= ACSTATE_BAD) {
70 /* kill. if already dead, just continue */
71 if (kill( asp_ac[ sid ]->ac_pid, SIGTERM) == 0)
72 syslog( LOG_INFO, "asp_alrm: %d timed out",
73 asp_ac[ sid ]->ac_pid );
75 asp_ac[ sid ]->ac_state = ACSTATE_DEAD;
79 /* send off a tickle */
80 asp_tickle(server_asp, sid, &asp_ac[sid]->ac_sat);
84 static void child_cleanup(const pid_t pid)
88 for (i = 0; i < children->nsessions; i++)
89 if (asp_ac[i] && (asp_ac[i]->ac_pid == pid)) {
90 asp_ac[i]->ac_state = ACSTATE_DEAD;
97 void asp_kill(int sig)
100 server_child_kill(children, CHILD_ASPFORK, sig);
105 * This call handles open, tickle, and getstatus requests. On a
106 * successful open, it forks a child process.
107 * It returns an ASP to the child and parent and NULL if there is
110 ASP asp_getsession(ASP asp, server_child *server_children,
113 struct sigaction action;
114 struct itimerval timer;
115 struct sockaddr_at sat;
116 struct atp_block atpb;
118 struct iovec iov[ 8 ];
124 if (!(children = server_children))
127 if ((asp_ac = (struct asp_child **)
128 calloc(server_children->nsessions, sizeof(struct asp_child *)))
134 /* install cleanup pointer */
135 server_child_setup(children, CHILD_ASPFORK, child_cleanup);
137 /* install tickle handler */
138 memset(&action, 0, sizeof(action));
139 action.sa_handler = tickle_handler;
140 sigemptyset(&action.sa_mask);
141 action.sa_flags = SA_RESTART;
143 timer.it_interval.tv_sec = timer.it_value.tv_sec = tickleval;
144 timer.it_interval.tv_usec = timer.it_value.tv_usec = 0;
145 if ((sigaction(SIGALRM, &action, NULL) < 0) ||
146 (setitimer(ITIMER_REAL, &timer, NULL) < 0)) {
154 memset( &sat, 0, sizeof( struct sockaddr_at ));
156 sat.sat_len = sizeof( struct sockaddr_at );
158 sat.sat_family = AF_APPLETALK;
159 sat.sat_addr.s_net = ATADDR_ANYNET;
160 sat.sat_addr.s_node = ATADDR_ANYNODE;
161 sat.sat_port = ATADDR_ANYPORT;
162 atpb.atp_saddr = &sat;
163 atpb.atp_rreqdata = asp->cmdbuf;
164 atpb.atp_rreqdlen = sizeof( asp->cmdbuf );
165 while ( atp_rreq( asp->asp_atp, &atpb ) < 0 ) {
166 if ( errno == EINTR || errno == EAGAIN ) {
172 switch ( asp->cmdbuf[ 0 ] ) {
174 sid = asp->cmdbuf[1];
175 if ((asp_ac[sid] != NULL) && (asp_ac[sid]->ac_state != ACSTATE_DEAD))
176 asp_ac[sid]->ac_state = ACSTATE_OK;
181 printf( "asp stat\n" );
183 if ( asp->asp_slen > 0 ) {
185 memcpy( asp->cmdbuf + 4, asp->asp_status, asp->asp_slen );
186 iov[ 0 ].iov_base = asp->cmdbuf;
187 iov[ 0 ].iov_len = 4 + asp->asp_slen;
188 atpb.atp_sresiov = iov;
189 atpb.atp_sresiovcnt = 1;
190 atp_sresp( asp->asp_atp, &atpb );
195 if (children->count < children->nsessions) {
198 for (sid = 0; sid < children->nsessions; sid++) {
199 if (asp_ac[sid] == NULL)
202 if (asp_ac[sid]->ac_state == ACSTATE_DEAD) {
209 if ((atp = atp_open(ATADDR_ANYPORT,
210 &(atp_sockaddr(asp->asp_atp)->sat_addr))) == NULL)
213 switch ((pid = fork())) {
215 signal(SIGTERM, SIG_DFL);
216 signal(SIGHUP, SIG_DFL);
217 /* free/close some things */
218 for (i = 0; i < children->nsessions; i++ ) {
219 if ( asp_ac[i] != NULL )
224 server_child_free(children);
226 atp_close(asp->asp_atp);
231 asp->asp_wss = asp->cmdbuf[1];
234 asp->asp_flags = ASPFL_SSS;
237 case -1 : /* error */
238 asp->cmdbuf[ 0 ] = 0;
239 asp->cmdbuf[ 1 ] = 0;
240 asperr = ASPERR_SERVBUSY;
243 default : /* parent process */
244 switch (server_child_add(children, CHILD_ASPFORK, pid)) {
245 case 0: /* added child */
246 if ((asp_ac[sid] = (struct asp_child *)
247 malloc(sizeof(struct asp_child)))) {
248 asp_ac[sid]->ac_pid = pid;
249 asp_ac[sid]->ac_state = ACSTATE_OK;
250 asp_ac[sid]->ac_sat = sat;
251 asp_ac[sid]->ac_sat.sat_port = asp->cmdbuf[1];
253 asp->cmdbuf[0] = atp_sockaddr(atp)->sat_port;
254 asp->cmdbuf[1] = sid;
257 } /* fall through if malloc fails */
258 case -1: /* bad error */
261 default: /* non-fatal error */
269 asp->cmdbuf[0] = asp->cmdbuf[1] = 0;
270 asperr = ASPERR_SERVBUSY;
273 memcpy( asp->cmdbuf + 2, &asperr, sizeof(asperr));
274 iov[ 0 ].iov_base = asp->cmdbuf;
275 iov[ 0 ].iov_len = 4;
276 atpb.atp_sresiov = iov;
277 atpb.atp_sresiovcnt = 1;
278 atp_sresp( asp->asp_atp, &atpb );
282 syslog(LOG_INFO, "ASPUnknown %d", asp->cmdbuf[0]);