fixes for -r and -w.
authorRalph Campbell <ralph@ucbvax.Berkeley.EDU>
Wed, 2 Nov 1983 06:29:45 +0000 (22:29 -0800)
committerRalph Campbell <ralph@ucbvax.Berkeley.EDU>
Wed, 2 Nov 1983 06:29:45 +0000 (22:29 -0800)
SCCS-vsn: usr.bin/rdist/defs.h 4.7
SCCS-vsn: usr.bin/rdist/docmd.c 4.8
SCCS-vsn: usr.bin/rdist/expand.c 4.5
SCCS-vsn: usr.bin/rdist/main.c 4.8
SCCS-vsn: usr.bin/rdist/server.c 4.7

usr/src/usr.bin/rdist/defs.h
usr/src/usr.bin/rdist/docmd.c
usr/src/usr.bin/rdist/expand.c
usr/src/usr.bin/rdist/main.c
usr/src/usr.bin/rdist/server.c

index 1f62f5d..1702017 100644 (file)
@@ -1,4 +1,4 @@
-/*     defs.h  4.6     83/10/26        */
+/*     defs.h  4.7     83/11/01        */
 
 #include <stdio.h>
 #include <ctype.h>
 
 #include <stdio.h>
 #include <ctype.h>
@@ -44,8 +44,7 @@
 #define WHOLE  0x2
 #define YOUNGER        0x4
 #define COMPARE        0x8
 #define WHOLE  0x2
 #define YOUNGER        0x4
 #define COMPARE        0x8
-#define STRIP  0x10
-#define REMOVE 0x20
+#define REMOVE 0x10
 
 #define ISDIR(m) (((m) & S_IFMT) == S_IFDIR)
 
 
 #define ISDIR(m) (((m) & S_IFMT) == S_IFDIR)
 
@@ -70,6 +69,8 @@ extern int iamremote;         /* acting as remote server */
 extern int filec;              /* number of files to update */
 extern char **filev;           /* list of files/directories to update */
 extern char tmpfile[];         /* file name for logging changes */
 extern int filec;              /* number of files to update */
 extern char **filev;           /* list of files/directories to update */
 extern char tmpfile[];         /* file name for logging changes */
+extern struct passwd *pw;      /* pointer to static area used by getpwent */
+extern struct group *gr;       /* pointer to static area used by getgrent */
 extern char host[];            /* host name of master copy */
 extern char *rhost;            /* host name of remote being updated */
 extern struct block *except;   /* list of files to exclude */
 extern char host[];            /* host name of master copy */
 extern char *rhost;            /* host name of remote being updated */
 extern struct block *except;   /* list of files to exclude */
index 5ec716a..1ef8233 100644 (file)
@@ -1,5 +1,5 @@
 #ifndef lint
 #ifndef lint
-static char *sccsid = "@(#)docmd.c     4.7 (Berkeley) 83/10/27";
+static char *sccsid = "@(#)docmd.c     4.8 (Berkeley) 83/11/01";
 #endif
 
 #include "defs.h"
 #endif
 
 #include "defs.h"
@@ -14,8 +14,6 @@ dohcmds(files, hosts, cmds)
 {
        register struct block *h, *f, *c;
        register char **cpp;
 {
        register struct block *h, *f, *c;
        register char **cpp;
-       static struct block excpt = { EXCEPT };
-       char *cp;
        int n, ddir;
 
        if (debug)
        int n, ddir;
 
        if (debug)
@@ -31,28 +29,10 @@ dohcmds(files, hosts, cmds)
                error("empty list of hosts to be updated\n");
                return;
        }
                error("empty list of hosts to be updated\n");
                return;
        }
+       if (!mkexceptlist(cmds))
+               return;
+
        ddir = files->b_next != NULL;
        ddir = files->b_next != NULL;
-       f = NULL;
-       except = NULL;
-       for (c = cmds; c != NULL; c = c->b_next) {
-               if (c->b_type != EXCEPT)
-                       continue;
-               if (except == NULL)
-                       except = &excpt;
-               for (h = c->b_args; h != NULL; h = h->b_next) {
-                       cp = h->b_name;
-                       if (*cp == '~') {
-                               (void) exptilde(buf, cp);
-                               cp = buf;
-                       }
-                       if (f == NULL)
-                               except->b_args = f = expand(makeblock(NAME, cp), 0);
-                       else
-                               f->b_next = expand(makeblock(NAME, cp), 0);
-                       while (f->b_next != NULL)
-                               f = f->b_next;
-               }
-       }
 
        for (h = hosts; h != NULL; h = h->b_next) {
                if (!qflag)
 
        for (h = hosts; h != NULL; h = h->b_next) {
                if (!qflag)
@@ -80,13 +60,12 @@ dohcmds(files, hosts, cmds)
                                if (c->b_type != INSTALL)
                                        continue;
                                n++;
                                if (c->b_type != INSTALL)
                                        continue;
                                n++;
-                               if (c->b_name == NULL)
-                                       install(f->b_name, f->b_name, 0, c->b_options);
-                               else
-                                       install(f->b_name, c->b_name, ddir, c->b_options);
+                               install(f->b_name, c->b_name,
+                                       c->b_name == NULL ? 0 : ddir,
+                                       c->b_options);
                        }
                        if (n == 0)
                        }
                        if (n == 0)
