/*
- * $Id: asp_getsess.c,v 1.5 2002-01-04 04:45:48 sibaz Exp $
+ * $Id: asp_getsess.c,v 1.9 2009-10-13 22:55:37 didg Exp $
*
* Copyright (c) 1990,1996 Regents of The University of Michigan.
* All Rights Reserved. See COPYRIGHT.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include <errno.h>
+#include <signal.h>
+
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif /* HAVE_UNISTD_H */
-#include <atalk/logger.h>
-#include <errno.h>
-#include <sys/signal.h>
+#include <sys/types.h>
#include <sys/time.h>
#include <sys/uio.h>
-
-/* POSIX.1 sys/wait.h check */
-#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/param.h>
#ifdef HAVE_SYS_WAIT_H
#include <sys/wait.h>
#endif /* HAVE_SYS_WAIT_H */
-#ifndef WEXITSTATUS
-#define WEXITSTATUS(stat_val) ((unsigned)(stat_val) >> 8)
-#endif /* ! WEXITSTATUS */
-#ifndef WIFEXITED
-#define WIFEXITED(stat_val) (((stat_val) & 255) == 0)
-#endif /* ! WIFEXITED */
-#include <sys/socket.h>
-#include <sys/param.h>
#include <netatalk/at.h>
+#include <atalk/logger.h>
#include <atalk/compat.h>
#include <atalk/atp.h>
#include <atalk/asp.h>
-
#include <atalk/server_child.h>
+
#include "asp_child.h"
+#ifndef WEXITSTATUS
+#define WEXITSTATUS(stat_val) ((unsigned)(stat_val) >> 8)
+#endif /* ! WEXITSTATUS */
+#ifndef WIFEXITED
+#define WIFEXITED(stat_val) (((stat_val) & 255) == 0)
+#endif /* ! WIFEXITED */
+
+#ifndef MIN
+#define MIN(a,b) ((a)<(b)?(a):(b))
+#endif /* ! MIN */
+
static ASP server_asp;
static struct server_child *children = NULL;
static struct asp_child **asp_ac = NULL;
* + space: if actual connections < potential
* - space: actual connections ~ potential
*/
-static void tickle_handler()
+static void tickle_handler(int sig _U_)
{
int sid;
server_child_kill(children, CHILD_ASPFORK, sig);
}
+void asp_stop_tickle(void)
+{
+ if (server_asp && server_asp->inited) {
+ static const struct itimerval timer = {{0, 0}, {0, 0}};
+
+ setitimer(ITIMER_REAL, &timer, NULL);
+ }
+}
/*
* This call handles open, tickle, and getstatus requests. On a
* It returns an ASP to the child and parent and NULL if there is
* an error.
*/
+static void set_asp_ac(int sid, struct asp_child *tmp);
+
ASP asp_getsession(ASP asp, server_child *server_children,
const int tickleval)
{
- struct sigaction action;
- struct itimerval timer;
- struct sockaddr_at sat;
- struct atp_block atpb;
+ struct sigaction action;
+ struct itimerval timer;
+ struct sockaddr_at sat;
+ struct atp_block atpb;
ATP atp;
- struct iovec iov[ 8 ];
+ struct iovec iov[ 8 ];
pid_t pid;
- int i, sid;
- u_int16_t asperr;
+ int i, iovcnt, sid;
+ u_int16_t asperr;
+ char *buf;
+ int buflen;
if (!asp->inited) {
if (!(children = server_children))
return NULL;
- if ((asp_ac = (struct asp_child **)
+ /* only calloc once */
+ if (!asp_ac && (asp_ac = (struct asp_child **)
calloc(server_children->nsessions, sizeof(struct asp_child *)))
== NULL)
return NULL;
/* install cleanup pointer */
server_child_setup(children, CHILD_ASPFORK, child_cleanup);
- /* install tickle handler */
+ /* install tickle handler
+ * we are the parent process
+ */
memset(&action, 0, sizeof(action));
action.sa_handler = tickle_handler;
sigemptyset(&action.sa_mask);
+ sigaddset(&action.sa_mask, SIGHUP);
+ sigaddset(&action.sa_mask, SIGTERM);
+ sigaddset(&action.sa_mask, SIGCHLD);
action.sa_flags = SA_RESTART;
timer.it_interval.tv_sec = timer.it_value.tv_sec = tickleval;
if ((sigaction(SIGALRM, &action, NULL) < 0) ||
(setitimer(ITIMER_REAL, &timer, NULL) < 0)) {
free(asp_ac);
+ server_asp = NULL;
+ asp_ac = NULL;
return NULL;
}
printf( "asp stat\n" );
#endif /* EBUG */
if ( asp->asp_slen > 0 ) {
- asp->cmdbuf[0] = 0;
- memcpy( asp->cmdbuf + 4, asp->asp_status, asp->asp_slen );
- iov[ 0 ].iov_base = asp->cmdbuf;
- iov[ 0 ].iov_len = 4 + asp->asp_slen;
- atpb.atp_sresiov = iov;
- atpb.atp_sresiovcnt = 1;
- atp_sresp( asp->asp_atp, &atpb );
+ i = 0;
+ while(atpb.atp_bitmap) {
+ i++;
+ atpb.atp_bitmap >>= 1;
+ }
+
+ /* asp->data is big enough ... */
+ memcpy( asp->data, asp->asp_status, MIN(asp->asp_slen, i*ASP_CMDSIZ));
+
+ buflen = MIN(asp->asp_slen, i*ASP_CMDSIZ);
+ buf = asp->data;
+ iovcnt = 0;
+
+ /* If status information is too big to fit into the available
+ * ASP packets, we simply send as much as we can.
+ * Older client versions will most likely not be able to use
+ * the additional information anyway, like directory services
+ * or UTF8 server name. A very long fqdn could be a problem,
+ * we could end up with an invalid address list.
+ */
+ do {
+ iov[ iovcnt ].iov_base = buf;
+ memmove(buf + ASP_HDRSIZ, buf, buflen);
+ memset( iov[ iovcnt ].iov_base, 0, ASP_HDRSIZ );
+
+ if ( buflen > ASP_CMDSIZ ) {
+ buf += ASP_CMDMAXSIZ;
+ buflen -= ASP_CMDSIZ;
+ iov[ iovcnt ].iov_len = ASP_CMDMAXSIZ;
+ } else {
+ iov[ iovcnt ].iov_len = buflen + ASP_HDRSIZ;
+ buflen = 0;
+ }
+ iovcnt++;
+ } while ( iovcnt < i && buflen > 0 );
+
+ atpb.atp_sresiovcnt = iovcnt;
+ atpb.atp_sresiov = iov;
+ atp_sresp( asp->asp_atp, &atpb );
}
break;
case ASPFUNC_OPEN :
if (children->count < children->nsessions) {
+ struct asp_child *asp_ac_tmp;
/* find a slot */
for (sid = 0; sid < children->nsessions; sid++) {
switch ((pid = fork())) {
case 0 : /* child */
- signal(SIGTERM, SIG_DFL);
- signal(SIGHUP, SIG_DFL);
+ server_reset_signal();
/* free/close some things */
for (i = 0; i < children->nsessions; i++ ) {
if ( asp_ac[i] != NULL )
break;
default : /* parent process */
+ /* we need atomic setting or pb with tickle_handler
+ */
switch (server_child_add(children, CHILD_ASPFORK, pid)) {
case 0: /* added child */
- if ((asp_ac[sid] = (struct asp_child *)
+ if ((asp_ac_tmp = (struct asp_child *)
malloc(sizeof(struct asp_child)))) {
- asp_ac[sid]->ac_pid = pid;
- asp_ac[sid]->ac_state = ACSTATE_OK;
- asp_ac[sid]->ac_sat = sat;
- asp_ac[sid]->ac_sat.sat_port = asp->cmdbuf[1];
+ asp_ac_tmp->ac_pid = pid;
+ asp_ac_tmp->ac_state = ACSTATE_OK;
+ asp_ac_tmp->ac_sat = sat;
+ asp_ac_tmp->ac_sat.sat_port = asp->cmdbuf[1];
asp->cmdbuf[0] = atp_sockaddr(atp)->sat_port;
asp->cmdbuf[1] = sid;
+ set_asp_ac(sid, asp_ac_tmp);
asperr = ASPERR_OK;
break;
} /* fall through if malloc fails */
return asp;
}
+
+/* with fn defined after use, assume it's not optimized by the compiler */
+static void set_asp_ac(int sid, struct asp_child *tmp)
+{
+ asp_ac[sid] = tmp;
+}