]> arthur.barton.de Git - netatalk.git/commitdiff
MFH sleep and unix priv functionalities.
authordidg <didg>
Mon, 21 Jul 2003 05:50:53 +0000 (05:50 +0000)
committerdidg <didg>
Mon, 21 Jul 2003 05:50:53 +0000 (05:50 +0000)
25 files changed:
bin/aecho/aecho.c
config/AppleVolumes.default
config/afpd.conf.tmpl
config/netatalk.conf
etc/afpd/afp_dsi.c
etc/afpd/afp_options.c
etc/afpd/auth.c
etc/afpd/desktop.c
etc/afpd/directory.c
etc/afpd/directory.h
etc/afpd/file.c
etc/afpd/file.h
etc/afpd/filedir.c
etc/afpd/fork.c
etc/afpd/globals.h
etc/afpd/main.c
etc/afpd/unix.c
etc/afpd/unix.h
etc/afpd/volume.c
etc/afpd/volume.h
include/atalk/server_child.h
include/atalk/server_ipc.h [new file with mode: 0644]
libatalk/util/Makefile.am
libatalk/util/server_child.c
libatalk/util/server_ipc.c [new file with mode: 0644]

index 3ce4fbfd0838e040751783b896ec23721c594d7e..410888b5395484c8ff4ef530676ee43a213e7c7c 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * $Id: aecho.c,v 1.5 2001-08-03 22:07:22 srittau Exp $
+ * $Id: aecho.c,v 1.5.10.1 2003-07-21 05:50:53 didg Exp $
  *
  * Copyright (c) 1990,1991 Regents of The University of Michigan.
  * All Rights Reserved.
@@ -139,6 +139,8 @@ int main( ac, av )
                fprintf(stderr, "Bad address.\n");
                exit(1);
            }
+           break;
+
          case 'c' :
            pings = atoi( optarg );
            break;
index 7859cc6cb40af54eaf4bf4a3fd8029274f3d6f4f..9aae88e8e7509af0ca8d518f869701b79dbc69d9 100644 (file)
@@ -83,6 +83,7 @@
 # preexec_close       -> a non-zero return code from preexec close the 
 #                        volume being mounted.
 # nostat              -> don't stat volume path when enumerating volumes list
+# upriv               -> use unix privilege.  
 #
 #
 # codepage:filename   -> load filename from nls directory.
index d32d8347e345343bc299bd93949708621c53a29e..47d4b03a5e501faab629fe78526cd2cb202064c4 100644 (file)
 #                         Note: Depending on the number of simultaneously
 #                         connected clients and the network's speed, this can
 #                         lead to a significant higher load on your network!
+#     -sleep   <number>   AFP 3.x wait number hours before disconnecting
+#                         clients in sleep mode. Default 10 hours
 #     -tickleval <number> Specify the tickle timeout interval (in seconds).
 #                         Note, this defaults to 30 seconds, and really 
 #                         shouldn't be changed.  If you want to control
index 5a30697de135d8bc1602570a8d6ff79f42fbfaa7..4d3bef9c9972a2e23a7d508826e8c3adafe6d512 100644 (file)
@@ -3,7 +3,7 @@
 AFPD_MAX_CLIENTS=20
 
 # Change this to set the machine's atalk name and zone.
-# NOTE: if you're zone has spaces in it, you're better off specifying
+# NOTE: if your zone has spaces in it, you're better off specifying
 #       it in afpd.conf
 #ATALK_ZONE=@zone
 ATALK_NAME=`echo ${HOSTNAME}|cut -d. -f1`
index efcb2fec92ce9d1f5dcf85b84b2706672ec23cce..24d73511c42e70b56ee82bce1b541d28eaf95acb 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * $Id: afp_dsi.c,v 1.27.2.2 2003-06-23 10:25:07 didg Exp $
+ * $Id: afp_dsi.c,v 1.27.2.3 2003-07-21 05:50:53 didg Exp $
  *
  * Copyright (c) 1999 Adrian Sun (asun@zoology.washington.edu)
  * Copyright (c) 1990,1993 Regents of The University of Michigan.
@@ -47,6 +47,7 @@ extern struct oforks  *writtenfork;
 
 #define CHILD_DIE         (1 << 0)
 #define CHILD_RUNNING     (1 << 1)
+#define CHILD_SLEEPING    (1 << 2)
 
 static struct {
     AFPObj *obj;
@@ -90,9 +91,14 @@ static void afp_dsi_die(int sig)
     }
 }
 
-/* ---------------------------------
- * SIGUSR1 down in five mn.
-*/
+/* */
+static void afp_dsi_sleep(void)
+{
+    child.flags |= CHILD_SLEEPING;
+    dsi_sleep(child.obj->handle, 1);
+}
+
+/* ------------------- */
 static void afp_dsi_timedown()
 {
     struct sigaction   sv;
@@ -155,13 +161,15 @@ static void afp_dsi_getmesg (int sig)
 }
 #endif /* SERVERTEXT */
 
