i often need to use different rsh-like commands depending on the host
i'm rsyncing with (for any given host). e.g.

  from A to B, "rsh" is ok
  from A to Q, "ssh" is needed
  from A to Z, "runsocks ssh -x -l other-username" is needed

the RSYNC_RSH environment variable can't cope with this and
having to use the -e option all the time gets very boring,
so here's a patch (against rsync-2.4.6) that implements a
$HOME/.rsyncrc file with the following format:

  "host" <hostname> ["user" <username>] "rsh" <rsh-like command>

lines containing "user" only match when a username was supplied to
rsync on the command line. e.g.

  rsync user@host:path ...

lines not containing "user" only match when a username wasn't supplied
to rsync. e.g.

  rsync host:path ...

parsing the .rsyncrc file breaks when the host or user name contains
the string "rsh". i'll fix that (and document it in rsyncrc(5)) if
anyone is interested.

raf

diff -durp rsync-2.4.6.orig/main.c rsync-2.4.6/main.c
--- rsync-2.4.6.orig/main.c     Wed Sep  6 13:46:43 2000
+++ rsync-2.4.6/main.c  Thu Jan  4 14:45:01 2001
@@ -117,19 +117,75 @@ static void report(int f)
        fflush(stderr);
 }
 
+static int match_cmd(char *cmd,size_t cmdsize,char *machine,char *user,char *line)
+{
+       char *p,h[100],u[100],jnk[100];
+       int match=0;
+
+       if ((p = strchr(line,'#')))
+               *p = '\0';
+       if ((p = strchr(line,'\n')))
+               *p = '\0';
+
+       if (user && sscanf(line, " host %100s user %100s rsh %100s", h, u, jnk) == 3) {
+               if (!strcmp(h,machine) && !strcmp(u,user))
+                       match = 1;
+       } else if (!user && sscanf(line, " host %100s rsh %100s", h, jnk) == 2) {
+               if (!strcmp(h,machine))
+                       match = 1;
+       }
+
+       if (match) {
+               /* XXX Note: this breaks when user or hostname contains "rsh" */
+               char *c = strstr(line, "rsh") + 3;
+               while (isspace(*c))
+                       ++c;
+               strlcpy(cmd,c,cmdsize);
+               return 1;
+       }
+
+       return 0;
+}
+
+static char *get_cmd(char *cmd,size_t cmdsize,char *machine,char *user)
+{
+       char fname[100],line[BUFSIZ],*home;
+       FILE *rcfile;
+
+       if (!(home = getenv("HOME")))
+               home = "";
+
+       strlcpy(fname,home,100);
+       strlcat(fname,"/.",100);
+       strlcat(fname,RSYNCRC_NAME,100);
+
+       rcfile = fopen(fname,"r");
+       if (rcfile) {
+               while (fgets(line,BUFSIZ,rcfile)) {
+                       if (match_cmd(cmd,cmdsize,machine,user,line)) {
+                               fclose(rcfile);
+                               return cmd;
+                       }
+               }
+               fclose(rcfile);
+       }
+
+       return getenv(RSYNC_RSH_ENV);
+}
 
 static int do_cmd(char *cmd,char *machine,char *user,char *path,int *f_in,int *f_out)
 {
        char *args[100];
        int i,argc=0, ret;
        char *tok,*dir=NULL;
+       char cmdbuf[100];
        extern int local_server;
        extern char *rsync_path;
        extern int blocking_io;
 
        if (!local_server) {
                if (!cmd)
-                       cmd = getenv(RSYNC_RSH_ENV);
+                       cmd = get_cmd(cmdbuf,100,machine,user);
                if (!cmd)
                        cmd = RSYNC_RSH;
                cmd = strdup(cmd);
diff -durp rsync-2.4.6.orig/rsync.h rsync-2.4.6/rsync.h
--- rsync-2.4.6.orig/rsync.h    Sat Aug 19 23:10:39 2000
+++ rsync-2.4.6/rsync.h Thu Jan  4 14:45:46 2001
@@ -22,6 +22,7 @@
 
 #define BLOCK_SIZE 700
 #define RSYNC_RSH_ENV "RSYNC_RSH"
+#define RSYNCRC_NAME "rsyncrc"
 
 #define RSYNC_NAME "rsync"
 #define RSYNCD_CONF "/etc/rsyncd.conf"

Reply via email to