]> arthur.barton.de Git - netatalk.git/blobdiff - libatalk/asp/asp_getsess.c
- merge branch-netatalk-afp-3x-dev, HEAD was tagged before
[netatalk.git] / libatalk / asp / asp_getsess.c
index 2a2826f9d17e722334da77515efb2ffed249fe5a..3d04c5fdff0e66111478ee052358c20b52687df8 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * $Id: asp_getsess.c,v 1.3 2001-06-29 14:14:46 rufustfirefly Exp $
+ * $Id: asp_getsess.c,v 1.8 2005-04-28 20:49:55 bfernhomberg 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 <syslog.h>
-#include <errno.h>
-#include <sys/signal.h>
-#include <sys/time.h>
 #include <sys/types.h>
+#include <sys/time.h>
 #include <sys/uio.h>
-#include <sys/wait.h>
 #include <sys/socket.h>
 #include <sys/param.h>
+#ifdef HAVE_SYS_WAIT_H
+#include <sys/wait.h>
+#endif /* HAVE_SYS_WAIT_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;
@@ -57,7 +72,7 @@ static void tickle_handler()
     if (++asp_ac[sid]->ac_state >= ACSTATE_BAD) {
       /* kill. if already dead, just continue */
       if (kill( asp_ac[ sid ]->ac_pid, SIGTERM) == 0)
-       syslog( LOG_INFO, "asp_alrm: %d timed out",
+       LOG(log_info, logtype_default, "asp_alrm: %d timed out",
                asp_ac[ sid ]->ac_pid );
 
       asp_ac[ sid ]->ac_state = ACSTATE_DEAD;
@@ -88,6 +103,14 @@ void asp_kill(int sig)
     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
@@ -95,24 +118,29 @@ void asp_kill(int sig)
  * 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;
@@ -122,10 +150,15 @@ ASP asp_getsession(ASP asp, server_child *server_children,
       /* 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;
@@ -133,6 +166,8 @@ ASP asp_getsession(ASP asp, server_child *server_children,
       if ((sigaction(SIGALRM, &action, NULL) < 0) ||
          (setitimer(ITIMER_REAL, &timer, NULL) < 0)) {
        free(asp_ac);
+       server_asp = NULL;
+       asp_ac = NULL;
        return NULL;
       }
 
@@ -169,18 +204,51 @@ ASP asp_getsession(ASP asp, server_child *server_children,
       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++) {
@@ -200,8 +268,7 @@ ASP asp_getsession(ASP asp, server_child *server_children,
 
        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 )
@@ -229,17 +296,20 @@ ASP asp_getsession(ASP asp, server_child *server_children,
          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 */
@@ -267,9 +337,15 @@ ASP asp_getsession(ASP asp, server_child *server_children,
       break;
 
     default:
-      syslog(LOG_INFO, "ASPUnknown %d", asp->cmdbuf[0]);
+      LOG(log_info, logtype_default, "ASPUnknown %d", asp->cmdbuf[0]);
       break;
     }
 
     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;
+}