bug-cvs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Patch to protect spaces in diff arguments.


From: Derek Price
Subject: Patch to protect spaces in diff arguments.
Date: Fri, 27 May 2005 13:16:13 -0400
User-agent: Mozilla Thunderbird 1.0.2 (Windows/20050317)

I just committed the attached patch to the stable branch.  This problem
has been listed in BUGS for some time, so I felt justified despite it
being a fairly large patch.  I went to some lengths to keep it clean and
I think that it mostly actually simplifes the code.

Cheers,

Derek
Index: BUGS
===================================================================
RCS file: /cvs/ccvs/BUGS,v
retrieving revision 1.55.6.18
retrieving revision 1.55.6.19
diff -u -p -r1.55.6.18 -r1.55.6.19
--- BUGS        25 Aug 2004 03:14:01 -0000      1.55.6.18
+++ BUGS        27 May 2005 16:25:41 -0000      1.55.6.19
@@ -88,13 +88,6 @@ an incorrect value, though this does not
 noticed under BSDI.
 
 
-* Spaces in arguments to `cvs diff' are currently split on spaces and tabs
-before being passed to diff.  This can often cause diff to abort since it can
-no longer interpret its options string and if it can, coincidentally,
-interpret its option string, then the problem may be output in unexpected
-formats.
-
-
 * Status
 
                              /*-------.
Index: ChangeLog
===================================================================
RCS file: /cvs/ccvs/ChangeLog,v
retrieving revision 1.692.2.209
retrieving revision 1.692.2.210
diff -u -p -r1.692.2.209 -r1.692.2.210
--- ChangeLog   4 May 2005 02:35:14 -0000       1.692.2.209
+++ ChangeLog   27 May 2005 16:25:41 -0000      1.692.2.210
@@ -1,3 +1,8 @@
+2005-05-27  Derek Price  <address@hidden>
+
+       * NEWS: Note diff space split fix.
+       * BUGS: Remove diff space split note.
+
 2005-05-03  Derek Price  <address@hidden>
 
        * INSTALL: Add footnote about compiling a CVS checkout of CVS on a
Index: NEWS
===================================================================
RCS file: /cvs/ccvs/NEWS,v
retrieving revision 1.116.2.131
retrieving revision 1.116.2.132
diff -u -p -r1.116.2.131 -r1.116.2.132
--- NEWS        2 May 2005 17:07:20 -0000       1.116.2.131
+++ NEWS        27 May 2005 16:25:41 -0000      1.116.2.132
@@ -3,6 +3,8 @@ Changes since 1.11.20:
 
 BUG FIXES
 
+* `cvs diff' no longer splits its arguments on spaces.
+
 * Thanks to an old report and patch from Stewart Brodie <address@hidden>, a
   potential crash in response to a corrupt RCS file has been fixed.
 
Index: src/ChangeLog
===================================================================
RCS file: /cvs/ccvs/src/ChangeLog,v
retrieving revision 1.2336.2.371
retrieving revision 1.2336.2.373
diff -u -p -r1.2336.2.371 -r1.2336.2.373
--- src/ChangeLog       2 May 2005 19:39:10 -0000       1.2336.2.371
+++ src/ChangeLog       27 May 2005 16:28:00 -0000      1.2336.2.373
@@ -1,3 +1,25 @@
+2005-05-27  Derek Price  <address@hidden>
+
+       * client.c (send_arg): Make arg const.
+       (send_option_string): Rename to...
+       (send_options): ...this and accept argc/argv in place of string.
+       * client.h: Update protos to match the changes to client.c.
+       * cvs.h (RCS_exec_rcsdiff, diff_exec): Update protos.
+       (run_add_arg_p, run_arg_free_p): New protos.
+       * diff.c (opts, opts_allocated): Replace with...
+       (diff_argv, diff_argc, diff_arg_allocated): ...these.
+       (add_diff_args): New convenience function.
+       (diff): Use new constructs and APIs.
+       * patch.c (patch_fileproc, RCS_checkin, RCS_delete_revs), rcscmds.c
+       (call_diff_add_arg, call_diff_setup, RCS_merge, RCS_exec_rcsdiff,
+       diff_exec, RCS_output_diff_options), update.c (patch_file): Use new
+       APIs.
+       * run.c (run_add_arg_p, run_arg_free_p): New functions.
+       (run_argc_allocated): Make size_t.
+       (run_setup, run_add_arg): Use new functions.
+       * sanity.sh: Accomodate above changes.
+       (rcslib-diffrgx-3): Slip in test for space splitting.
+
 2005-05-02  Derek Price  <address@hidden>
 
        Remove unnecessary level of indirection.
