2 * $Id: asp_getsess.c,v 1.7 2002-06-18 23:45:16 didg Exp $
4 * Copyright (c) 1990,1996 Regents of The University of Michigan.
5 * All Rights Reserved. See COPYRIGHT.
10 #endif /* HAVE_CONFIG_H */
20 #endif /* HAVE_UNISTD_H */
22 #include <sys/types.h>
25 #include <sys/socket.h>
26 #include <sys/param.h>
27 #ifdef HAVE_SYS_WAIT_H
29 #endif /* HAVE_SYS_WAIT_H */
31 #include <netatalk/at.h>
32 #include <atalk/logger.h>
33 #include <atalk/compat.h>
34 #include <atalk/atp.h>
35 #include <atalk/asp.h>
36 #include <atalk/server_child.h>
38 #include "asp_child.h"
41 #define WEXITSTATUS(stat_val) ((unsigned)(stat_val) >> 8)
42 #endif /* ! WEXITSTATUS */
44 #define WIFEXITED(stat_val) (((stat_val) & 255) == 0)
45 #endif /* ! WIFEXITED */
47 static ASP server_asp;
48 static struct server_child *children = NULL;
49 static struct asp_child **asp_ac = NULL;
51 /* send tickles and check tickle status of connections
52 * thoughts on using a hashed list:
53 * + child_cleanup, finding slots
54 * - tickle_handler, freeing, tickles
55 * if setup for a large number of connections,
56 * + space: if actual connections < potential
57 * - space: actual connections ~ potential
59 static void tickle_handler()
64 for (sid = 0; sid < children->nsessions; sid++) {
65 if (asp_ac[sid] == NULL || asp_ac[sid]->ac_state == ACSTATE_DEAD)
68 if (++asp_ac[sid]->ac_state >= ACSTATE_BAD) {
69 /* kill. if already dead, just continue */
70 if (kill( asp_ac[ sid ]->ac_pid, SIGTERM) == 0)
71 LOG(log_info, logtype_default, "asp_alrm: %d timed out",
72 asp_ac[ sid ]->ac_pid );
74 asp_ac[ sid ]->ac_state = ACSTATE_DEAD;
78 /* send off a tickle */
79 asp_tickle(server_asp, sid, &asp_ac[sid]->ac_sat);
83 static void child_cleanup(const pid_t pid)
87 for (i = 0; i < children->nsessions; i++)
88 if (asp_ac[i] && (asp_ac[i]->ac_pid == pid)) {
89 asp_ac[i]->ac_state = ACSTATE_DEAD;
96 void asp_kill(int sig)
99 server_child_kill(children, CHILD_ASPFORK, sig);
104 * This call handles open, tickle, and getstatus requests. On a
105 * successful open, it forks a child process.
106 * It returns an ASP to the child and parent and NULL if there is
109 static void set_asp_ac(int sid, struct asp_child *tmp);
111 ASP asp_getsession(ASP asp, server_child *server_children,
114 struct sigaction action;
115 struct itimerval timer;
116 struct sockaddr_at sat;
117 struct atp_block atpb;
119 struct iovec iov[ 8 ];
125 if (!(children = server_children))
128 if ((asp_ac = (struct asp_child **)
129 calloc(server_children->nsessions, sizeof(struct asp_child *)))
135 /* install cleanup pointer */
136 server_child_setup(children, CHILD_ASPFORK, child_cleanup);
138 /* install tickle handler */
139 memset(&action, 0, sizeof(action));
140 action.sa_handler = tickle_handler;
141 sigemptyset(&action.sa_mask);
142 action.sa_flags = SA_RESTART;
144 timer.it_interval.tv_sec = timer.it_value.tv_sec = tickleval;
145 timer.it_interval.tv_usec = timer.it_value.tv_usec = 0;
146 if ((sigaction(SIGALRM, &action, NULL) < 0) ||
147 (setitimer(ITIMER_REAL, &timer, NULL) < 0)) {
155 memset( &sat, 0, sizeof( struct sockaddr_at ));
157 sat.sat_len = sizeof( struct sockaddr_at );
159 sat.sat_family = AF_APPLETALK;
160 sat.sat_addr.s_net = ATADDR_ANYNET;
161 sat.sat_addr.s_node = ATADDR_ANYNODE;
162 sat.sat_port = ATADDR_ANYPORT;
163 atpb.atp_saddr = &sat;
164 atpb.atp_rreqdata = asp->cmdbuf;
165 atpb.atp_rreqdlen = sizeof( asp->cmdbuf );
166 while ( atp_rreq( asp->asp_atp, &atpb ) < 0 ) {
167 if ( errno == EINTR || errno == EAGAIN ) {
173 switch ( asp->cmdbuf[ 0 ] ) {
175 sid = asp->cmdbuf[1];
176 if ((asp_ac[sid] != NULL) && (asp_ac[sid]->ac_state != ACSTATE_DEAD))
177 asp_ac[sid]->ac_state = ACSTATE_OK;
182 printf( "asp stat\n" );
184 if ( asp->asp_slen > 0 ) {
186 memcpy( asp->cmdbuf + 4, asp->asp_status, asp->asp_slen );
187 iov[ 0 ].iov_base = asp->cmdbuf;
188 iov[ 0 ].iov_len = 4 + asp->asp_slen;
189 atpb.atp_sresiov = iov;
190 atpb.atp_sresiovcnt = 1;
191 atp_sresp( asp->asp_atp, &atpb );
196 if (children->count < children->nsessions) {
197 struct asp_child *asp_ac_tmp;
200 for (sid = 0; sid < children->nsessions; sid++) {
201 if (asp_ac[sid] == NULL)
204 if (asp_ac[sid]->ac_state == ACSTATE_DEAD) {
211 if ((atp = atp_open(ATADDR_ANYPORT,
212 &(atp_sockaddr(asp->asp_atp)->sat_addr))) == NULL)
215 switch ((pid = fork())) {
217 signal(SIGTERM, SIG_DFL);
218 signal(SIGHUP, SIG_DFL);
219 /* free/close some things */
220 for (i = 0; i < children->nsessions; i++ ) {
221 if ( asp_ac[i] != NULL )
226 server_child_free(children);
228 atp_close(asp->asp_atp);
233 asp->asp_wss = asp->cmdbuf[1];
236 asp->asp_flags = ASPFL_SSS;
239 case -1 : /* error */
240 asp->cmdbuf[ 0 ] = 0;
241 asp->cmdbuf[ 1 ] = 0;
242 asperr = ASPERR_SERVBUSY;
245 default : /* parent process */
246 /* we need atomic setting or pb with tickle_handler
248 switch (server_child_add(children, CHILD_ASPFORK, pid)) {
249 case 0: /* added child */
250 if ((asp_ac_tmp = (struct asp_child *)
251 malloc(sizeof(struct asp_child)))) {
252 asp_ac_tmp->ac_pid = pid;
253 asp_ac_tmp->ac_state = ACSTATE_OK;
254 asp_ac_tmp->ac_sat = sat;
255 asp_ac_tmp->ac_sat.sat_port = asp->cmdbuf[1];
257 asp->cmdbuf[0] = atp_sockaddr(atp)->sat_port;
258 asp->cmdbuf[1] = sid;
259 set_asp_ac(sid, asp_ac_tmp);
262 } /* fall through if malloc fails */
263 case -1: /* bad error */
266 default: /* non-fatal error */
274 asp->cmdbuf[0] = asp->cmdbuf[1] = 0;
275 asperr = ASPERR_SERVBUSY;
278 memcpy( asp->cmdbuf + 2, &asperr, sizeof(asperr));
279 iov[ 0 ].iov_base = asp->cmdbuf;
280 iov[ 0 ].iov_len = 4;
281 atpb.atp_sresiov = iov;
282 atpb.atp_sresiovcnt = 1;
283 atp_sresp( asp->asp_atp, &atpb );
287 LOG(log_info, logtype_default, "ASPUnknown %d", asp->cmdbuf[0]);
294 /* with fn defined after use, assume it's not optimized by the compiler */
295 static void set_asp_ac(int sid, struct asp_child *tmp)