-/* ---------------------- */
 static void alarm_handler()
 {
-int err;
+    int err;
+
     /* if we're in the midst of processing something,
        don't die. */
-    if ((child.flags & CHILD_RUNNING) || (child.tickle++ < child.obj->options.timeout)) {
+    if ((child.flags & CHILD_SLEEPING) && child.tickle++ < child.obj->options.sleep) {
+        return;
+    } else if ((child.flags & CHILD_RUNNING) || (child.tickle++ < child.obj->options.timeout)) {
         if (!(err = pollvoltime(child.obj)))
             err = dsi_tickle(child.obj->handle);
         if (err <= 0) 
@@ -203,6 +211,7 @@ void afp_over_dsi(AFPObj *obj)
     obj->reply = (int (*)()) dsi_cmdreply;
     obj->attention = (int (*)(void *, AFPUserBytes)) dsi_attention;
 
+    obj->sleep = afp_dsi_sleep;
     child.obj = obj;
     child.tickle = child.flags = 0;
 
@@ -270,6 +279,7 @@ void afp_over_dsi(AFPObj *obj)
     /* get stuck here until the end */
     while ((cmd = dsi_receive(dsi))) {
         child.tickle = 0;
+        child.flags &= ~CHILD_SLEEPING;
         dsi_sleep(dsi, 0); /* wake up */
         if (reload_request) {
             reload_request = 0;
@@ -278,7 +288,7 @@ void afp_over_dsi(AFPObj *obj)
 
         if (cmd == DSIFUNC_TICKLE) {
             /* so we don't get killed on the client side. */
-            if (child.flags & CHILD_DIE)
+            if ((child.flags & CHILD_DIE))
                 dsi_tickle(dsi);
             continue;
         } else if (!(child.flags & CHILD_DIE)) { /* reset tickle timer */
index ef6ddc144e2e12c4102b672e2ecce06cad5dee4c..31c923f05fc5a25997c28529a320d897a85a7c23 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * $Id: afp_options.c,v 1.30.2.1 2003-05-26 11:17:25 didg Exp $
+ * $Id: afp_options.c,v 1.30.2.2 2003-07-21 05:50:53 didg Exp $
  *
  * Copyright (c) 1997 Adrian Sun (asun@zoology.washington.edu)
  * Copyright (c) 1990,1993 Regents of The University of Michigan.
@@ -159,6 +159,7 @@ void afp_options_init(struct afp_options *options)
     options->passwdfile = _PATH_AFPDPWFILE;
     options->tickleval = 30;
     options->timeout = 4;
+    options->sleep = 10* 120; /* 10 h in 30 seconds tick */
     options->server_notif = 1;
     options->authprintdir = NULL;
     options->signature = "host";
@@ -264,6 +265,13 @@ int afp_options_parseline(char *buf, struct afp_options *options)
         }
     }
 
+    if ((c = getoption(buf, "-sleep"))) {
+        options->sleep = atoi(c) *120;
+        if (options->sleep <= 4) {
+            options->sleep = 4;
+        }
+    }
+
     if ((c = getoption(buf, "-server_quantum")))
         options->server_quantum = strtoul(c, NULL, 0);
 
index 949f4ca75ac5e60d062634278536e8ca04987a77..afa85645bd7d64364ce0e88291a09cadcd47836a 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * $Id: auth.c,v 1.44.2.2 2003-05-26 11:04:36 didg Exp $
+ * $Id: auth.c,v 1.44.2.3 2003-07-21 05:50:53 didg Exp $
  *
  * Copyright (c) 1990,1993 Regents of The University of Michigan.
  * All Rights Reserved.  See COPYRIGHT.
@@ -33,6 +33,7 @@
 #include <pwd.h>
 #include <grp.h>
 #include <atalk/logger.h>
+#include <atalk/server_ipc.h>
 
 #ifdef TRU64
 #include <netdb.h>
@@ -272,6 +273,7 @@ static int login(AFPObj *obj, struct passwd *pwd, void (*logout)(void))
 
         LOG(log_info, logtype_afpd, "session from %s (%s)", hostname,
             inet_ntoa( dsi->client.sin_addr ) );
+
         if (setegid( pwd->pw_gid ) < 0 || seteuid( pwd->pw_uid ) < 0) {
             LOG(log_error, logtype_afpd, "login: %s", strerror(errno) );
             return AFPERR_BADUAM;
@@ -334,14 +336,15 @@ unsigned int ibuflen, *rbuflen;
 
     *rbuflen = 0;
 
-    retdata = 1;
+    retdata = obj->options.sleep /120;
+    if (!retdata) {
+       retdata = 1;
+    }
     *rbuflen = sizeof(retdata);
     retdata = htonl(retdata);
     memcpy(rbuf, &retdata, sizeof(retdata));
-    if (obj->proto == AFPPROTO_DSI) {
-        DSI *dsi = obj->handle;
-        dsi_sleep(dsi, 1);
-    }
+    if (obj->sleep)
+        obj->sleep();
     rbuf += sizeof(retdata);
     return AFP_OK;
 }
@@ -353,10 +356,12 @@ char           *ibuf, *rbuf;
 unsigned int ibuflen, *rbuflen;
 {
     u_int16_t           type;
-    u_int32_t           idlen;
+    u_int32_t           idlen = 0;
+    u_int32_t          boottime;
 
     u_int16_t           tklen; /* FIXME: spec  u_int32_t? */
     pid_t               token;
+    char               *p;
 
     *rbuflen = 0;
 
@@ -388,6 +393,19 @@ unsigned int ibuflen, *rbuflen;
         break;
     case 3: /* Jaguar */
     case 4:
+       if (ibuflen >= 8 ) {
+           p = ibuf;
+           memcpy( &idlen, ibuf, sizeof(idlen));
+           idlen = ntohl(idlen);
+           ibuf += sizeof(idlen);
+           ibuflen -= sizeof(idlen);
+           ibuf += sizeof(boottime);
+           ibuflen -= sizeof(boottime);
+           if (ibuflen < idlen || idlen > (90-10)) {
+               return AFPERR_PARAM;
+           }
+           server_ipc_write(IPC_GETSESSION, idlen+8, p ); 
+       }
        type = 0;
        break;
     }
@@ -434,6 +452,9 @@ int         ibuflen, *rbuflen;
     }   
     memcpy(&token, ibuf, tklen);
     /* killed old session, not easy */
+    server_ipc_write(IPC_KILLTOKEN, tklen, &token);
+    sleep(1);
+    
     return AFPERR_SESSCLOS;   /* was AFP_OK */
 }
 
@@ -509,7 +530,7 @@ int         ibuflen, *rbuflen;
     if (!len || len > ibuflen)
         return send_reply(obj, AFPERR_BADUAM);
 
-    if ((afp_uam = auth_uamfind(UAM_SERVER_LOGIN, ibuf, len)) == NULL)
+    if (NULL == (afp_uam = auth_uamfind(UAM_SERVER_LOGIN, ibuf, len)) )
         return send_reply(obj, AFPERR_BADUAM);
     ibuf += len;
     ibuflen -= len;
index 749ab69a51f2f8a09fbbbcfd365ec4d68d1706d5..a6375e4eb7df2e08fb5542fdaae8ecbb860119a3 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * $Id: desktop.c,v 1.26.2.3 2003-06-23 10:25:07 didg Exp $
+ * $Id: desktop.c,v 1.26.2.4 2003-07-21 05:50:54 didg Exp $
  *
  * See COPYRIGHT.
  *
@@ -911,7 +911,7 @@ int         ibuflen, *rbuflen;
     clen = min( clen, 199 );
 
     upath = path->u_name;
-    if (check_access(upath, OPENACC_WR ) < 0) {
+    if (!vol_unix_priv(vol) && check_access(upath, OPENACC_WR ) < 0) {
         return AFPERR_ACCESS;
     }
 
@@ -1047,7 +1047,7 @@ int               ibuflen, *rbuflen;
     }
 
     upath = s_path->u_name;
-    if (check_access(upath, OPENACC_WR ) < 0) {
+    if (!vol_unix_priv(vol) && check_access(upath, OPENACC_WR ) < 0) {
         return AFPERR_ACCESS;
     }
 
index 50f0fca27c9d0f648a6a5c179f15c98668081585..c6e7e015875bc4186b4797dcf8eede368b679d6a 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * $Id: directory.c,v 1.71.2.3 2003-05-20 14:49:18 didg Exp $
+ * $Id: directory.c,v 1.71.2.4 2003-07-21 05:50:54 didg Exp $
  *
  * Copyright (c) 1990,1993 Regents of The University of Michigan.
  * All Rights Reserved.  See COPYRIGHT.
@@ -164,6 +164,9 @@ struct dir *dir;
 /* -----------------------------------------
  * if did is not in the cache resolve it with cnid 
  * 
+ * FIXME
+ * OSX call it with bogus id, ie file ID not folder ID,
+ * and we are really bad in this case.
  */
 struct dir *
             dirlookup( vol, did )
@@ -1216,6 +1219,20 @@ char *p;
     return 0;
 }
 
+/* --------------------- */
+int file_access(struct path *path, int mode)
+{
+struct maccess ma;
+
+    accessmode(path->u_name, &ma, curdir, &path->st);
+    if ((mode & OPENACC_WR) && !(ma.ma_user & AR_UWRITE))
+        return -1;
+    if ((mode & OPENACC_RD) && !(ma.ma_user & AR_UREAD))
+        return -1;
+    return 0;
+
+}
+
 /* ------------------------------ 
    (".", curdir)
    (name, dir) with curdir:name == dir, from afp_enumerate
@@ -1403,6 +1420,28 @@ int getdirparams(const struct vol *vol,
             }
             break;
 
+        case DIRPBIT_UNIXPR :
+            aint = htonl(st->st_uid);
+            memcpy( data, &aint, sizeof( aint ));
+            data += sizeof( aint );
+            aint = htonl(st->st_gid);
+            memcpy( data, &aint, sizeof( aint ));
+            data += sizeof( aint );
+       
+           aint = st->st_mode;
+           aint = htonl ( aint & ~S_ISGID );  /* Remove SGID, OSX doesn't like it ... */
+           memcpy( data, &aint, sizeof( aint ));
+           data += sizeof( aint );
+
+            accessmode( upath, &ma, dir , st);
+
+            *data++ = ma.ma_user;
+            *data++ = ma.ma_world;
+            *data++ = ma.ma_group;
+            *data++ = ma.ma_owner;
+            break;
+
+
         default :
             if ( isad ) {
                 ad_close( &ad, ADFLAGS_HF );
@@ -1776,6 +1815,56 @@ int setdirparams(const struct vol *vol,
                 buf += 6;
                 break;
             }
+
+       case DIRPBIT_UNIXPR :
+           /* Skip UID and GID for now, there seems to be now way to set them from an OSX client anyway */
+            buf += sizeof( aint );
+            buf += sizeof( aint );
+
+            change_mdate = 1;
+            change_parent_mdate = 1;
+            memcpy( &aint, buf, sizeof( aint ));
+            buf += sizeof( aint );
+           aint = ntohl (aint);
+            if (curdir->d_did == DIRDID_ROOT)
+                setdeskmode( aint );
+#if 0 /* don't error if we can't set the desktop mode */
+            switch ( errno ) {
+            case EPERM :
+            case EACCES :
+                err = AFPERR_ACCESS;
+                goto setdirparam_done;
+            case EROFS :
+                err = AFPERR_VLOCK;
+                goto setdirparam_done;
+            default :
+                LOG(log_error, logtype_afpd, "setdirparam: setdeskmode: %s",
+                    strerror(errno) );
+                break;
+                err = AFPERR_PARAM;
+                goto setdirparam_done;
+            }
+#endif /* 0 */
+
+            if ( setdirunixmode( aint, vol_noadouble(vol),
+                         (vol->v_flags & AFPVOL_DROPBOX)) < 0 ) {
+                switch ( errno ) {
+                case EPERM :
+                case EACCES :
+                    err = AFPERR_ACCESS;
+                    goto setdirparam_done;
+                case EROFS :
+                    err = AFPERR_VLOCK;
+                    goto setdirparam_done;
+                default :
+                    LOG(log_error, logtype_afpd, "setdirparam: setdirmode: %s",
+                        strerror(errno) );
+                    err = AFPERR_PARAM;
+                    goto setdirparam_done;
+                }
+            }
+            break;
+
         default :
             err = AFPERR_BITMAP;
             goto setdirparam_done;
index 832e28c03c55d3ab3eab33f932fbae125b19ebdc..b6e7cd1b66d84fedbbc1ff9b9c0b89dba1540ad0 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * $Id: directory.h,v 1.13.2.3 2003-05-20 14:49:19 didg Exp $
+ * $Id: directory.h,v 1.13.2.4 2003-07-21 05:50:54 didg Exp $
  *
  * Copyright (c) 1990,1991 Regents of The University of Michigan.
  * All Rights Reserved.
@@ -137,6 +137,7 @@ extern int path_isadir(struct path *o_path);
 #define DIRPBIT_GID    11
 #define DIRPBIT_ACCESS 12
 #define DIRPBIT_PDINFO  13         /* ProDOS Info */
+#define DIRPBIT_UNIXPR  15
 
 /* directory attribute bits (see file.h for other bits) */
 #define ATTRBIT_EXPFOLDER   (1 << 1) /* shared point */
@@ -212,6 +213,7 @@ typedef int (*dir_loop)(struct dirent *, char *, void *);
 extern int  for_each_dirent __P((const struct vol *, char *, dir_loop , void *));
 
 extern int  check_access __P((char *name , int mode));
+extern int file_access   __P((struct path *path, int mode));
 
 extern int netatalk_unlink __P((const char *name));
 
index 8b5cf25b780745e2f671777ddc13dcc780eeba98..8a7fe25448b5e0f27f063cd299a3e99e764e5423 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * $Id: file.c,v 1.92.2.1 2003-06-05 08:48:18 didg Exp $
+ * $Id: file.c,v 1.92.2.2 2003-07-21 05:50:54 didg Exp $
  *
  * Copyright (c) 1990,1993 Regents of The University of Michigan.
  * All Rights Reserved.  See COPYRIGHT.
@@ -58,6 +58,7 @@ char *strchr (), *strrchr ();
 #include "file.h"
 #include "filedir.h"
 #include "globals.h"
+#include "unix.h"
 
 /* the format for the finderinfo fields (from IM: Toolbox Essentials):
  * field         bytes        subfield    bytes
@@ -142,7 +143,7 @@ char *set_name(const struct vol *vol, char *data, char *name, u_int32_t utf8)
         if (aint > 255)  /* FIXME safeguard, anyway if no ascii char it's game over*/
            aint = 255;
 
-        utf8 = 0;    /* mac roman hint */
+        utf8 = 0;         /* htonl(utf8) */
         memcpy(data, &utf8, sizeof(utf8));
         data += sizeof(utf8);
         
@@ -262,6 +263,8 @@ int getmetadata(struct vol *vol,
     u_char              achar, fdType[4];
     u_int32_t           utf8 = 0;
     struct stat         *st;
+    struct maccess     ma;
+
 #ifdef DEBUG
     LOG(log_info, logtype_afpd, "begin getmetadata:");
 #endif /* DEBUG */
@@ -460,6 +463,26 @@ int getmetadata(struct vol *vol,
             memcpy(data, &aint, sizeof( aint ));
             data += sizeof( aint );
             break;
+        case FILPBIT_UNIXPR :
+            aint = htonl(st->st_uid);
+            memcpy( data, &aint, sizeof( aint ));
+            data += sizeof( aint );
+            aint = htonl(st->st_gid);
+            memcpy( data, &aint, sizeof( aint ));
+            data += sizeof( aint );
+
+            aint = htonl(st->st_mode);
+            memcpy( data, &aint, sizeof( aint ));
+            data += sizeof( aint );
+
+            accessmode( upath, &ma, dir , st);
+
+            *data++ = ma.ma_user;
+            *data++ = ma.ma_world;
+            *data++ = ma.ma_group;
+            *data++ = ma.ma_owner;
+            break;
+
         default :
             return( AFPERR_BITMAP );
         }
@@ -769,7 +792,7 @@ int setfilparams(struct vol *vol,
         adp = &ad;
     }
 
-    if (check_access(upath, OPENACC_WR ) < 0) {
+    if (!vol_unix_priv(vol) && check_access(upath, OPENACC_WR ) < 0) {
         return AFPERR_ACCESS;
     }
 
@@ -871,6 +894,19 @@ int setfilparams(struct vol *vol,
                 break;
             }
             /* fallthrough */
+        case FILPBIT_UNIXPR :
+           /* Skip the UIG/GID, no way to set them from OSX clients */
+            buf += sizeof( aint );
+            buf += sizeof( aint );
+
+            change_mdate = 1;
+            change_parent_mdate = 1;
+            memcpy( &aint, buf, sizeof( aint ));
+            buf += sizeof( aint );
+            aint = ntohl (aint);
+
+            setfilemode(path, aint);
+            break;
         default :
             err = AFPERR_BITMAP;
             goto setfilparam_done;
index bd45bf67813179b288723d4944cfefb91d397dcb..b3179db45d4d0285833817ccf1f8a5718489b2a8 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * $Id: file.h,v 1.16.2.1 2003-06-23 10:25:07 didg Exp $
+ * $Id: file.h,v 1.16.2.2 2003-07-21 05:50:54 didg Exp $
  *
  * Copyright (c) 1990,1991 Regents of The University of Michigan.
  * All Rights Reserved.
@@ -52,6 +52,7 @@ extern const u_char   ufinderi[];
 #define FILPBIT_EXTDFLEN 11
 #define FILPBIT_PDINFO   13    /* ProDOS Info/ UTF8 name */
 #define FILPBIT_EXTRFLEN 14
+#define FILPBIT_UNIXPR   15
 
 /* attribute bits. (d) = directory attribute bit as well. */
 #define ATTRBIT_INVISIBLE (1<<0)  /* invisible (d) */
index 4917d42fb5ae61bcfde72646be7ad277ab25747c..24e1e1572fe41ed58d83ca034a61c62bc861eb9b 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * $Id: filedir.c,v 1.45.2.1 2003-05-10 10:33:16 didg Exp $
+ * $Id: filedir.c,v 1.45.2.2 2003-07-21 05:50:54 didg Exp $
  *
  * Copyright (c) 1990,1993 Regents of The University of Michigan.
  * All Rights Reserved.  See COPYRIGHT.
@@ -752,7 +752,8 @@ int         ibuflen, *rbuflen;
         }
         else
 #endif /* DROPKLUDGE */
-            if (!isdir) {
+            /* if unix priv don't try to match perm with dest folder */
+            if (!isdir && !vol_unix_priv(vol)) {
                 int  admode = ad_mode("", 0777);
 
                 setfilmode(upath, admode, NULL);
index ddc01fb31c2a7bd5ffea9391901d0e872b9d3573..7a60db017fa5b8f7f0210e718ac1102b7126796b 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * $Id: fork.c,v 1.51 2003-03-15 01:34:35 didg Exp $
+ * $Id: fork.c,v 1.51.2.1 2003-07-21 05:50:54 didg Exp $
  *
  * Copyright (c) 1990,1993 Regents of The University of Michigan.
  * All Rights Reserved.  See COPYRIGHT.
@@ -329,8 +329,15 @@ int                ibuflen, *rbuflen;
     }
     /* FIXME should we check it first ? */
     upath = s_path->u_name;
-    if (check_access(upath, access ) < 0) {
-        return AFPERR_ACCESS;
+    if (!vol_unix_priv(vol)) {
+        if (check_access(upath, access ) < 0) {
+            return AFPERR_ACCESS;
+        }
+    }
+    else {
+        if (file_access(s_path, access ) < 0) {
+            return AFPERR_ACCESS;
+        }
     }
 
     st   = &s_path->st;
index 41b067e6abae0f36195deb3aec2db16651b057f8..9cb09f4a7bd44221e8a15773cfd74e57a0c3497d 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * $Id: globals.h,v 1.18.2.1 2003-05-26 11:17:25 didg Exp $
+ * $Id: globals.h,v 1.18.2.2 2003-07-21 05:50:54 didg Exp $
  *
  * Copyright (c) 1990,1993 Regents of The University of Michigan.
  * All Rights Reserved.  See COPYRIGHT.
@@ -72,6 +72,7 @@ struct afp_options {
     char *k5service, *k5realm;
     mode_t umask;
     mode_t save_mask;
+    int    sleep;
 #ifdef ADMIN_GRP
     gid_t admingid;
 #endif /* ADMIN_GRP */
@@ -88,6 +89,7 @@ typedef struct AFPObj {
     void (*logout)(void), (*exit)(int);
     int (*reply)(void *, int);
     int (*attention)(void *, AFPUserBytes);
+    void (*sleep)(void);
     /* to prevent confusion, only use these in afp_* calls */
     char oldtmp[AFPOBJ_TMPSIZ + 1], newtmp[AFPOBJ_TMPSIZ + 1];
     void *uam_cookie; /* cookie for uams */
index 02c3e14847650a2da18434b28be1c520e835dc7b..c6446141e1c84819f909da73193e1e34bbd6ccab 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * $Id: main.c,v 1.20.4.1 2003-05-26 11:17:25 didg Exp $
+ * $Id: main.c,v 1.20.4.2 2003-07-21 05:50:54 didg Exp $
  *
  * Copyright (c) 1990,1993 Regents of The University of Michigan.
  * All Rights Reserved.  See COPYRIGHT.
@@ -41,6 +41,7 @@
 #include <atalk/paths.h>
 #include <atalk/util.h>
 #include <atalk/server_child.h>
+#include <atalk/server_ipc.h>
 
 #include "globals.h"
 #include "afp_config.h"
@@ -63,6 +64,7 @@ struct afp_options default_options;
 static AFPConfig *configs;
 static server_child *server_children;
 static fd_set save_rfds;
+static int    Ipc_fd = -1;
 
 #ifdef TRU64
 void afp_get_cmdline( int *ac, char ***av)
@@ -78,6 +80,25 @@ static void afp_exit(const int i)
     exit(i);
 }
 
+/* ------------------
+   initialize fd set we are waiting for.
+*/
+static void set_fd(int ipc_fd)
+{
+    AFPConfig   *config;
+
+    FD_ZERO(&save_rfds);
+    for (config = configs; config; config = config->next) {
+        if (config->fd < 0) /* for proxies */
+            continue;
+        FD_SET(config->fd, &save_rfds);
+    }
+    if (ipc_fd >= 0) {
+        FD_SET(ipc_fd, &save_rfds);
+    }
+}
+/* ------------------ */
 static void afp_goaway(int sig)
 {
 
@@ -107,12 +128,7 @@ static void afp_goaway(int sig)
                 LOG(log_error, logtype_afpd, "config re-read: no servers configured");
                 afp_exit(1);
             }
-            FD_ZERO(&save_rfds);
-            for (config = configs; config; config = config->next) {
-                if (config->fd < 0)
-                    continue;
-                FD_SET(config->fd, &save_rfds);
-            }
+            set_fd(Ipc_fd);
         } else {
             LOG(log_info, logtype_afpd, "disallowing logins");
             auth_unload();
@@ -147,6 +163,7 @@ char        **av;
 {
     AFPConfig           *config;
     fd_set              rfds;
+    void                *ipc;
     struct sigaction   sv;
     sigset_t            sigs;
 
@@ -229,13 +246,11 @@ char      **av;
     }
     sigprocmask(SIG_UNBLOCK, &sigs, NULL);
 
-    /* watch atp and dsi sockets. */
-    FD_ZERO(&save_rfds);
-    for (config = configs; config; config = config->next) {
-        if (config->fd < 0) /* for proxies */
-            continue;
-        FD_SET(config->fd, &save_rfds);
+    /* watch atp, dsi sockets and ipc parent/child file descriptor. */
+    if ((ipc = server_ipc_create())) {
+        Ipc_fd = server_ipc_parent(ipc);
     }
+    set_fd(Ipc_fd);
 
     /* wait for an appleshare connection. parent remains in the loop
      * while the children get handled by afp_over_{asp,dsi}.  this is
@@ -251,7 +266,9 @@ char        **av;
             LOG(log_error, logtype_afpd, "main: can't wait for input: %s", strerror(errno));
             break;
         }
-
+        if (Ipc_fd >=0 && FD_ISSET(Ipc_fd, &rfds)) {
+            server_ipc_read(server_children);
+       }
         for (config = configs; config; config = config->next) {
             if (config->fd < 0)
                 continue;
index 72b634e63898c9465b951ee98ccbd9673298e65a..8c22d752df85663972570eb4dfa6b06792246dd1 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * $Id: unix.c,v 1.43 2003-03-09 19:55:35 didg Exp $
+ * $Id: unix.c,v 1.43.2.1 2003-07-21 05:50:54 didg Exp $
  *
  * Copyright (c) 1990,1993 Regents of The University of Michigan.
  * All Rights Reserved.  See COPYRIGHT.
@@ -22,9 +22,8 @@
 #include <limits.h>
 #include <atalk/adouble.h>
 #include <atalk/afp.h>
-
 /* STDC check */
-#if STDC_HEADERS
+#ifdef STDC_HEADERS
 #include <string.h>
 #else /* STDC_HEADERS */
 #ifndef HAVE_STRCHR
@@ -45,6 +44,7 @@ char *strchr (), *strrchr ();
 #include "directory.h"
 #include "volume.h"
 #include "unix.h"
+#include "fork.h"
 
 /*
  * Get the free space on a partition.
@@ -107,10 +107,10 @@ mode_t    bits;
 
     mbits = 0;
 
-    mbits |= ( bits & ( S_IREAD >> 6 )) ? (AR_UREAD | AR_USEARCH) : 0;
+    mbits |= ( bits & ( S_IREAD >> 6 ))  ? AR_UREAD  : 0;
     mbits |= ( bits & ( S_IWRITE >> 6 )) ? AR_UWRITE : 0;
-    /* Do we really need this?
-        mbits |= ( bits & ( S_IEXEC >> 6) ) ? AR_USEARCH : 0; */
+    /* Do we really need this? */
+    mbits |= ( bits & ( S_IEXEC >> 6) ) ? AR_USEARCH : 0;
 
     return( mbits );
 }
@@ -363,6 +363,26 @@ const mode_t       mode;
     return( 0 );
 }
 
+/* --------------------- */
+int setfilemode (path, mode)
+struct path* path;
+mode_t mode;
+{
+    if (!path->st_valid) {
+        of_stat(path);
+    }
+
+    if (path->st_errno) {
+        return -1;
+    }
+        
+    if (setfilmode( path->u_name, mode, &path->st) < 0)
+        return -1;
+    /* we need to set write perm if read set for resource fork */
+    return setfilmode(ad_path( path->u_name, ADFLAGS_HF ), ad_hf_mode(mode), &path->st);
+}
+
+/* --------------------- */
 int setfilmode(name, mode, st)
 char * name;
 mode_t mode;
@@ -384,6 +404,21 @@ mode_t mask = S_IRUSR |S_IWUSR | S_IRGRP | S_IWGRP |S_IROTH | S_IWOTH;
    return 0;
 }
 
+/* --------------------- */
+int setdirunixmode( mode, noadouble, dropbox )
+const mode_t mode;
+const int noadouble;
+const int dropbox;
+{
+    if ( stickydirmode(".AppleDouble", DIRBITS | mode, dropbox) < 0 && !noadouble)
+        return  -1 ;
+
+    if ( stickydirmode(".", DIRBITS | mode, dropbox) < 0 )
+        return -1;
+    return 0;
+}
+
+/* --------------------- */
 int setdirmode( mode, noadouble, dropbox )
 const mode_t mode;
 const int noadouble;
@@ -675,10 +710,12 @@ recursive_chown_end:
 /* This is equivalent of unix rename(). */
 int unix_rename(const char *oldpath, const char *newpath)
 {
+#if 0
        char pd_name[PATH_MAX+1];
        int i;
         struct stat pd_stat;
         uid_t uid;
+#endif
 
        if (rename(oldpath, newpath) < 0)
                return -1;
index 3eba6c471b38fa5b292de546aeea935de47c8035..aa95930ee072b6862079ff8104b4c3488a782324 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * $Id: unix.h,v 1.12 2003-01-07 15:55:22 rlewczuk Exp $
+ * $Id: unix.h,v 1.12.2.1 2003-07-21 05:50:54 didg Exp $
  */
 
 #ifndef AFPD_UNIX_H
@@ -98,15 +98,17 @@ extern int uquota_getvolspace __P((const struct vol *, VolSpace *, VolSpace *,
 
 extern struct afp_options default_options;
 
-extern int gmem         __P((const gid_t));
-extern int setdeskmode  __P((const mode_t));
-extern int setdirmode   __P((const mode_t, const int, const int));
-extern int setdeskowner __P((const uid_t, const gid_t));
-extern int setdirowner  __P((const uid_t, const gid_t, const int));
-extern int setfilmode   __P((char *, mode_t , struct stat *));
-extern int unix_rename  __P((const char *oldpath, const char *newpath));
-
-extern void accessmode  __P((char *, struct maccess *, struct dir *, struct stat *));
+extern int gmem            __P((const gid_t));
+extern int setdeskmode      __P((const mode_t));
+extern int setdirunixmode   __P((const mode_t, const int, const int));
+extern int setdirmode       __P((const mode_t, const int, const int));
+extern int setdeskowner     __P((const uid_t, const gid_t));
+extern int setdirowner      __P((const uid_t, const gid_t, const int));
+extern int setfilmode       __P((char *, mode_t , struct stat *));
+extern int setfilemode      __P((struct path*, const mode_t));
+extern int unix_rename      __P((const char *oldpath, const char *newpath));
+
+extern void accessmode      __P((char *, struct maccess *, struct dir *, struct stat *));
 
 #ifdef AFS     
     #define accessmode afsmode
index 466be9bb92258ebef348689a81ffcf964dd479ea..db0f5017c1acc4f20b44746dba1e7ac0db272099 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * $Id: volume.c,v 1.51.2.6 2003-06-23 10:25:08 didg Exp $
+ * $Id: volume.c,v 1.51.2.7 2003-07-21 05:50:54 didg Exp $
  *
  * Copyright (c) 1990,1993 Regents of The University of Michigan.
  * All Rights Reserved.  See COPYRIGHT.
@@ -432,6 +432,9 @@ static void volset(struct vol_option *options, struct vol_option *save,
                options[VOLOPT_PREEXEC].i_value = 1;
             else if (strcasecmp(p, "root_preexec_close") == 0)
                options[VOLOPT_ROOTPREEXEC].i_value = 1;
+            else if (strcasecmp(p, "upriv") == 0)
+                options[VOLOPT_FLAGS].i_value |= AFPVOL_UNIX_PRIV;
+
             p = strtok(NULL, ",");
         }
 
@@ -1175,6 +1178,8 @@ int               *buflen;
             ashort |= VOLPBIT_ATTR_CATSEARCH;
             if (afp_version >= 30) {
                 ashort |= VOLPBIT_ATTR_UTF8;
+               if (vol->v_flags & AFPVOL_UNIX_PRIV)
+                   ashort |= VOLPBIT_ATTR_UNIXPRIV;
             }
             ashort = htons(ashort);
             memcpy(data, &ashort, sizeof( ashort ));
@@ -1403,7 +1408,8 @@ int       ibuflen, *rbuflen;
            completely worked this out, but it's related to booting
            from the server.  Support for that function is a ways
            off.. <shirsch@ibm.net> */
-        *data++ |= (volume->v_flags & AFPVOL_A2VOL) ? AFPSRVR_CONFIGINFO : 0;
+        *data |= (volume->v_flags & AFPVOL_A2VOL) ? AFPSRVR_CONFIGINFO : 0;
+        *data++ |= 0; /* UNIX PRIVS BIT ..., OSX doesn't seem to use it, so we don't either */
         len = strlen( volume->v_name );
         *data++ = len;
         memcpy(data, volume->v_name, len );
index e32130d8cf1969bc29c3cd19a82cc9c0b908be66..debca3774db100535a1d2357f029c02e8ad38882 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * $Id: volume.h,v 1.19.2.4 2003-06-23 10:25:08 didg Exp $
+ * $Id: volume.h,v 1.19.2.5 2003-07-21 05:50:54 didg Exp $
  *
  * Copyright (c) 1990,1994 Regents of The University of Michigan.
  * All Rights Reserved.  See COPYRIGHT.
@@ -118,6 +118,7 @@ this is going away. */
 #define AFPVOL_NOFILEID  (1 << 15)  /* don't advertise createid resolveid and deleteid calls */
 #define AFPVOL_UTF8      (1 << 16)  /* unix name are in UTF8 */
 #define AFPVOL_NOSTAT    (1 << 17)  /* unix name are in UTF8 */
+#define AFPVOL_UNIX_PRIV (1 << 18)  /* support unix privileges */
 
 /* FPGetSrvrParms options */
 #define AFPSRVR_CONFIGINFO     (1 << 0)
@@ -178,6 +179,7 @@ int wincheck(const struct vol *vol, const char *path);
 #define vol_utf8(vol) (0)
 #define utf8_encoding() (0)
 #endif
+#define vol_unix_priv(vol) (afp_version >= 30 && ((vol)->v_flags & AFPVOL_UNIX_PRIV))
 
 extern struct vol      *getvolbyvid __P((const u_int16_t));
 extern int              ustatfs_getvolspace __P((const struct vol *,
index c983a863400a2b6d82b4624496244a89a5416e13..7112e06964ffbd6633f16000443d35ba0bd43725 100644 (file)
@@ -30,6 +30,10 @@ extern int server_child_remove __P((server_child *, const int, const pid_t));
 extern void server_child_free __P((server_child *));
 
 extern void server_child_kill __P((server_child *, const int, const int));
+extern void server_child_kill_one __P((server_child *children, const int forkid, const pid_t pid));
+extern void server_child_kill_one_by_id __P((server_child *children, const int forkid, const pid_t pid, 
+                                               const u_int32_t len, char *id, u_int32_t boottime));
+
 extern void server_child_setup __P((server_child *, const int, void (*)()));
 extern void server_child_handler __P((server_child *));
 
diff --git a/include/atalk/server_ipc.h b/include/atalk/server_ipc.h
new file mode 100644 (file)
index 0000000..b462c6f
--- /dev/null
@@ -0,0 +1,16 @@
+
+#include <atalk/server_child.h>
+
+#define IPC_KILLTOKEN   1
+#define IPC_GETSESSION  2
+
+void *server_ipc_create(void);
+int server_ipc_child(void *obj);
+int server_ipc_parent(void *obj);
+int server_ipc_read(server_child *children);
+int server_ipc_write(uint16_t command, int len, void *token);
+
+
+
+
+
index 8ebacf304885cff0fe3a4a96f66ebcfe137f06c4..21ae9e822a0a752ec386117551577bc054aabc1b 100644 (file)
@@ -11,6 +11,7 @@ libutil_la_SOURCES = \
        logger.c        \
        module.c        \
        server_child.c  \
+       server_ipc.c    \
        server_lock.c   \
        strcasestr.c    \
        strdicasecmp.c  
index d443eb2b0876eed74482e8dd3c20ef8b9d621b3e..a4eb0a272643b512f030ac0491d58908c4521bcd 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * $Id: server_child.c,v 1.7 2002-10-07 19:14:41 didg Exp $
+ * $Id: server_child.c,v 1.7.4.1 2003-07-21 05:50:54 didg Exp $
  *
  * Copyright (c) 1997 Adrian Sun (asun@zoology.washington.edu)
  * All rights reserved. See COPYRIGHT.
@@ -43,6 +43,9 @@
 #ifndef WIFSIGNALED
 #define WIFSIGNALED(status) (!WIFSTOPPED(status) && !WIFEXITED(status)) 
 #endif
+#ifndef WTERMSIG
+#define WTERMSIG(status)      ((status) & 0x7f)
+#endif
 
 #include <atalk/server_child.h>
 
 
 struct server_child_data {
   pid_t pid; 
+  u_int32_t  time;
+  u_int32_t idlen;
+  
+  char *clientid;
   struct server_child_data **prevp, *next;
 };
 
@@ -176,6 +183,9 @@ int server_child_remove(server_child *children, const int forkid,
     return 0;
   
   unhash_child(child);
+  if (child->clientid) {
+      free(child->clientid);
+  }
   free(child);
   children->count--;
   return 1;
@@ -195,6 +205,9 @@ void server_child_free(server_child *children)
       child = fork->table[j]; /* start at the beginning */
       while (child) {
        tmp = child->next;
+        if (child->clientid) {
+            free(child->clientid);
+        }
        free(child);
        child = tmp;
       }
@@ -224,6 +237,72 @@ void server_child_kill(server_child *children, const int forkid,
   }
 }
 
+/* send kill to a child processes.
+ * a plain-old linked list 
+ * FIXME use resolve_child ?
+ */
+void server_child_kill_one(server_child *children, const int forkid, const pid_t pid)
+{
+  server_child_fork *fork;
+  struct server_child_data *child, *tmp;
+  int i;
+
+  fork = (server_child_fork *) children->fork + forkid;
+  for (i = 0; i < CHILD_HASHSIZE; i++) {
+    child = fork->table[i];
+    while (child) {
+      tmp = child->next;
+      if (child->pid == pid) {
+          kill(child->pid, SIGTERM);
+      }
+      child = tmp;
+    }
+  }
+}
+
+
+/* see if there is a process for the same mac     */
+/* if the times don't match mac has been rebooted */
+void server_child_kill_one_by_id(server_child *children, const int forkid, const pid_t pid, 
+          const u_int32_t idlen, char *id, u_int32_t boottime)
+{
+  server_child_fork *fork;
+  struct server_child_data *child, *tmp;
+  int i;
+
+  fork = (server_child_fork *) children->fork + forkid;
+  for (i = 0; i < CHILD_HASHSIZE; i++) {
+    child = fork->table[i];
+    while (child) {
+      tmp = child->next;
+      if ( child->pid != pid) {
+          if ( child->idlen == idlen && !memcmp(child->clientid, id, idlen)) {
+            if ( child->time != boottime ) {
+                 kill(child->pid, SIGTERM);
+                 LOG(log_info, logtype_default, "Disconnecting old session %d, client rebooted.",  child->pid);
+            }
+            else {
+                 LOG(log_info, logtype_default, "WARNING: 2 connections (%d, %d), boottime identical, don't know if one needs to be disconnected.");
+            } 
+               
+         }
+      }
+      else 
+      {
+         child->time = boottime;
+         /* free old token if any */
+         if (child->clientid) {
+             free(child->clientid);
+         }
+         child->idlen = idlen;
+          child->clientid = id;
+         LOG(log_info, logtype_default, "Setting clientid (len %d) for %d, boottime %X", idlen, child->pid, boottime);
+      }
+      child = tmp;
+    }
+  }
+}
+
 /* for extra cleanup if necessary */
 void server_child_setup(server_child *children, const int forkid,
                          void (*fcn)(const pid_t))
@@ -266,7 +345,8 @@ void server_child_handler(server_child *children)
     } else {
       if (WIFSIGNALED(status))
       { 
-       LOG(log_info, logtype_default, "server_child[%d] %d killed", i, pid);
+       LOG(log_info, logtype_default, "server_child[%d] %d killed by signal %d", i, pid,  
+              WTERMSIG (status));
       }
       else
       {
diff --git a/libatalk/util/server_ipc.c b/libatalk/util/server_ipc.c
new file mode 100644 (file)
index 0000000..58eba00
--- /dev/null
@@ -0,0 +1,187 @@
+/*
+ * $Id: server_ipc.c,v 1.1.4.1 2003-07-21 05:50:55 didg Exp $
+ *
+ * All rights reserved. See COPYRIGHT.
+ *
+ *
+ * ipc between parent and children.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif 
+
+#include <sys/types.h>
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif 
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <atalk/server_child.h>
+#include <atalk/server_ipc.h>
+#include <atalk/logger.h>
+
+typedef struct ipc_header {
+       u_int16_t command;
+        pid_t    child_pid;
+        u_int32_t len;
+       char      *msg;
+} ipc_header;
+
+static int pipe_fd[2];
+   
+void *server_ipc_create(void)
+{
+    if (pipe(pipe_fd)) {
+        return NULL;
+    }
+    return &pipe_fd;
+}
+
+/* ----------------- */
+int server_ipc_child(void *obj)
+{
+    /* close input */
+    close(pipe_fd[0]);
+    return pipe_fd[1];
+}
+
+/* ----------------- */
+int server_ipc_parent(void *obj)
+{
+    return pipe_fd[0];
+}
+
+/* ----------------- */
+int ipc_kill_token (struct ipc_header *ipc, server_child *children)
+{
+    pid_t pid;
+
+    if (ipc->len != sizeof(pid_t)) {
+        return -1;
+    }
+    /* assume signals SA_RESTART set */
+    memcpy (&pid, ipc->msg, sizeof(pid_t));
+
+    LOG(log_info, logtype_default, "child %d disconnected", pid); 
+    server_child_kill_one(children, CHILD_DSIFORK, pid);
+    return 0;
+}
+
+/* ----------------- */
+int ipc_get_session (struct ipc_header *ipc, server_child *children)
+{
+    u_int32_t boottime;
+    u_int32_t idlen;
+    char     *clientid, *p;
+
+
+    if (ipc->len < (sizeof(idlen) + sizeof(boottime)) ) {
+       return -1;
+    }
+    p = ipc->msg;
+    memcpy (&idlen, p, sizeof(idlen));
+    idlen = ntohl (idlen);
+    p += sizeof(idlen); 
+
+    memcpy (&boottime, p, sizeof(boottime));
+    p += sizeof(boottime);
+    
+    if (ipc->len < idlen + sizeof(idlen) + sizeof(boottime)) {
+       return -1;
+    }
+    if (NULL == (clientid = (char*) malloc(idlen)) ) {
+       return -1;
+    }
+    memcpy (clientid, p, idlen);
+  
+    server_child_kill_one_by_id (children, CHILD_DSIFORK, ipc->child_pid, idlen, clientid, boottime);
+    /* FIXME byte to ascii if we want to log clientid */
+    LOG (log_info, logtype_afpd, "ipc_get_session: len: %u, idlen %d, time %x", ipc->len, idlen, boottime); 
+    return 0;
+}
+
+#define IPC_HEADERLEN 10
+#define IPC_MAXMSGSIZE 90
+
+/* ----------------- */
+int server_ipc_read(server_child *children)
+{
+    int       ret = 0;
+    struct ipc_header ipc;
+    char      buf[IPC_MAXMSGSIZE], *p;
+
+    if ((ret = read(pipe_fd[0], buf, IPC_HEADERLEN)) != IPC_HEADERLEN) {
+       LOG (log_info, logtype_afpd, "Reading IPC header failed (%u of %u  bytes read)", ret, IPC_HEADERLEN);
+       return -1;
+    } 
+
+    p = buf;
+    memcpy(&ipc.command, p, sizeof(ipc.command));
+    p += sizeof(ipc.command);
+    memcpy(&ipc.child_pid, p, sizeof(ipc.child_pid));
+    p += sizeof(ipc.child_pid);
+    memcpy(&ipc.len, p, sizeof(ipc.len));
+
+    /* This should never happen */
+    if (ipc.len > (IPC_MAXMSGSIZE - IPC_HEADERLEN))
+    {
+       LOG (log_info, logtype_afpd, "IPC message exceeds allowed size (%u)", ipc.len);
+       return -1;
+    }
+
+    memset (buf, 0, IPC_MAXMSGSIZE);
+    if ( ipc.len != 0) {
+           if ((ret = read(pipe_fd[0], buf, ipc.len)) != ipc.len) {
+               LOG (log_info, logtype_afpd, "Reading IPC message failed (%u of %u  bytes read)", ret, ipc.len);
+               return -1;
+       }        
+    }
+    ipc.msg = buf;
+    
+    LOG (log_info, logtype_afpd, "ipc_read: command: %u, pid: %u, len: %u", ipc.command, ipc.child_pid, ipc.len); 
+
+    switch (ipc.command)
+    {
+       case IPC_KILLTOKEN:
+               return (ipc_kill_token(&ipc, children));
+               break;
+       case IPC_GETSESSION:
+               return (ipc_get_session(&ipc, children));
+               break;
+       default:
+               LOG (log_info, logtype_afpd, "ipc_read: unknown command: %d", ipc.command);
+               return -1;
+    }
+
+}
+
+/* ----------------- */
+int server_ipc_write( u_int16_t command, int len, void *msg)
+{
+   char block[IPC_MAXMSGSIZE], *p;
+   pid_t pid;
+   p = block;
+
+   memset ( p, 0 , IPC_MAXMSGSIZE);
+   if (len + IPC_HEADERLEN > IPC_MAXMSGSIZE)
+       return -1;
+
+   memcpy(p, &command, sizeof(command));
+   p   += sizeof(command);
+
+   pid = getpid();
+   memcpy(p, &pid, sizeof(pid_t));
+   p += sizeof(pid_t);
+
+   memcpy(p, &len, 4);
+   p += 4;
+
+   memcpy(p, msg, len);
+
+   LOG (log_info, logtype_afpd, "ipc_write: command: %u, pid: %u, msglen: %u", command, pid, len); 
+   return write(pipe_fd[1], block, len+IPC_HEADERLEN );
+}
+