Index: src/client.c
===================================================================
RCS file: /cvs/ccvs/src/client.c,v
retrieving revision 1.318.4.27
retrieving revision 1.318.4.28
diff -u -p -r1.318.4.27 -r1.318.4.28
--- src/client.c        17 Mar 2005 15:39:09 -0000      1.318.4.27
+++ src/client.c        27 May 2005 16:25:10 -0000      1.318.4.28
@@ -4903,10 +4903,10 @@ start_rsh_server (root, to_server, from_
 /* Send an argument STRING.  */
 void
 send_arg (string)
-    char *string;
+    const char *string;
 {
     char buf[1];
-    char *p = string;
+    const char *p = string;
 
     send_to_server ("Argument ", 0);
 
@@ -5404,36 +5404,15 @@ send_dirleave_proc (callerdat, dir, err,
 }
 
 /*
- * Send each option in a string to the server, one by one.
- * This assumes that the options are separated by spaces, for example
- * STRING might be "--foo -C5 -y".
+ * Send each option in an array to the server, one by one.
+ * argv might be "--foo=bar",  "-C", "5", "-y".
  */
-
 void
-send_option_string (string)
-    char *string;
+send_options (int argc, char *const *argv)
 {
-    char *copy;
-    char *p;
-
-    copy = xstrdup (string);
-    p = copy;
-    while (1)
-    {
-        char *s;
-       char l;
-
-       for (s = p; *s != ' ' && *s != '\0'; s++)
-           ;
-       l = *s;
-       *s = '\0';
-       if (s != p)
-           send_arg (p);
-       if (l == '\0')
-           break;
-       p = s + 1;
-    }
-    free (copy);
+    int i;
+    for (i = 0; i < argc; i++)
+       send_arg (argv[i]);
 }
 
 
Index: src/client.h
===================================================================
RCS file: /cvs/ccvs/src/client.h,v
retrieving revision 1.39.6.2
retrieving revision 1.39.6.3
diff -u -p -r1.39.6.2 -r1.39.6.3
--- src/client.h        20 Mar 2004 18:14:56 -0000      1.39.6.2
+++ src/client.h        27 May 2005 16:25:10 -0000      1.39.6.3
@@ -119,11 +119,10 @@ send_files PROTO((int argc, char **argv,
 
 /* Send an argument to the remote server.  */
 void
-send_arg PROTO((char *string));
+send_arg PROTO((const char *string));
 
 /* Send a string of single-char options to the remote server, one by one.  */
-void
-send_option_string PROTO((char *string));
+void send_options PROTO ((int argc, char * const *argv));
 
 extern void send_a_repository PROTO ((const char *, const char *,
                                       const char *));
Index: src/cvs.h
===================================================================
RCS file: /cvs/ccvs/src/cvs.h,v
retrieving revision 1.235.4.31
retrieving revision 1.235.4.32
diff -u -p -r1.235.4.31 -r1.235.4.32
--- src/cvs.h   2 May 2005 17:06:56 -0000       1.235.4.31
+++ src/cvs.h   27 May 2005 16:25:10 -0000      1.235.4.32
@@ -431,14 +431,16 @@ int RCS_merge PROTO((RCSNode *, const ch
 #define RCS_FLAGS_KEEPFILE 16
 #define RCS_FLAGS_USETIME 32
 
-extern int RCS_exec_rcsdiff PROTO ((RCSNode *rcsfile,
-                                   const char *opts, const char *options,
+extern int RCS_exec_rcsdiff PROTO ((RCSNode *rcsfile, int diff_argc,
+                                   char *const *diff_argv,
+                                   const char *options,
                                    const char *rev1, const char *rev1_cache,
                                     const char *rev2, const char *label1,
                                     const char *label2, const char *workfile));
 extern int diff_exec PROTO ((const char *file1, const char *file2,
                             const char *label1, const char *label2,
-                            const char *options, const char *out));
+                            int diff_argc, char *const *diff_argv,
+                            const char *out));
 
 
 #include "error.h"
@@ -696,6 +698,8 @@ void sleep_past PROTO ((time_t desttime)
 #define        RUN_SIGIGNORE         0x0010    /* ignore interrupts for 
command */
 #define        RUN_TTY               (char *)0 /* for the benefit of lint */
 
+void run_add_arg_p PROTO ((int *, size_t *, char ***, const char *s));
+void run_arg_free_p PROTO ((int, char **));
 void run_arg PROTO((const char *s));
 void run_print PROTO((FILE * fp));
 void run_setup PROTO ((const char *prog));
Index: src/diff.c
===================================================================
RCS file: /cvs/ccvs/src/diff.c,v
retrieving revision 1.94.2.9
retrieving revision 1.94.2.10
diff -u -p -r1.94.2.9 -r1.94.2.10
--- src/diff.c  31 Jan 2005 22:15:11 -0000      1.94.2.9
+++ src/diff.c  27 May 2005 16:25:11 -0000      1.94.2.10
@@ -65,8 +65,9 @@ static int have_rev1_label, have_rev2_la
 static char *user_file_rev;
 
 static char *options;
-static char *opts;
-static size_t opts_allocated = 1;
+static char **diff_argv;
+static int diff_argc;
+static size_t diff_arg_allocated;
 static int diff_errors;
 static int empty_files = 0;
 
@@ -211,6 +212,54 @@ static struct option const longopts[] =
     {0, 0, 0, 0}
 };
 
+
+
+/* Add one of OPT or LONGOPT, and ARGUMENT, when present, to global DIFF_ARGV.
+ *
+ * INPUTS
+ *   opt               A character option representation.
+ *   longopt           A long option name.
+ *   argument          Optional option argument.
+ *   
+ * GLOBALS
+ *   diff_argc         The number of arguments in DIFF_ARGV.
+ *   diff_argv         Array of argument strings.
+ *   diff_arg_allocated        Allocated length of DIFF_ARGV.
+ *
+ * NOTES
+ *   Behavior when both OPT & LONGOPT are provided is undefined.
+ *
+ * RETURNS
+ *   Nothing.
+ */
+static void
+add_diff_args (char opt, const char *longopt, const char *argument)
+{
+    char *tmp;
+
+    /* Add opt or longopt to diff_arv.  */
+    assert (opt || (longopt && *longopt));
+    assert (!(opt && (longopt && *longopt)));
+    if (opt)
+    {
+       tmp = xmalloc (3);
+       sprintf (tmp, "-%c", opt);
+    }
+    else
+    {
+       tmp = xmalloc (3 + strlen (longopt));
+       sprintf (tmp, "--%s", longopt);
+    }
+    run_add_arg_p (&diff_argc, &diff_arg_allocated, &diff_argv, tmp);
+    free (tmp);
+
+    /* When present, add ARGUMENT to DIFF_ARGV.  */
+    if (argument)
+       run_add_arg_p (&diff_argc, &diff_arg_allocated, &diff_argv, argument);
+}
+
+
+
 /* CVS 1.9 and similar versions seemed to have pretty weird handling
    of -y and -T.  In the cases where it called rcsdiff,
    they would have the meanings mentioned below.  In the cases where it
@@ -247,7 +296,6 @@ diff (argc, argv)
     int argc;
     char **argv;
 {
-    char tmp[50];
     int c, err = 0;
     int local = 0;
     int which;
@@ -267,12 +315,11 @@ diff (argc, argv)
     /* Clean out our global variables (multiroot can call us multiple
        times and the server can too, if the client sends several
        diff commands).  */
-    if (opts == NULL)
+    if (diff_argc)
     {
-       opts_allocated = 1;
-       opts = xmalloc (opts_allocated);
+       run_arg_free_p (diff_argc, diff_argv);
+       diff_argc = 0;
     }
-    opts[0] = '\0';
     diff_rev1 = NULL;
     diff_rev2 = NULL;
     diff_date1 = NULL;
@@ -293,7 +340,7 @@ diff (argc, argv)
        switch (c)
        {
            case 'y':
-               xrealloc_and_strcat (&opts, &opts_allocated, " --side-by-side");
+               add_diff_args (0, "side-by-side", NULL);
                break;
            case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
            case 'h': case 'i': case 'n': case 'p': case 's': case 't':
@@ -301,8 +348,7 @@ diff (argc, argv)
             case '0': case '1': case '2': case '3': case '4': case '5':
             case '6': case '7': case '8': case '9':
            case 'B': case 'H': case 'T':
-               (void) sprintf (tmp, " -%c", (char) c);
-               xrealloc_and_strcat (&opts, &opts_allocated, tmp);
+               add_diff_args (c, NULL, NULL);
                break;
            case 'L':
                if (have_rev1_label++)
@@ -311,33 +357,15 @@ diff (argc, argv)
                        error (0, 0, "extra -L arguments ignored");
                        break;
                    }
-
-               xrealloc_and_strcat (&opts, &opts_allocated, " -L");
-               xrealloc_and_strcat (&opts, &opts_allocated, optarg);
-               break;
+               /* Fall through.  */
            case 'C': case 'F': case 'I': case 'U': case 'W':
-               (void) sprintf (tmp, " -%c", (char) c);
-               xrealloc_and_strcat (&opts, &opts_allocated, tmp);
-               xrealloc_and_strcat (&opts, &opts_allocated, optarg);
+               add_diff_args (c, NULL, optarg);
                break;
-           case 131:
-               /* --ifdef.  */
-               xrealloc_and_strcat (&opts, &opts_allocated, " --ifdef=");
-               xrealloc_and_strcat (&opts, &opts_allocated, optarg);
-               break;
-           case 129: case 130:           case 132: case 133: case 134:
+           case 129: case 130: case 131: case 132: case 133: case 134:
            case 135: case 136: case 137: case 138: case 139: case 140:
            case 141: case 142: case 143: case 145: case 146:
-               xrealloc_and_strcat (&opts, &opts_allocated, " --");
-               xrealloc_and_strcat (&opts, &opts_allocated,
-                                    longopts[option_index].name);
-               if (longopts[option_index].has_arg == 1
-                   || (longopts[option_index].has_arg == 2
-                       && optarg != NULL))
-               {
-                   xrealloc_and_strcat (&opts, &opts_allocated, "=");
-                   xrealloc_and_strcat (&opts, &opts_allocated, optarg);
-               }
+               add_diff_args (0, longopts[option_index].name,
+                             longopts[option_index].has_arg ? optarg : NULL);
                break;
            case 'R':
                local = 0;
@@ -395,7 +423,7 @@ diff (argc, argv)
            send_arg("-l");
        if (empty_files)
            send_arg("-N");
-       send_option_string (opts);
+       send_options (diff_argc, diff_argv);
        if (options[0] != '\0')
            send_arg (options);
        if (diff_rev1)
@@ -705,8 +733,8 @@ RCS file: ", 0);
        if (empty_file == DIFF_ADDED)
        {
            if (use_rev2 == NULL)
-                status = diff_exec (DEVNULL, finfo->file, label1, label2, opts,
-                                    RUN_TTY);
+                status = diff_exec (DEVNULL, finfo->file, label1, label2,
+                                   diff_argc, diff_argv, RUN_TTY);
            else
            {
                int retcode;
@@ -722,7 +750,8 @@ RCS file: ", 0);
                if( retcode != 0 )
                    goto out;
 
-               status = diff_exec (DEVNULL, tmp, label1, label2, opts, 
RUN_TTY);
+               status = diff_exec (DEVNULL, tmp, label1, label2,
+                                   diff_argc, diff_argv, RUN_TTY);
            }
        }
        else
@@ -738,16 +767,16 @@ RCS file: ", 0);
            if (retcode != 0)
                goto out;
 
-           status = diff_exec (tmp, DEVNULL, label1, label2, opts, RUN_TTY);
+           status = diff_exec (tmp, DEVNULL, label1, label2,
+                               diff_argc, diff_argv, RUN_TTY);
        }
     }
     else
     {
-       status = RCS_exec_rcsdiff(vers->srcfile, opts,
-                                  *options ? options : vers->options,
-                                  use_rev1, rev1_cache, use_rev2,
-                                  label1, label2,
-                                  finfo->file);
+       status = RCS_exec_rcsdiff (vers->srcfile, diff_argc, diff_argv,
+                                   *options ? options : vers->options,
+                                   use_rev1, rev1_cache, use_rev2,
+                                   label1, label2, finfo->file);
 
     }
 
Index: src/patch.c
===================================================================
RCS file: /cvs/ccvs/src/patch.c,v
retrieving revision 1.80.4.11
retrieving revision 1.80.4.12
diff -u -p -r1.80.4.11 -r1.80.4.12
--- src/patch.c 18 Apr 2005 17:36:45 -0000      1.80.4.11
+++ src/patch.c 27 May 2005 16:25:11 -0000      1.80.4.12
@@ -406,6 +406,9 @@ patch_fileproc (callerdat, finfo)
     char *cp1, *cp2;
     FILE *fp;
     int line_length;
+    int dargc = 0;
+    size_t darg_allocated = 0;
+    char **dargv = NULL;
 
     line1 = NULL;
     line1_chars_allocated = 0;
@@ -585,8 +588,10 @@ patch_fileproc (callerdat, finfo)
            (void)utime (tmpfile2, &t);
     }
 
-    switch (diff_exec (tmpfile1, tmpfile2, NULL, NULL, unidiff ? "-u" : "-c",
-                       tmpfile3))
+    if (unidiff) run_add_arg_p (&dargc, &darg_allocated, &dargv, "-u");
+    else run_add_arg_p (&dargc, &darg_allocated, &dargv, "-c");
+    switch (diff_exec (tmpfile1, tmpfile2, NULL, NULL, dargc, dargv,
+                      tmpfile3))
     {
        case -1:                        /* fork/wait failure */
            error (1, errno, "fork for diff failed on %s", rcs);
@@ -758,6 +763,11 @@ failed to read diff file header %s for %
     free (tmpfile2);
     free (tmpfile3);
     tmpfile1 = tmpfile2 = tmpfile3 = NULL;
+    if (dargc)
+    {
+       run_arg_free_p (dargc, dargv);
+       free (dargv);
+    }
 
  out2:
     if (vers_tag != NULL)
Index: src/rcs.c
===================================================================
RCS file: /cvs/ccvs/src/rcs.c,v
retrieving revision 1.262.4.37
retrieving revision 1.262.4.38
diff -u -p -r1.262.4.37 -r1.262.4.38
--- src/rcs.c   20 Apr 2005 20:40:42 -0000      1.262.4.37
+++ src/rcs.c   27 May 2005 16:25:11 -0000      1.262.4.38
@@ -5049,7 +5049,9 @@ RCS_checkin (rcs, workfile_in, message, 
     Deltatext *dtext;
     Node *nodep;
     char *tmpfile, *changefile;
-    char *diffopts;
+    int dargc = 0;
+    size_t darg_allocated = 0;
+    char **dargv = NULL;
     size_t bufsize;
     int status, checkin_quiet;
     struct tm *ftm;
@@ -5478,9 +5480,10 @@ workfile);
 
     /* Diff options should include --binary if the RCS file has -kb set
        in its `expand' field. */
-    diffopts = (rcs->expand != NULL && STREQ (rcs->expand, "b")
-               ? "-a -n --binary"
-               : "-a -n");
+    run_add_arg_p (&dargc, &darg_allocated, &dargv, "-a");
+    run_add_arg_p (&dargc, &darg_allocated, &dargv, "-n");
+    if (rcs->expand && STREQ (rcs->expand, "b"))
+       run_add_arg_p (&dargc, &darg_allocated, &dargv, "--binary");
 
     if (STREQ (commitpt->version, rcs->head) &&
        numdots (delta->version) == 1)
@@ -5503,7 +5506,8 @@ workfile);
        memset (commitpt->text, 0, sizeof (Deltatext));
 
        bufsize = 0;
-       switch (diff_exec (workfile, tmpfile, NULL, NULL, diffopts, changefile))
+       switch (diff_exec (workfile, tmpfile, NULL, NULL,
+                          dargc, dargv, changefile))
        {
            case 0:
            case 1:
@@ -5551,7 +5555,8 @@ workfile);
        /* This file is not being inserted at the head, but on a side
           branch somewhere.  Make a diff from the previous revision
           to the working file. */
-       switch (diff_exec (tmpfile, workfile, NULL, NULL, diffopts, changefile))
+       switch (diff_exec (tmpfile, workfile, NULL, NULL,
+                          dargc, dargv, changefile))
        {
            case 0:
            case 1:
@@ -5578,6 +5583,9 @@ workfile);
        }
     }
 
+    run_arg_free_p (dargc, dargv);
+    free (dargv);
+
     /* Update DELTA linkage.  It is important not to do this before
        the very end of RCS_checkin; if an error arises that forces
        us to abort checking in, we must not have malformed deltas
@@ -6651,6 +6659,10 @@ RCS_delete_revs (rcs, tag1, tag2, inclus
        }
        else
        {
+           int dargc = 0;
+           size_t darg_allocated = 0;
+           char **dargv = NULL;
+
            beforefile = cvs_temp_name();
            status = RCS_checkout (rcs, NULL, before, NULL, "-ko", beforefile,
                                   (RCSCHECKOUTPROC)0, NULL);
@@ -6658,7 +6670,12 @@ RCS_delete_revs (rcs, tag1, tag2, inclus
                goto delrev_done;
 
            outfile = cvs_temp_name();
-           status = diff_exec (beforefile, afterfile, NULL, NULL, "-an", 
outfile);
+           run_add_arg_p (&dargc, &darg_allocated, &dargv, "-a");
+           run_add_arg_p (&dargc, &darg_allocated, &dargv, "-n");
+           status = diff_exec (beforefile, afterfile, NULL, NULL,
+                               dargc, dargv, outfile);
+           run_arg_free_p (dargc, dargv);
+           free (dargv);
 
            if (status == 2)
            {
Index: src/rcscmds.c
===================================================================
RCS file: /cvs/ccvs/src/rcscmds.c,v
retrieving revision 1.52.4.5
retrieving revision 1.52.4.6
diff -u -p -r1.52.4.5 -r1.52.4.6
--- src/rcscmds.c       16 Mar 2005 22:00:45 -0000      1.52.4.5
+++ src/rcscmds.c       27 May 2005 16:25:11 -0000      1.52.4.6
@@ -56,8 +56,8 @@
    On a related note, see the comments at diff_exec, later in this file,
    for more on the diff library.  */
 
-static void RCS_output_diff_options PROTO ((const char *, const char *,
-                                            const char *, const char *));
+static void RCS_output_diff_options PROTO ((int, char *const *, const char *,
+                                           const char *, const char *));
 
 
 /* Stuff to deal with passing arguments the way libdiff.a wants to deal
@@ -69,7 +69,7 @@ static void RCS_output_diff_options PROT
    argument will be parsed into whitespace separated words and added
    to the global call_diff_argv list.
 
-   Then, optionally, call call_diff_arg for each additional argument
+   Then, optionally, call call_diff_add_arg for each additional argument
    that you'd like to pass to the diff library.
 
    Finally, call call_diff or call_diff3 to produce the diffs.  */
@@ -79,7 +79,8 @@ static int call_diff_argc;
 static int call_diff_argc_allocated;
 
 static void call_diff_add_arg PROTO ((const char *));
-static void call_diff_setup PROTO ((const char *prog));
+static void call_diff_setup PROTO ((const char *prog,
+                                   int argc, char * const *argv));
 static int call_diff PROTO ((const char *out));
 static int call_diff3 PROTO ((char *out));
 
@@ -88,62 +89,37 @@ static void call_diff_flush_output PROTO
 static void call_diff_write_stdout PROTO((const char *));
 static void call_diff_error PROTO((const char *, const char *, const char *));
 
+
+
+static void
+call_diff_add_arg (s)
+    const char *s;
+{
+    run_add_arg_p (&call_diff_argc, &call_diff_argc_allocated, &call_diff_argv,
+                  s);
+}
+
+
+
 /* VARARGS */
 static void 
-call_diff_setup (prog)
+call_diff_setup (prog, argc, argv)
     const char *prog;
+    int argc;
+    char * const *argv;
 {
-    char *cp;
     int i;
-    char *call_diff_prog;
 
     /* clean out any malloc'ed values from call_diff_argv */
-    for (i = 0; i < call_diff_argc; i++)
-    {
-       if (call_diff_argv[i])
-       {
-           free (call_diff_argv[i]);
-           call_diff_argv[i] = (char *) 0;
-       }
-    }
+    run_arg_free_p (call_diff_argc, call_diff_argv);
     call_diff_argc = 0;
 
-    call_diff_prog = xstrdup (prog);
-
     /* put each word into call_diff_argv, allocating it as we go */
-    for (cp = strtok (call_diff_prog, " \t");
-        cp != NULL;
-        cp = strtok ((char *) NULL, " \t"))
-       call_diff_add_arg (cp);
-    free (call_diff_prog);
-}
-
-static void
-call_diff_arg (s)
-    const char *s;
-{
-    call_diff_add_arg (s);
+    call_diff_add_arg (prog);
+    for (i = 0; i < argc; i++)
+       call_diff_add_arg (argv[i]);
 }
 
-static void
-call_diff_add_arg (s)
-    const char *s;
-{
-    /* allocate more argv entries if we've run out */
-    if (call_diff_argc >= call_diff_argc_allocated)
-    {
-       call_diff_argc_allocated += 50;
-       call_diff_argv = (char **)
-           xrealloc ((char *) call_diff_argv,
-                     call_diff_argc_allocated * sizeof (char **));
-    }
-
-    if (s)
-       call_diff_argv[call_diff_argc++] = xstrdup (s);
-    else
-       /* Not post-incremented on purpose!  */
-       call_diff_argv[call_diff_argc] = (char *) 0;
-}
 
 /* Callback function for the diff library to write data to the output
    file.  This is used when we are producing output to stdout.  */
@@ -216,6 +192,8 @@ static int
 call_diff (out)
     const char *out;
 {
+    call_diff_add_arg (NULL);
+
     if (out == RUN_TTY)
        return diff_run (call_diff_argc, call_diff_argv, NULL,
                         &call_diff_stdout_callbacks);
@@ -308,21 +286,21 @@ RCS_merge(rcs, path, workfile, options, 
     /* Remember that the first word in the `call_diff_setup' string is used now
        only for diagnostic messages -- CVS no longer forks to run diff3. */
     diffout = cvs_temp_name();
-    call_diff_setup ("diff3");
-    call_diff_arg ("-E");
-    call_diff_arg ("-am");
-
-    call_diff_arg ("-L");
-    call_diff_arg (workfile);
-    call_diff_arg ("-L");
-    call_diff_arg (xrev1);
-    call_diff_arg ("-L");
-    call_diff_arg (xrev2);
-
-    call_diff_arg ("--");
-    call_diff_arg (workfile);
-    call_diff_arg (tmp1);
-    call_diff_arg (tmp2);
+    call_diff_setup ("diff3", 0, NULL);
+    call_diff_add_arg ("-E");
+    call_diff_add_arg ("-am");
+
+    call_diff_add_arg ("-L");
+    call_diff_add_arg (workfile);
+    call_diff_add_arg ("-L");
+    call_diff_add_arg (xrev1);
+    call_diff_add_arg ("-L");
+    call_diff_add_arg (xrev2);
+
+    call_diff_add_arg ("--");
+    call_diff_add_arg (workfile);
+    call_diff_add_arg (tmp1);
+    call_diff_add_arg (tmp2);
 
     retval = call_diff3 (diffout);
 
@@ -388,10 +366,11 @@ RCS_merge(rcs, path, workfile, options, 
    about this--any such features are undocumented in the context of
    CVS, and I'm not sure how important to users.  */
 int
-RCS_exec_rcsdiff(rcsfile, opts, options, rev1, rev1_cache, rev2,
-                 label1, label2, workfile )
+RCS_exec_rcsdiff (rcsfile, diff_argc, diff_argv, options, rev1, rev1_cache,
+                 rev2, label1, label2, workfile)
     RCSNode *rcsfile;
-    const char *opts;
+    int diff_argc;
+    char * const *diff_argv;
     const char *options;
     const char *rev1;
     const char *rev1_cache;
@@ -471,8 +450,9 @@ RCS file: ", 0);
        use_file2 = tmpfile2;
     }
 
-    RCS_output_diff_options (opts, rev1, rev2, workfile);
-    status = diff_exec( use_file1, use_file2, label1, label2, opts, RUN_TTY );
+    RCS_output_diff_options (diff_argc, diff_argv, rev1, rev2, workfile);
+    status = diff_exec (use_file1, use_file2, label1, label2,
+                       diff_argc, diff_argv, RUN_TTY);
     if (status >= 0)
     {
        retval = status;
@@ -551,16 +531,15 @@ RCS file: ", 0);
    message on stderr.  */
 
 int
-diff_exec (file1, file2, label1, label2, options, out)
+diff_exec (file1, file2, label1, label2, dargc, dargv, out)
     const char *file1;
     const char *file2;
     const char *label1;
     const char *label2;
-    const char *options;
+    int dargc;
+    char * const *dargv;
     const char *out;
 {
-    char *args;
-
 #ifdef PRESERVE_PERMISSIONS_SUPPORT
     /* If either file1 or file2 are special files, pretend they are
        /dev/null.  Reason: suppose a file that represents a block
@@ -594,18 +573,15 @@ diff_exec (file1, file2, label1, label2,
     }
 #endif
 
-    args = xmalloc (strlen (options) + 10);
-    /* The first word in this string is used only for error reporting. */
-    sprintf (args, "diff %s", options);
-    call_diff_setup (args);
+    /* The first arg to call_diff_setup is used only for error reporting. */
+    call_diff_setup ("diff", dargc, dargv);
     if (label1)
-       call_diff_arg (label1);
+       call_diff_add_arg (label1);
     if (label2)
-       call_diff_arg (label2);
-    call_diff_arg ("--");
-    call_diff_arg (file1);
-    call_diff_arg (file2);
-    free (args);
+       call_diff_add_arg (label2);
+    call_diff_add_arg ("--");
+    call_diff_add_arg (file1);
+    call_diff_add_arg (file2);
 
     return call_diff (out);
 }
@@ -617,19 +593,23 @@ diff_exec (file1, file2, label1, label2,
    that I have seen. */
 
 static void
-RCS_output_diff_options (opts, rev1, rev2, workfile)
-    const char *opts;
+RCS_output_diff_options (diff_argc, diff_argv, rev1, rev2, workfile)
+    int diff_argc;
+    char * const *diff_argv;
     const char *rev1;
     const char *rev2;
     const char *workfile;
 {
-    char *tmp;
-
-    tmp = (char *) xmalloc (strlen (opts) + strlen (rev1) + 10);
-
-    sprintf (tmp, "diff%s -r%s", opts, rev1);
-    cvs_output (tmp, 0);
-    free (tmp);
+    int i;
+    
+    cvs_output ("diff", 0);
+    for (i = 0; i < diff_argc; i++)
+    {
+        cvs_output (" ", 1);
+       cvs_output (diff_argv[i], 0);
+    }
+    cvs_output (" -r", 3);
+    cvs_output (rev1, 0);
 
     if (rev2)
     {
Index: src/run.c
===================================================================
RCS file: /cvs/ccvs/src/run.c,v
retrieving revision 1.33.6.3
retrieving revision 1.33.6.4
diff -u -p -r1.33.6.3 -r1.33.6.4
--- src/run.c   1 Apr 2004 19:07:51 -0000       1.33.6.3
+++ src/run.c   27 May 2005 16:25:11 -0000      1.33.6.4
@@ -36,7 +36,19 @@ extern char *strtok ();
  */
 static char **run_argv;
 static int run_argc;
-static int run_argc_allocated;
+static size_t run_argc_allocated;
+
+
+
+void
+run_arg_free_p (int argc, char **argv)
+{
+    int i;
+    for (i = 0; i < argc; i++)
+       free (argv[i]);
+}
+
+
 
 /* VARARGS */
 void 
@@ -44,18 +56,10 @@ run_setup (prog)
     const char *prog;
 {
     char *cp;
-    int i;
     char *run_prog;
 
     /* clean out any malloc'ed values from run_argv */
-    for (i = 0; i < run_argc; i++)
-    {
-       if (run_argv[i])
-       {
-           free (run_argv[i]);
-           run_argv[i] = (char *) 0;
-       }
-    }
+    run_arg_free_p (run_argc, run_argv);
     run_argc = 0;
 
     run_prog = xstrdup (prog);
@@ -73,22 +77,35 @@ run_arg (s)
     run_add_arg (s);
 }
 
-static void
-run_add_arg (s)
+
+
+void
+run_add_arg_p (iargc, iarg_allocated, iargv, s)
+    int *iargc;
+    size_t *iarg_allocated;
+    char ***iargv;
     const char *s;
 {
     /* allocate more argv entries if we've run out */
-    if (run_argc >= run_argc_allocated)
+    if (*iargc >= *iarg_allocated)
     {
-       run_argc_allocated += 50;
-       run_argv = (char **) xrealloc ((char *) run_argv,
-                                    run_argc_allocated * sizeof (char **));
+       *iarg_allocated += 50;
+       *iargv = xrealloc (*iargv, *iarg_allocated * sizeof (char **));
     }
 
     if (s)
-       run_argv[run_argc++] = xstrdup (s);
+       (*iargv)[(*iargc)++] = xstrdup (s);
     else
-       run_argv[run_argc] = (char *) 0;        /* not post-incremented on 
purpose! */
+       (*iargv)[*iargc] = NULL;        /* not post-incremented on purpose! */
+}
+
+
+
+static void
+run_add_arg (s)
+    const char *s;
+{
+    run_add_arg_p (&run_argc, &run_argc_allocated, &run_argv, s);
 }
 
 
Index: src/sanity.sh
===================================================================
RCS file: /cvs/ccvs/src/sanity.sh,v
retrieving revision 1.752.2.170
retrieving revision 1.752.2.171
diff -u -p -r1.752.2.170 -r1.752.2.171
--- src/sanity.sh       2 May 2005 17:06:56 -0000       1.752.2.170
+++ src/sanity.sh       27 May 2005 16:25:11 -0000      1.752.2.171
@@ -2204,7 +2204,7 @@ ${PLUS} ssfile line 2"
 ===================================================================
 RCS file: ${CVSROOT_DIRNAME}/first-dir/sdir/ssdir/ssfile,v
 retrieving revision 1\.1
-diff -c -C3isacrowd -r1\.1 ssfile
+diff -c -C 3isacrowd -r1\.1 ssfile
 ${PROG} diff: invalid context length argument"
          dotest basica-7 "${testcvs} -q ci -m modify-it" \
 "Checking in sdir/ssdir/ssfile;
@@ -4813,7 +4813,7 @@ done"
 ===================================================================
 RCS file: ${CVSROOT_DIRNAME}/first-dir/abc,v
 retrieving revision 1\.2
-diff --ifdef=HAVE_WINSOCK_H -r1\.2 abc
+diff --ifdef HAVE_WINSOCK_H -r1\.2 abc
 #ifndef HAVE_WINSOCK_H
 extern int gethostname ();
 #else /\* HAVE_WINSOCK_H \*/
@@ -7623,12 +7623,12 @@ mumble;
 }
 EOF
          # Use dotest_fail because exit status from `cvs diff' must be 1.
-         dotest_fail rcslib-diffrgx-3 "${testcvs} diff -c -F'.*(' rgx.c" \
+         dotest_fail rcslib-diffrgx-3 "${testcvs} diff -c -F'.* (' rgx.c" \
 "Index: rgx\.c
 ===================================================================
 RCS file: ${CVSROOT_DIRNAME}/first-dir/rgx\.c,v
 retrieving revision 1\.1
-diff -c -F\.\*( -r1\.1 rgx\.c
+diff -c -F \.\* ( -r1\.1 rgx\.c
 \*\*\* rgx\.c  ${RFCDATE}      1\.1
 --- rgx\.c     ${RFCDATE}
 \*\*\*\*\*\*\*\*\*\*\*\*\*\*\* test_regex (whiz, bang)
Index: src/update.c
===================================================================
RCS file: /cvs/ccvs/src/update.c,v
retrieving revision 1.202.4.24
retrieving revision 1.202.4.25
diff -u -p -r1.202.4.24 -r1.202.4.25
--- src/update.c        16 Mar 2005 22:00:45 -0000      1.202.4.24
+++ src/update.c        27 May 2005 16:25:14 -0000      1.202.4.25
@@ -1724,7 +1724,9 @@ patch_file (finfo, vers_ts, docheckout, 
     retcode = 0;
     if (! fail)
     {
-       char *diff_options;
+       int dargc = 0;
+       size_t darg_allocated = 0;
+       char **dargv = NULL;
 
        /* If the client does not support the Rcs-diff command, we
            send a context diff, and the client must invoke patch.
@@ -1732,16 +1734,13 @@ patch_file (finfo, vers_ts, docheckout, 
            new approach only requires running diff in the server; the
            client can handle everything without invoking an external
            program.  */
-       if (! rcs_diff_patches)
-       {
+       if (!rcs_diff_patches)
            /* We use -c, not -u, because that is what CVS has
               traditionally used.  Kind of a moot point, now that
               Rcs-diff is preferred, so there is no point in making
               the compatibility issues worse.  */
-           diff_options = "-c";
-       }
+           run_add_arg_p (&dargc, &darg_allocated, &dargv, "-c");
        else
-       {
            /* Now that diff is librarified, we could be passing -a if
               we wanted to.  However, it is unclear to me whether we
               would want to.  Does diff -a, in any significant
@@ -1751,10 +1750,11 @@ patch_file (finfo, vers_ts, docheckout, 
               'binary'.  Conversely, do they tend to be much larger
               in the bad cases?  This needs some more
               thought/investigation, I suspect.  */
-
-           diff_options = "-n";
-       }
-       retcode = diff_exec (file1, file2, NULL, NULL, diff_options, 
finfo->file);
+           run_add_arg_p (&dargc, &darg_allocated, &dargv, "-n");
+       retcode = diff_exec (file1, file2, NULL, NULL, dargc, dargv,
+                            finfo->file);
+       run_arg_free_p (dargc, dargv);
+       free (dargv);
 
        /* A retcode of 0 means no differences.  1 means some differences.  */
        if (retcode != 0

reply via email to

[Prev in Thread] Current Thread [Next in Thread]