-                               install(f->b_name, f->b_name, 0, options);
+                               install(f->b_name, NULL, 0, options);
                }
                if (!nflag) {
                        /* signal end of connection */
                }
                if (!nflag) {
                        /* signal end of connection */
@@ -112,8 +91,7 @@ makeconn(rhost)
        register char *ruser;
        extern char user[];
 
        register char *ruser;
        extern char user[];
 
-       (void) sprintf(buf, "/usr/local/rdist -Server%s%s",
-               nflag ? " -n" : "", qflag ? " -q" : "");
+       (void) sprintf(buf, "/usr/local/rdist -Server%s", qflag ? " -q" : "");
 
        ruser = rindex(rhost, '.');
        if (ruser != NULL) {
 
        ruser = rindex(rhost, '.');
        if (ruser != NULL) {
@@ -138,44 +116,24 @@ makeconn(rhost)
        return(1);
 }
 
        return(1);
 }
 
-/*
- * Update the file(s) if they are different.
- * destdir = 1 if destination should be a directory
- * (i.e., more than one source is being copied to the same destination).
- */
-install(src, dest, destdir, opts)
-       char *src, *dest;
-       int destdir, opts;
+okname(name)
+       register char *name;
 {
 {
-       register char *cp;
-
-       if (exclude(src))
-               return;
+       register char *cp = name;
+       register int c;
 
 
-       if (nflag || debug) {
-               printf("%s%s%s%s%s %s %s\n", opts & VERIFY ? "verify":"install",
-                       opts & WHOLE ? " -w" : "",
-                       opts & YOUNGER ? " -y" : "",
-                       opts & COMPARE ? " -b" : "",
-                       opts & REMOVE ? " -r" : "", src, dest);
-               if (nflag)
-                       return;
-       }
-       /*
-        * Pass the destination file/directory name to remote.
-        */
-       (void) sprintf(buf, "%c%s\n", destdir ? 'T' : 't', dest);
-       if (debug)
-               printf("buf = %s", buf);
-       (void) write(rem, buf, strlen(buf));
-
-       if (!destdir && (opts & WHOLE))
-               opts |= STRIP;
-       if (opts & REMOVE) {
-               opts &= ~REMOVE;
-               rmchk(src, NULL, opts);
-       }
-       sendf(src, NULL, opts);
+       do {
+               c = *cp;
+               if (c & 0200)
+                       goto bad;
+               if (!isalpha(c) && !isdigit(c) && c != '_' && c != '-')
+                       goto bad;
+               cp++;
+       } while (*cp);
+       return(1);
+bad:
+       error("invalid user name %s\n", name);
+       return(0);
 }
 
 struct tstamp {
 }
 
 struct tstamp {
@@ -214,7 +172,8 @@ dofcmds(files, stamps, cmds)
                error("empty time stamp file list\n");
                return;
        }
                error("empty time stamp file list\n");
                return;
        }
-       except = cmds;
+       if (!mkexceptlist(cmds))
+               return;
 
        t = ts;
        nstamps = 0;
 
        t = ts;
        nstamps = 0;
@@ -284,7 +243,8 @@ cmptime(name)
         * first time cmptime() is called?
         */
        if (tp == NULL) {
         * first time cmptime() is called?
         */
        if (tp == NULL) {
-               exptilde(target, name);
+               if (exptilde(target, name) == NULL)
+                       return;
                tp = name = target;
                while (*tp)
                        tp++;
                tp = name = target;
                while (*tp)
                        tp++;
@@ -437,36 +397,48 @@ struct    block *except;          /* list of files to exclude */
 exclude(file)
        char *file;
 {
 exclude(file)
        char *file;
 {
-       register struct block *b, *c;
+       register struct block *c;
 
 
-       for (c = except; c != NULL; c = c->b_next) {
-               if (c->b_type != EXCEPT)
-                       continue;
-               for (b = c->b_args; b != NULL; b = b->b_next)
-                       if (!strcmp(file, b->b_name))
-                               return(1);
-       }
+       for (c = except; c != NULL; c = c->b_next)
+               if (!strcmp(file, c->b_name))
+                       return(1);
        return(0);
 }
 
        return(0);
 }
 
-okname(name)
-       register char *name;
+/*
+ * Build the exception list from an unexpanded list of commands.
+ */
+mkexceptlist(cmds)
+       struct block *cmds;
 {
 {
-       register char *cp = name;
-       register int c;
+       register struct block *f, *a, *c;
+       register char *cp;
 
 
-       do {
-               c = *cp;
-               if (c & 0200)
-                       goto bad;
-               if (!isalpha(c) && !isdigit(c) && c != '_' && c != '-')
-                       goto bad;
-               cp++;
-       } while (*cp);
+       if (debug)
+               printf("mkexceptlist()\n");
+
+       except = f = NULL;
+       for (c = cmds; c != NULL; c = c->b_next) {
+               if (c->b_type != EXCEPT)
+                       continue;
+               for (a = c->b_args; a != NULL; a = a->b_next) {
+                       cp = a->b_name;
+                       if (*cp == '~') {
+                               if (exptilde(buf, cp) == NULL)
+                                       return(0);
+                               cp = buf;
+                       }
+                       if (f == NULL)
+                               except = f = expand(makeblock(NAME, cp), 0);
+                       else
+                               f->b_next = expand(makeblock(NAME, cp), 0);
+                       while (f->b_next != NULL)
+                               f = f->b_next;
+               }
+       }
+       if (debug)
+               prnames(except);
        return(1);
        return(1);
-bad:
-       error("invalid user name %s\n", name);
-       return(0);
 }
 
 char *
 }
 
 char *
index fb4c75d..d53d3f7 100644 (file)
@@ -1,5 +1,5 @@
 #ifndef lint
 #ifndef lint
-static char *sccsid = "@(#)expand.c    4.4 (Berkeley) 83/10/20";
+static char *sccsid = "@(#)expand.c    4.5 (Berkeley) 83/11/01";
 #endif
 
 #include "defs.h"
 #endif
 
 #include "defs.h"
@@ -550,30 +550,32 @@ exptilde(buf, file)
        register char *file;
 {
        register char *s1, *s2, *s3;
        register char *file;
 {
        register char *s1, *s2, *s3;
-       register struct passwd *pw;
-       extern char *homedir;
+       extern char homedir[];
 
        if (*file != '~') {
                strcpy(buf, file);
                return(buf);
        }
 
        if (*file != '~') {
                strcpy(buf, file);
                return(buf);
        }
-       file++;
-       if (*file == '\0' || *file == '/') {
+       if (*++file == '\0') {
+               s2 = homedir;
+               s3 = NULL;
+       } else if (*file == '/') {
                s2 = homedir;
                s3 = file;
        } else {
                s2 = homedir;
                s3 = file;
        } else {
-               for (s3 = file; *s3 && *s3 != '/'; s3++)
-                       ;
+               while (*s3 && *s3 != '/')
+                       s3++;
                if (*s3 == '/')
                        *s3 = '\0';
                else
                        s3 = NULL;
                if (*s3 == '/')
                        *s3 = '\0';
                else
                        s3 = NULL;
-               pw = getpwnam(file);
-               if (pw == NULL) {
-                       error("unknown user %s\n", file);
-                       if (s3 != NULL)
-                               *s3 = '/';
-                       return(NULL);
+               if (pw == NULL || strcmp(pw->pw_name, file) != 0) {
+                       if ((pw = getpwnam(file)) == NULL) {
+                               error("unknown user %s\n", file);
+                               if (s3 != NULL)
+                                       *s3 = '/';
+                               return(NULL);
+                       }
                }
                if (s3 != NULL)
                        *s3 = '/';
                }
                if (s3 != NULL)
                        *s3 = '/';
@@ -582,8 +584,10 @@ exptilde(buf, file)
        for (s1 = buf; *s1++ = *s2++; )
                ;
        s2 = --s1;
        for (s1 = buf; *s1++ = *s2++; )
                ;
        s2 = --s1;
-       if (s3 != NULL)
+       if (s3 != NULL) {
+               s2++;
                while (*s1++ = *s3++)
                        ;
                while (*s1++ = *s3++)
                        ;
+       }
        return(s2);
 }
        return(s2);
 }
index dc8bc82..31e73d9 100644 (file)
@@ -1,5 +1,5 @@
 #ifndef lint
 #ifndef lint
-static char *sccsid = "@(#)main.c      4.7 (Berkeley) 83/10/26";
+static char *sccsid = "@(#)main.c      4.8 (Berkeley) 83/11/01";
 #endif
 
 #include "defs.h"
 #endif
 
 #include "defs.h"
@@ -30,6 +30,9 @@ char  homedir[128];   /* user's home directory */
 int    userid;         /* user's user ID */
 int    groupid;        /* user's group ID */
 
 int    userid;         /* user's user ID */
 int    groupid;        /* user's group ID */
 
+struct passwd *pw;     /* pointer to static area used by getpwent */
+struct group *gr;      /* pointer to static area used by getgrent */
+
 int    cleanup();
 int    lostconn();
 
 int    cleanup();
 int    lostconn();
 
@@ -38,7 +41,6 @@ main(argc, argv)
        char *argv[];
 {
        register char *arg;
        char *argv[];
 {
        register char *arg;
-       register struct passwd *pw;
        int cmdargs = 0;
 
        pw = getpwuid(userid = getuid());
        int cmdargs = 0;
 
        pw = getpwuid(userid = getuid());
index 6f328a9..a8d28aa 100644 (file)
@@ -1,5 +1,5 @@
 #ifndef lint
 #ifndef lint
-static char *sccsid = "@(#)server.c    4.6 (Berkeley) 83/10/26";
+static char *sccsid = "@(#)server.c    4.7 (Berkeley) 83/11/01";
 #endif
 
 #include "defs.h"
 #endif
 
 #include "defs.h"
@@ -11,10 +11,7 @@ char target[BUFSIZ];         /* target/source directory name */
 char   *tp;                    /* pointer to end of target name */
 int    catname;                /* cat name to target name */
 char   *stp[32];               /* stack of saved tp's for directories */
 char   *tp;                    /* pointer to end of target name */
 int    catname;                /* cat name to target name */
 char   *stp[32];               /* stack of saved tp's for directories */
-int    sumask;                 /* saved umask for creating files */
-
-static struct passwd *p = NULL;
-static struct group *g = NULL;
+int    oumask;                 /* old umask for creating files */
 
 extern FILE *lfp;              /* log file for mailing changes */
 
 
 extern FILE *lfp;              /* log file for mailing changes */
 
@@ -31,10 +28,10 @@ server()
 {
        char cmdbuf[BUFSIZ];
        register char *cp;
 {
        char cmdbuf[BUFSIZ];
        register char *cp;
-       register struct block *bp, *last = NULL;
+       register struct block *bp = NULL;
        int opts;
 
        int opts;
 
-       sumask = umask(0);
+       oumask = umask(0);
        ga();
 
        for (;;) {
        ga();
 
        for (;;) {
@@ -42,7 +39,7 @@ server()
                if (read(rem, cp, 1) <= 0)
                        return;
                if (*cp++ == '\n') {
                if (read(rem, cp, 1) <= 0)
                        return;
                if (*cp++ == '\n') {
-                       error("expected control record\n");
+                       error("server: expected control record\n");
                        continue;
                }
                do {
                        continue;
                }
                do {
@@ -52,23 +49,6 @@ server()
                *--cp = '\0';
                cp = cmdbuf;
                switch (*cp++) {
                *--cp = '\0';
                cp = cmdbuf;
                switch (*cp++) {
-               case 'X':  /* add name to list of files to exclude */
-                       if (*cp == '\0')
-                               continue;
-                       if (*cp == '~') {
-                               exptilde(buf, cp);
-                               cp = buf;
-                       }
-                       bp = makeblock(EXCEPT);
-                       bp->b_args = expand(makeblock(NAME, cp), 0);
-                       if (last == NULL)
-                               except = last = bp;
-                       else {
-                               last->b_next = bp;
-                               last = bp;
-                       }
-                       continue;
-
                case 'T':  /* init target file/directory name */
                        catname = 1;    /* target should be directory */
                        goto dotarget;
                case 'T':  /* init target file/directory name */
                        catname = 1;    /* target should be directory */
                        goto dotarget;
@@ -76,18 +56,12 @@ server()
                case 't':  /* init target file/directory name */
                        catname = 0;
                dotarget:
                case 't':  /* init target file/directory name */
                        catname = 0;
                dotarget:
-                       (void) exptilde(target, cp);
+                       if (exptilde(target, cp) == NULL)
+                               continue;
                        tp = target;
                        while (*tp)
                                tp++;
                        tp = target;
                        while (*tp)
                                tp++;
-                       continue;
-
-               case 'S':  /* Send. Transfer file if out of date. */
-                       sendf(cp, NULL, 0);
-                       continue;
-
-               case 'V':  /* Verify. See if file is out of date. */
-                       sendf(cp, NULL, VERIFY);
+                       ga();
                        continue;
 
                case 'R':  /* Receive. Transfer file. */
                        continue;
 
                case 'R':  /* Receive. Transfer file. */
@@ -100,39 +74,71 @@ server()
 
                case 'E':  /* End. (of directory) */
                        *tp = '\0';
 
                case 'E':  /* End. (of directory) */
                        *tp = '\0';
-                       if (--catname < 0) {
-                               error("too many 'E's\n");
+                       if (catname <= 0) {
+                               error("server: too many 'E's\n");
                                continue;
                        }
                                continue;
                        }
-                       tp = stp[catname];
+                       tp = stp[--catname];
                        *tp = '\0';
                        ga();
                        continue;
 
                case 'C':  /* Clean. Cleanup a directory */
                        *tp = '\0';
                        ga();
                        continue;
 
                case 'C':  /* Clean. Cleanup a directory */
-                       if (*cp < '0' || *cp > '7') {
-                               error("bad options\n");
+                       opts = 0;
+                       while (*cp >= '0' && *cp <= '7')
+                               opts = (opts << 3) | (*cp++ - '0');
+                       if (*cp++ != ' ')
+                               error("server: options not delimited\n");
+                       else
+                               clean(cp, opts, 1);
+                       continue;
+
+               case 'Q':  /* Query. Does the file/directory exist? */
+                       query(cp);
+                       continue;
+
+#ifdef notdef
+               /*
+                * These entries are reserved but not currently used.
+                * The intent is to allow remote hosts to have master copies.
+                * Currently, only the host rdist runs on can have masters.
+                */
+               case 'X':  /* start a new list of files to exclude */
+                       except = bp = NULL;
+               case 'x':  /* add name to list of files to exclude */
+                       if (*cp == '\0') {
+                               ga();
                                continue;
                        }
                                continue;
                        }
-                       opts = *cp++ - '0';
-                       if (*cp++ != ' ') {
-                               error("options not delimited\n");
-                               continue;
+                       if (*cp == '~') {
+                               if (exptilde(buf, cp) == NULL)
+                                       continue;
+                               cp = buf;
                        }
                        }
-                       clean(cp, opts, 1);
-                       continue;
-
-               case 'Q':  /* Query. Does directory exist? */
-                       query(cp, 1);
+                       if (bp == NULL)
+                               except = bp = expand(makeblock(NAME, cp), 0);
+                       else
+                               bp->b_next = expand(makeblock(NAME, cp), 0);
+                       while (bp->b_next != NULL)
+                               bp = bp->b_next;
+                       ga();
                        continue;
 
                        continue;
 
-               case 'q':  /* query. Does file exist? */
-                       query(cp, 0);
+               case 'S':  /* Send. Transfer file if out of date. */
+                       opts = 0;
+                       while (*cp >= '0' && *cp <= '7')
+                               opts = (opts << 3) | (*cp++ - '0');
+                       if (*cp++ != ' ') {
+                               error("server: options not delimited\n");
+                               return;
+                       }
+                       sendf(cp, opts);
                        continue;
 
                case 'L':  /* Log. save message in log file */
                        log(lfp, cp);
                        continue;
                        continue;
 
                case 'L':  /* Log. save message in log file */
                        log(lfp, cp);
                        continue;
+#endif
 
                case '\1':
                        errs++;
 
                case '\1':
                        errs++;
@@ -142,7 +148,7 @@ server()
                        return;
 
                default:
                        return;
 
                default:
-                       error("unknown command type %s\n", cp);
+                       error("server: unknown command '%s'\n", cp);
                case '\0':
                        continue;
                }
                case '\0':
                        continue;
                }
@@ -150,74 +156,117 @@ server()
 }
 
 /*
 }
 
 /*
- * Transfer the file or directory 'name'.
+ * Update the file(s) if they are different.
+ * destdir = 1 if destination should be a directory
+ * (i.e., more than one source is being copied to the same destination).
  */
  */
-sendf(lname, rname, opts)
-       char *lname, *rname;
-       int opts;
+install(src, dest, destdir, opts)
+       char *src, *dest;
+       int destdir, opts;
 {
 {
-       register char *cp;
-       struct stat stb;
-       int sizerr, f, u;
-       off_t i;
+       char *rname;
 
 
-       if (debug)
-               printf("sendf(%s, %s, %x)\n", lname,
-                       rname != NULL ? rname : "NULL", opts);
+       if (dest == NULL) {
+               opts &= ~WHOLE; /* WHOLE mode only useful if renaming */
+               dest = src;
+       }
 
 
+       if (nflag || debug) {
+               printf("%s%s%s%s%s %s %s\n", opts & VERIFY ? "verify":"install",
+                       opts & WHOLE ? " -w" : "",
+                       opts & YOUNGER ? " -y" : "",
+                       opts & COMPARE ? " -b" : "",
+                       opts & REMOVE ? " -r" : "", src, dest);
+               if (nflag)
+                       return;
+       }
+
+       rname = exptilde(target, src);
+       if (rname == NULL)
+               return;
+       tp = target;
+       while (*tp)
+               tp++;
        /*
        /*
-        * First time sendf() is called?
+        * If we are renaming a directory and we want to preserve
+        * the directory heirarchy (-w), we must strip off the first
+        * directory name and preserve the rest.
         */
         */
-       if (rname == NULL) {
-               rname = exptilde(target, lname);
-               if (rname == NULL)
-                       return;
-               tp = lname = target;
-               while (*tp)
-                       tp++;
-               /*
-                * If we are renaming a directory and we want to preserve
-                * the directory heirarchy (-w), we must strip off the first
-                * directory name and preserve the rest.
-                */
-               if (opts & STRIP) {
-                       opts &= ~STRIP;
+       if (opts & WHOLE) {
+               if (!destdir) {
                        rname = index(rname, '/');
                        if (rname == NULL)
                        rname = index(rname, '/');
                        if (rname == NULL)
-                               rname = tp;
-                       else
-                               rname++;
-               } else if (!(opts & WHOLE)) {
-                       rname = rindex(lname, '/');
-                       if (rname == NULL)
-                               rname = lname;
-                       else
+                               rname = tp; /* doesn't matter what rname is */
+                       else {
+                               destdir++; /* cat rname to dest */
                                rname++;
                                rname++;
+                       }
                }
                }
+       } else {
+               rname = rindex(target, '/');
+               if (rname == NULL)
+                       rname = target;
+               else
+                       rname++;
        }
        }
-       if (exclude(lname))
+       if (debug)
+               printf("target = %s, rname = %s\n", target, rname);
+       /*
+        * Pass the destination file/directory name to remote.
+        */
+       (void) sprintf(buf, "%c%s\n", destdir ? 'T' : 't', dest);
+       if (debug)
+               printf("buf = %s", buf);
+       (void) write(rem, buf, strlen(buf));
+       if (response() < 0)
+               return;
+
+       sendf(rname, opts);
+}
+
+/*
+ * Transfer the file or directory in target[].
+ * rname is the name of the file on the remote host.
+ */
+sendf(rname, opts)
+       char *rname;
+       int opts;
+{
+       register char *cp;
+       struct stat stb;
+       int sizerr, f, u;
+       off_t i;
+
+       if (debug)
+               printf("sendf(%s, %x)\n", rname, opts);
+
+       if (exclude(target))
                return;
                return;
-       if (access(lname, 4) < 0 || stat(lname, &stb) < 0) {
-               error("%s: %s\n", lname, sys_errlist[errno]);
+       if (access(target, 4) < 0 || stat(target, &stb) < 0) {
+               error("%s: %s\n", target, sys_errlist[errno]);
                return;
        }
                return;
        }
-       if ((u = update(lname, rname, opts, &stb)) == 0)
+       if (opts & REMOVE) {
+               opts &= ~REMOVE;
+               if (ISDIR(stb.st_mode))
+                       rmchk(rname, opts);
+       }
+       if ((u = update(rname, opts, &stb)) == 0)
                return;
 
                return;
 
-       if (p == NULL || p->pw_uid != stb.st_uid)
-               if ((p = getpwuid(stb.st_uid)) == NULL) {
-                       error("%s: no password entry for uid %d\n",
-                               lname, stb.st_uid);
+       if (pw == NULL || pw->pw_uid != stb.st_uid)
+               if ((pw = getpwuid(stb.st_uid)) == NULL) {
+                       error("%s: no password entry for uid %d\n", target,
+                               stb.st_uid);
                        return;
                }
                        return;
                }
-       if (g == NULL || g->gr_gid != stb.st_gid)
-               if ((g = getgrgid(stb.st_gid)) == NULL) {
-                       error("%s: no name for group %d\n",
-                               lname, stb.st_gid);
+       if (gr == NULL || gr->gr_gid != stb.st_gid)
+               if ((gr = getgrgid(stb.st_gid)) == NULL) {
+                       error("%s: no name for group %d\n", target, stb.st_gid);
                        return;
                }
        if (u == 1) {
                        return;
                }
        if (u == 1) {
-               log(lfp, "installing: %s\n", lname);
+               log(lfp, "installing: %s\n", target);
                if (opts & VERIFY)
                        return;
                opts &= ~COMPARE;
                if (opts & VERIFY)
                        return;
                opts &= ~COMPARE;
@@ -228,27 +277,27 @@ sendf(lname, rname, opts)
                break;
 
        case S_IFDIR:
                break;
 
        case S_IFDIR:
-               rsendf(lname, rname, opts, &stb, p->pw_name, g->gr_name);
+               rsendf(rname, opts, &stb, pw->pw_name, gr->gr_name);
                return;
 
        default:
                return;
 
        default:
-               error("%s: not a plain file\n", lname);
+               error("%s: not a plain file\n", target);
                return;
        }
 
        if (u == 2) {
                return;
        }
 
        if (u == 2) {
-               log(lfp, "updating: %s\n", lname);
+               log(lfp, "updating: %s\n", target);
                if (opts & VERIFY)
                        return;
        }
 
                if (opts & VERIFY)
                        return;
        }
 
-       if ((f = open(lname, 0)) < 0) {
-               error("%s: %s\n", lname, sys_errlist[errno]);
+       if ((f = open(target, 0)) < 0) {
+               error("%s: %s\n", target, sys_errlist[errno]);
                return;
        }
        (void) sprintf(buf, "R%o %04o %D %D %s %s %s\n", opts,
                stb.st_mode & 07777, stb.st_size, stb.st_mtime,
                return;
        }
        (void) sprintf(buf, "R%o %04o %D %D %s %s %s\n", opts,
                stb.st_mode & 07777, stb.st_size, stb.st_mtime,
-               p->pw_name, g->gr_name, rname);
+               pw->pw_name, gr->gr_name, rname);
        if (debug)
                printf("buf = %s", buf);
        (void) write(rem, buf, strlen(buf));
        if (debug)
                printf("buf = %s", buf);
        (void) write(rem, buf, strlen(buf));
@@ -267,14 +316,14 @@ sendf(lname, rname, opts)
        }
        (void) close(f);
        if (sizerr)
        }
        (void) close(f);
        if (sizerr)
-               error("%s: file changed size\n", lname);
+               error("%s: file changed size\n", target);
        else
                ga();
        (void) response();
 }
 
        else
                ga();
        (void) response();
 }
 
-rsendf(lname, rname, opts, st, owner, group)
-       char *lname, *rname;
+rsendf(rname, opts, st, owner, group)
+       char *rname;
        int opts;
        struct stat *st;
        char *owner, *group;
        int opts;
        struct stat *st;
        char *owner, *group;
@@ -285,11 +334,11 @@ rsendf(lname, rname, opts, st, owner, group)
        int len;
 
        if (debug)
        int len;
 
        if (debug)
-               printf("rsendf(%s, %s, %x, %x, %s, %s)\n", lname, rname,
-                       opts, st, owner, group);
+               printf("rsendf(%s, %x, %x, %s, %s)\n", rname, opts, st,
+                       owner, group);
 
 
-       if ((d = opendir(lname)) == NULL) {
-               error("%s: %s\n", lname, sys_errlist[errno]);
+       if ((d = opendir(target)) == NULL) {
+               error("%s: %s\n", target, sys_errlist[errno]);
                return;
        }
        (void) sprintf(buf, "D%o %04o 0 0 %s %s %s\n", opts,
                return;
        }
        (void) sprintf(buf, "D%o %04o 0 0 %s %s %s\n", opts,
@@ -316,7 +365,7 @@ rsendf(lname, rname, opts, st, owner, group)
                while (*tp++ = *cp++)
                        ;
                tp--;
                while (*tp++ = *cp++)
                        ;
                tp--;
-               sendf(target, dp->d_name, opts);
+               sendf(dp->d_name, opts);
        }
        closedir(d);
        (void) write(rem, "E\n", 2);
        }
        closedir(d);
        (void) write(rem, "E\n", 2);
@@ -327,34 +376,35 @@ rsendf(lname, rname, opts, st, owner, group)
 
 /*
  * Check to see if file needs to be updated on the remote machine.
 
 /*
  * Check to see if file needs to be updated on the remote machine.
- * Returns 0 if no update, 1 if remote doesn't exist, and 2 if out of date.
+ * Returns 0 if no update, 1 if remote doesn't exist, 2 if out of date
+ * and 3 if comparing binaries to determine if out of date.
  */
  */
-update(lname, rname, opts, st)
-       char *lname, *rname;
+update(rname, opts, st)
+       char *rname;
        int opts;
        struct stat *st;
 {
        int opts;
        struct stat *st;
 {
-       register char *cp;
+       register char *cp, *s;
        register off_t size;
        register time_t mtime;
 
        if (debug) 
        register off_t size;
        register time_t mtime;
 
        if (debug) 
-               printf("update(%s, %s, %x, %x)\n", lname, rname, opts, st);
+               printf("update(%s, %x, %x)\n", rname, opts, st);
 
        /*
         * Check to see if the file exists on the remote machine.
         */
 
        /*
         * Check to see if the file exists on the remote machine.
         */
-       (void) sprintf(buf, "%c%s\n", ISDIR(st->st_mode) ? 'Q' : 'q', rname);
+       (void) sprintf(buf, "Q%s\n", rname);
        if (debug)
                printf("buf = %s", buf);
        (void) write(rem, buf, strlen(buf));
        if (debug)
                printf("buf = %s", buf);
        (void) write(rem, buf, strlen(buf));
-       cp = buf;
+       cp = s = buf;
        do {
                if (read(rem, cp, 1) != 1)
                        lostconn();
        } while (*cp++ != '\n' && cp < &buf[BUFSIZ]);
 
        do {
                if (read(rem, cp, 1) != 1)
                        lostconn();
        } while (*cp++ != '\n' && cp < &buf[BUFSIZ]);
 
-       switch (buf[0]) {
+       switch (*s++) {
        case 'Y':
                break;
 
        case 'Y':
                break;
 
@@ -363,40 +413,41 @@ update(lname, rname, opts, st)
 
        case '\1':
                errs++;
 
        case '\1':
                errs++;
-               if (cp > &buf[2]) {
+               if (*s != '\n') {
                        if (!iamremote) {
                                fflush(stdout);
                        if (!iamremote) {
                                fflush(stdout);
-                               (void) write(2, cp, cp - buf);
+                               (void) write(2, s, cp - s);
                        }
                        if (lfp != NULL)
                        }
                        if (lfp != NULL)
-                               (void) fwrite(cp, 1, cp - buf, lfp);
+                               (void) fwrite(s, 1, cp - s, lfp);
                }
                return(0);
 
        default:
                }
                return(0);
 
        default:
-               error("unexpected response '%c' to query\n", buf[0]);
+               printf("buf = ");
+               fwrite(buf, 1, cp - s, stdout);
+               error("update: unexpected response '%c'\n", buf[0]);
                return(0);
        }
 
                return(0);
        }
 
-       cp = &buf[1];
-       if (*cp == '\n')
+       if (*s == '\n')
                return(2);
 
        if (opts & COMPARE)
                return(3);
 
        size = 0;
                return(2);
 
        if (opts & COMPARE)
                return(3);
 
        size = 0;
-       while (isdigit(*cp))
-               size = size * 10 + (*cp++ - '0');
-       if (*cp++ != ' ') {
-               error("size not delimited\n");
+       while (isdigit(*s))
+               size = size * 10 + (*s++ - '0');
+       if (*s++ != ' ') {
+               error("update: size not delimited\n");
                return(0);
        }
        mtime = 0;
                return(0);
        }
        mtime = 0;
-       while (isdigit(*cp))
-               mtime = mtime * 10 + (*cp++ - '0');
-       if (*cp != '\n') {
-               error("mtime not delimited\n");
+       while (isdigit(*s))
+               mtime = mtime * 10 + (*s++ - '0');
+       if (*s != '\n') {
+               error("update: mtime not delimited\n");
                return(0);
        }
        /*
                return(0);
        }
        /*
@@ -406,7 +457,7 @@ update(lname, rname, opts, st)
                if (st->st_mtime == mtime)
                        return(0);
                if (st->st_mtime < mtime) {
                if (st->st_mtime == mtime)
                        return(0);
                if (st->st_mtime < mtime) {
-                       log(lfp, "Warning: %s: remote copy is newer\n", lname);
+                       log(lfp, "Warning: %s: remote copy is newer\n", target);
                        return(0);
                }
        } else if (st->st_mtime == mtime && st->st_size == size)
                        return(0);
                }
        } else if (st->st_mtime == mtime && st->st_size == size)
@@ -421,16 +472,14 @@ update(lname, rname, opts, st)
  *     Y\n             - exists and its a directory
  *     ^Aerror message\n
  */
  *     Y\n             - exists and its a directory
  *     ^Aerror message\n
  */
-query(name, isdir)
+query(name)
        char *name;
        char *name;
-       int isdir;
 {
        struct stat stb;
 
        if (catname)
                (void) sprintf(tp, "/%s", name);
 
 {
        struct stat stb;
 
        if (catname)
                (void) sprintf(tp, "/%s", name);
 
-again:
        if (stat(target, &stb) < 0) {
                (void) write(rem, "N\n", 2);
                *tp = '\0';
        if (stat(target, &stb) < 0) {
                (void) write(rem, "N\n", 2);
                *tp = '\0';
@@ -444,14 +493,6 @@ again:
                break;
 
        case S_IFDIR:
                break;
 
        case S_IFDIR:
-               /*
-                * If file -> directory, need to cat name to target and stat.
-                */
-               if (!isdir && !catname) {
-                       isdir = 1;
-                       (void) sprintf(tp, "/%s", name);
-                       goto again;
-               }
                (void) write(rem, "Y\n", 2);
                break;
 
                (void) write(rem, "Y\n", 2);
                break;
 
@@ -481,35 +522,35 @@ recvf(cmd, isdir)
        while (*cp >= '0' && *cp <= '7')
                opts = (opts << 3) | (*cp++ - '0');
        if (*cp++ != ' ') {
        while (*cp >= '0' && *cp <= '7')
                opts = (opts << 3) | (*cp++ - '0');
        if (*cp++ != ' ') {
-               error("options not delimited\n");
+               error("recvf: options not delimited\n");
                return;
        }
        mode = 0;
        while (*cp >= '0' && *cp <= '7')
                mode = (mode << 3) | (*cp++ - '0');
        if (*cp++ != ' ') {
                return;
        }
        mode = 0;
        while (*cp >= '0' && *cp <= '7')
                mode = (mode << 3) | (*cp++ - '0');
        if (*cp++ != ' ') {
-               error("mode not delimited\n");
+               error("recvf: mode not delimited\n");
                return;
        }
        size = 0;
        while (isdigit(*cp))
                size = size * 10 + (*cp++ - '0');
        if (*cp++ != ' ') {
                return;
        }
        size = 0;
        while (isdigit(*cp))
                size = size * 10 + (*cp++ - '0');
        if (*cp++ != ' ') {
-               error("size not delimited\n");
+               error("recvf: size not delimited\n");
                return;
        }
        mtime = 0;
        while (isdigit(*cp))
                mtime = mtime * 10 + (*cp++ - '0');
        if (*cp++ != ' ') {
                return;
        }
        mtime = 0;
        while (isdigit(*cp))
                mtime = mtime * 10 + (*cp++ - '0');
        if (*cp++ != ' ') {
-               error("mtime not delimited\n");
+               error("recvf: mtime not delimited\n");
                return;
        }
        owner = cp;
        while (*cp && *cp != ' ')
                cp++;
        if (*cp != ' ') {
                return;
        }
        owner = cp;
        while (*cp && *cp != ' ')
                cp++;
        if (*cp != ' ') {
-               error("owner name not delimited\n");
+               error("recvf: owner name not delimited\n");
                return;
        }
        *cp++ = '\0';
                return;
        }
        *cp++ = '\0';
@@ -517,7 +558,7 @@ recvf(cmd, isdir)
        while (*cp && *cp != ' ')
                cp++;
        if (*cp != ' ') {
        while (*cp && *cp != ' ')
                cp++;
        if (*cp != ' ') {
-               error("group name not delimited\n");
+               error("recvf: group name not delimited\n");
                return;
        }
        *cp++ = '\0';
                return;
        }
        *cp++ = '\0';
@@ -559,17 +600,7 @@ recvf(cmd, isdir)
        if (catname)
                (void) sprintf(tp, "/%s", cp);
        if (stat(target, &stb) == 0) {
        if (catname)
                (void) sprintf(tp, "/%s", cp);
        if (stat(target, &stb) == 0) {
-               switch (stb.st_mode & S_IFMT) {
-               case S_IFREG:
-                       break;
-
-               case S_IFDIR:
-                       if (!catname) {
-                               (void) sprintf(tp, "/%s", cp);
-                               break;
-                       }
-
-               default:
+               if ((stb.st_mode & S_IFMT) != S_IFREG) {
                        error("%s: not a regular file\n", target);
                        return;
                }
                        error("%s: not a regular file\n", target);
                        return;
                }
@@ -582,7 +613,7 @@ recvf(cmd, isdir)
        if (cp == NULL)
                dir = ".";
        else if (cp == target) {
        if (cp == NULL)
                dir = ".";
        else if (cp == target) {
-               dir = "/";
+               dir = "";
                cp = NULL;
        } else {
                dir = target;
                cp = NULL;
        } else {
                dir = target;
@@ -720,7 +751,7 @@ chkparent(name)
                        goto bad;
                if (!strcmp(dir, ".") || !strcmp(dir, "/"))
                        goto bad;
                        goto bad;
                if (!strcmp(dir, ".") || !strcmp(dir, "/"))
                        goto bad;
-               if (mkdir(dir, 0777 & ~sumask) < 0)
+               if (mkdir(dir, 0777 & ~oumask) < 0)
                        goto bad;
                if (chown(dir, userid, groupid) < 0) {
                        (void) unlink(dir);
                        goto bad;
                if (chown(dir, userid, groupid) < 0) {
                        (void) unlink(dir);
@@ -751,31 +782,31 @@ chog(file, owner, group, mode)
 
        uid = userid;
        if (userid == 0) {
 
        uid = userid;
        if (userid == 0) {
-               if (p == NULL || strcmp(owner, p->pw_name) != 0) {
-                       if ((p = getpwnam(owner)) == NULL) {
+               if (pw == NULL || strcmp(owner, pw->pw_name) != 0) {
+                       if ((pw = getpwnam(owner)) == NULL) {
                                if (mode & 04000) {
                                        error("%s: unknown login name\n", owner);
                                        return(-1);
                                }
                        } else
                                if (mode & 04000) {
                                        error("%s: unknown login name\n", owner);
                                        return(-1);
                                }
                        } else
-                               uid = p->pw_uid;
+                               uid = pw->pw_uid;
                } else
                } else
-                       uid = p->pw_uid;
+                       uid = pw->pw_uid;
        }
        gid = groupid;
        }
        gid = groupid;
-       if (g == NULL || strcmp(group, g->gr_name) != 0) {
-               if ((g = getgrnam(group)) == NULL) {
+       if (gr == NULL || strcmp(group, gr->gr_name) != 0) {
+               if ((gr = getgrnam(group)) == NULL) {
                        if (mode & 02000) {
                                error("%s: unknown group\n", group);
                                return(-1);
                        }
                } else
                        if (mode & 02000) {
                                error("%s: unknown group\n", group);
                                return(-1);
                        }
                } else
-                       gid = g->gr_gid;
+                       gid = gr->gr_gid;
        } else
        } else
-               gid = g->gr_gid;
+               gid = gr->gr_gid;
        if (userid && groupid != gid) {
        if (userid && groupid != gid) {
-               for (i = 0; g->gr_mem[i] != NULL; i++)
-                       if (!(strcmp(user, g->gr_mem[i])))
+               for (i = 0; gr->gr_mem[i] != NULL; i++)
+                       if (!(strcmp(user, gr->gr_mem[i])))
                                goto ok;
                gid = groupid;
        }
                                goto ok;
                gid = groupid;
        }
@@ -791,55 +822,15 @@ ok:
  * Check for files on the machine being updated that are not on the master
  * machine and remove them.
  */
  * Check for files on the machine being updated that are not on the master
  * machine and remove them.
  */
-rmchk(lname, rname, opts)
-       char *lname, *rname;
+rmchk(rname, opts)
+       char *rname;
        int opts;
 {
        int opts;
 {
-       register char *cp;
+       register char *cp, *s;
        struct stat stb;
 
        if (debug)
        struct stat stb;
 
        if (debug)
-               printf("rmchk(%s, %s, %x)\n", lname,
-                       rname != NULL ? rname : "NULL", opts);
-
-       /*
-        * First time rmchk() is called?
-        */
-       if (rname == NULL) {
-               rname = exptilde(target, lname);
-               if (rname == NULL)
-                       return;
-               tp = lname = target;
-               while (*tp)
-                       tp++;
-               /*
-                * If we are renaming a directory and we want to preserve
-                * the directory heirarchy (-w), we must strip off the first
-                * directory name and preserve the rest.
-                */
-               if (opts & STRIP) {
-                       opts &= ~STRIP;
-                       rname = index(rname, '/');
-                       if (rname == NULL)
-                               rname = tp;
-                       else
-                               rname++;
-               } else if (!(opts & WHOLE)) {
-                       rname = rindex(lname, '/');
-                       if (rname == NULL)
-                               rname = lname;
-                       else
-                               rname++;
-               }
-       }
-       if (exclude(lname))
-               return;
-       if (access(lname, 4) < 0 || stat(lname, &stb) < 0) {
-               error("%s: %s\n", lname, sys_errlist[errno]);
-               return;
-       }
-       if (!ISDIR(stb.st_mode))
-               return;
+               printf("rmchk(%s, %x)\n", rname, opts);
 
        /*
         * Tell the remote to clean the files from the last directory sent.
 
        /*
         * Tell the remote to clean the files from the last directory sent.
@@ -850,15 +841,16 @@ rmchk(lname, rname, opts)
        (void) write(rem, buf, strlen(buf));
        if (response() < 0)
                return;
        (void) write(rem, buf, strlen(buf));
        if (response() < 0)
                return;
-       catname = 0;
+       stp[0] = tp;
+       catname = 1;
        for (;;) {
        for (;;) {
-               cp = buf;
+               cp = s = buf;
                do {
                        if (read(rem, cp, 1) != 1)
                                lostconn();
                } while (*cp++ != '\n' && cp < &buf[BUFSIZ]);
 
                do {
                        if (read(rem, cp, 1) != 1)
                                lostconn();
                } while (*cp++ != '\n' && cp < &buf[BUFSIZ]);
 
-               switch (buf[0]) {
+               switch (*s++) {
                case 'Q': /* its a directory on the remote end */
                case 'q': /* its a regular file on the remote end */
                        /*
                case 'Q': /* its a directory on the remote end */
                case 'q': /* its a regular file on the remote end */
                        /*
@@ -868,14 +860,12 @@ rmchk(lname, rname, opts)
                         * y\n -- file exists and is a regular file.
                         */
                        *--cp = '\0';
                         * y\n -- file exists and is a regular file.
                         */
                        *--cp = '\0';
-                       (void) sprintf(tp, "/%s", buf + 1);
+                       (void) sprintf(tp, "/%s", s);
                        if (debug)
                                printf("check %s\n", target);
                        if (debug)
                                printf("check %s\n", target);
-                       if (exclude(target)) {
+                       if (exclude(target))
                                (void) write(rem, "y\n", 2);
                                (void) write(rem, "y\n", 2);
-                               break;
-                       }
-                       if (stat(target, &stb) < 0)
+                       else if (stat(target, &stb) < 0)
                                (void) write(rem, "N\n", 2);
                        else if (buf[0] == 'Q' && ISDIR(stb.st_mode)) {
                                if (catname >= sizeof(stp)) {
                                (void) write(rem, "N\n", 2);
                        else if (buf[0] == 'Q' && ISDIR(stb.st_mode)) {
                                if (catname >= sizeof(stp)) {
@@ -896,35 +886,35 @@ rmchk(lname, rname, opts)
                        if (catname < 0)
                                fatal("too many 'E's\n");
                        ga();
                        if (catname < 0)
                                fatal("too many 'E's\n");
                        ga();
-                       if (catname == 0)
-                               return;
                        tp = stp[--catname];
                        *tp = '\0';
                        tp = stp[--catname];
                        *tp = '\0';
+                       if (catname == 0)
+                               return;
                        break;
 
                case '\0':
                        *--cp = '\0';
                        break;
 
                case '\0':
                        *--cp = '\0';
-                       if (buf[1] != '\0')
-                               log(lfp, "%s\n", buf + 1);
+                       if (*s != '\0')
+                               log(lfp, "%s\n", s);
                        break;
 
                case '\1':
                case '\2':
                        errs++;
                        break;
 
                case '\1':
                case '\2':
                        errs++;
-                       if (buf[1] != '\n') {
+                       if (*s != '\n') {
                                if (!iamremote) {
                                        fflush(stdout);
                                if (!iamremote) {
                                        fflush(stdout);
-                                       (void) write(2, buf + 1, cp - buf + 1);
+                                       (void) write(2, s, cp - s);
                                }
                                if (lfp != NULL)
                                }
                                if (lfp != NULL)
-                                       (void) fwrite(buf + 1, 1, cp - buf + 1, lfp);
+                                       (void) fwrite(s, 1, cp - s, lfp);
                        }
                        if (buf[0] == '\2')
                                cleanup();
                        break;
 
                default:
                        }
                        if (buf[0] == '\2')
                                cleanup();
                        break;
 
                default:
-                       error("unknown response type %s\n", buf[0]);
+                       error("rmchk: unexpected response '%c'\n", buf[0]);
                }
        }
 }
                }
        }
 }
@@ -933,8 +923,8 @@ rmchk(lname, rname, opts)
  * Check the directory initialized by the 'T' command to server()
  * for extraneous files and remove them.
  */
  * Check the directory initialized by the 'T' command to server()
  * for extraneous files and remove them.
  */
-clean(lname, opts, first)
-       char *lname;
+clean(name, opts, first)
+       char *name;
        int opts, first;
 {
        DIR *d;
        int opts, first;
 {
        DIR *d;
@@ -948,19 +938,18 @@ clean(lname, opts, first)
                ootp = tp;
                if (catname) {
                        *tp++ = '/';
                ootp = tp;
                if (catname) {
                        *tp++ = '/';
-                       cp = lname;
+                       cp = name;
                        while (*tp++ = *cp++)
                                ;
                        tp--;
                }
                if (stat(target, &stb) < 0) {
                        while (*tp++ = *cp++)
                                ;
                        tp--;
                }
                if (stat(target, &stb) < 0) {
-                       if (errno == ENOENT) {
+                       if (errno != ENOENT) {
                                ga();
                                goto done;
                        }
                                ga();
                                goto done;
                        }
-               bad:
                        error("%s: %s\n", target, sys_errlist[errno]);
                        error("%s: %s\n", target, sys_errlist[errno]);
-                       tp = otp;
+                       tp = ootp;
                        *tp = '\0';
                        return;
                }
                        *tp = '\0';
                        return;
                }
@@ -974,8 +963,14 @@ clean(lname, opts, first)
                }
        }
 
                }
        }
 
-       if (access(target, 6) < 0 || (d = opendir(target)) == NULL)
-               goto bad;
+       if (access(target, 6) < 0 || (d = opendir(target)) == NULL) {
+               error("%s: %s\n", target, sys_errlist[errno]);
+               if (first) {
+                       tp = ootp;
+                       *tp = '\0';
+               }
+               return;
+       }
        ga();
 
        otp = tp;
        ga();
 
        otp = tp;
@@ -1012,17 +1007,26 @@ clean(lname, opts, first)
                                clean(dp->d_name, opts, 0);
                        continue;
                }
                                clean(dp->d_name, opts, 0);
                        continue;
                }
-               if (!(opts & VERIFY))
+               if (opts & VERIFY) {
+                       cp = buf;
+                       *cp++ = '\0';
+                       (void) sprintf(cp, "removing %s\n", target);
+                       (void) write(rem, buf, strlen(cp) + 1);
+               } else
                        remove(&stb);
        }
        closedir(d);
 done:
                        remove(&stb);
        }
        closedir(d);
 done:
-       tp = (first) ? ootp : otp;
-       *tp = '\0';
        (void) write(rem, "E\n", 2);
        (void) response();
        (void) write(rem, "E\n", 2);
        (void) response();
+       tp = (first) ? ootp : otp;
+       *tp = '\0';
 }
 
 }
 
+/*
+ * Remove a file or directory (recursively) and send back an acknowledge
+ * or an error message.
+ */
 remove(st)
        struct stat *st;
 {
 remove(st)
        struct stat *st;
 {
@@ -1170,11 +1174,10 @@ response()
                        if (lfp != NULL)
                                (void) fwrite(s, 1, cp - s, lfp);
                }
                        if (lfp != NULL)
                                (void) fwrite(s, 1, cp - s, lfp);
                }
-               if (buf[0] == '\1')
-                       return(-1);
-               cleanup();
+               if (buf[0] == '\2')
+                       cleanup();
+               return(-1);
        }
        }
-       /*NOTREACHED*/
 }
 
 lostconn()
 }
 
 lostconn()