cvs-cvs
[Top][All Lists]
Advanced

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

[Cvs-cvs] Changes to ccvs/src/sign.c [signed-commits]


From: Derek Robert Price
Subject: [Cvs-cvs] Changes to ccvs/src/sign.c [signed-commits]
Date: Fri, 14 Oct 2005 21:39:38 -0400

Index: ccvs/src/sign.c
diff -u ccvs/src/sign.c:1.1.2.1 ccvs/src/sign.c:1.1.2.2
--- ccvs/src/sign.c:1.1.2.1     Wed Oct 12 02:46:37 2005
+++ ccvs/src/sign.c     Sat Oct 15 01:39:25 2005
@@ -20,7 +20,285 @@
 # include <config.h>
 #endif
 
+/* Verify interface.  */
 #include "sign.h"
 
-/* Sign configuration that may be set via CVS global command line options.  */
-char *sign_textmode;
+/* Standard headers.  */
+#include <assert.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+/* GNULIB headers.  */
+#include "error.h"
+#include "xalloc.h"
+
+/* CVS headers.  */
+#include "root.h"
+#include "run.h"
+#include "stack.h"
+#include "stack.h"
+#include "subr.h"
+
+
+
+extern int noexec;
+
+
+
+/*
+ * Globals set via the command line parser in main.c.
+ */
+
+/* If a GPG-like program couldn't be found at compile time, default the sign
+ * state to off, otherwise, depend on the server support.
+ */
+#ifdef GPG_PROGRAM
+static sign_state sign_commits = SIGN_DEFAULT;
+#else
+static sign_state sign_commits = SIGN_NEVER;
+#endif
+
+static char *sign_template;
+static char *sign_textmode;
+static List *sign_args;
+
+
+
+void
+set_sign_commits (sign_state sign)
+{
+    sign_commits = sign;
+}
+
+
+
+void
+set_sign_template (const char *template)
+{
+    assert (template);
+    if (sign_template) free (sign_template);
+    sign_template = xstrdup (template);
+}
+
+
+
+void
+set_sign_textmode (const char *textmode)
+{
+    assert (textmode);
+    if (sign_textmode) free (sign_textmode);
+    sign_textmode = xstrdup (textmode);
+}
+
+
+
+void
+add_sign_arg (const char *arg)
+{
+    if (!sign_args) sign_args = getlist ();
+    push_string (sign_args, xstrdup (arg));
+}
+
+
+
+/* Return true if the client should attempt to sign files sent to the server
+ * as part of a commit.
+ *
+ * INPUTS
+ *   server_support    Whether the server supports signed files.
+ */
+bool
+get_sign_commits (bool server_support)
+{
+    sign_state tmp;
+
+    if (sign_commits == SIGN_DEFAULT)
+       tmp = current_parsed_root->sign;
+    else
+       tmp = sign_commits;
+
+    return tmp == SIGN_ALWAYS || (tmp == SIGN_DEFAULT && server_support);
+}
+
+
+
+/* Return SIGN_TEMPLATE from the command line if it exists, else return the
+ * SIGN_TEMPLATE from CURRENT_PARSED_ROOT.
+ */
+static inline const char *
+get_sign_template (void)
+{
+    if (sign_template) return sign_template;
+    return current_parsed_root->sign_template;
+}
+
+
+
+/* Return SIGN_TEXTMODE from the command line if it exists, else return the
+ * SIGN_TEXTMODE from CURRENT_PARSED_ROOT.
+ */
+static inline const char *
+get_sign_textmode (void)
+{
+    if (sign_textmode) return sign_textmode;
+    return current_parsed_root->sign_textmode;
+}
+
+
+
+/* Return SIGN_ARGS from the command line if it exists, else return the
+ * SIGN_ARGS from CURRENT_PARSED_ROOT.
+ */
+static inline List *
+get_sign_args (void)
+{
+    if (sign_args && !list_isempty (sign_args)) return sign_args;
+    return current_parsed_root->sign_args;
+}
+
+
+
+/* This function is intended to be passed into walklist() with a list of args
+ * to be substituted into the sign template.
+ *
+ * closure will be a struct format_cmdline_walklist_closure
+ * where closure is undefined.
+ */
+static int
+sign_args_list_to_args_proc (Node *p, void *closure)
+{
+    struct format_cmdline_walklist_closure *c = closure;
+    char *arg = NULL;
+    const char *f;
+    char *d;
+    size_t doff;
+
+    if (p->data == NULL) return 1;
+
+    f = c->format;
+    d = *c->d;
+    /* foreach requested attribute */
+    while (*f)
+    {
+       switch (*f++)
+       {
+           case 'a':
+               arg = p->key;
+               break;
+           default:
+               error (1, 0,
+                      "Unknown format character or not a list attribute: %c",
+                      f[-1]);
+               /* NOTREACHED */
+               break;
+       }
+       /* copy the attribute into an argument */
+       if (c->quotes)
+       {
+           arg = cmdlineescape (c->quotes, arg);
+       }
+       else
+       {
+           arg = cmdlinequote ('"', arg);
+       }
+
+       doff = d - *c->buf;
+       expand_string (c->buf, c->length, doff + strlen (arg));
+       d = *c->buf + doff;
+       strncpy (d, arg, strlen (arg));
+       d += strlen (arg);
+       free (arg);
+
+       /* Always put the extra space on.  we'll have to back up a char
+        * when we're done, but that seems most efficient.
+        */
+       doff = d - *c->buf;
+       expand_string (c->buf, c->length, doff + 1);
+       d = *c->buf + doff;
+       *d++ = ' ';
+    }
+    /* correct our original pointer into the buff */
+    *c->d = d;
+    return 0;
+}
+
+
+
+/* Generate a signature and return it in allocated memory.  */
+char *
+get_signature (const char *srepos, const char *filename, bool bin, size_t *len)
+{
+    char *cmdline;
+    FILE *pipefp;
+    bool save_noexec = noexec;
+    char *sigbuf = NULL;
+    size_t sigoff = 0, sigsize = 64;
+    int pipestatus;
+
+    /*
+     * %p = shortrepos
+     * %r = repository
+     * %{a} = user defined sign args
+     * %t = textmode flag
+     * %s = file name
+     */
+    /*
+     * Cast any NULL arguments as appropriate pointers as this is an
+     * stdarg function and we need to be certain the caller gets what
+     * is expected.
+     */
+    cmdline = format_cmdline (
+#ifdef SUPPORT_OLD_INFO_FMT_STRINGS
+                             false, srepos,
+#endif /* SUPPORT_OLD_INFO_FMT_STRINGS */
+                             get_sign_template (),
+                             "a", ",", get_sign_args (),
+                             sign_args_list_to_args_proc, (void *) NULL,
+                             "p", "s", srepos,
+                             "r", "s", current_parsed_root->directory,
+                             "t", "s", bin ? NULL : get_sign_textmode (),
+                             "s", "s", filename,
+                             (char *) NULL);
+
+    if (!cmdline || !strlen (cmdline))
+       error (1, 0, "sign template resolved to the empty string!");
+
+    noexec = false;
+    if (!(pipefp = run_popen (cmdline, "r")))
+       error (1, errno, "failed to execute signature generator");
+    noexec = save_noexec;
+
+    do
+    {
+       size_t len;
+
+       sigsize *= 2;
+       sigbuf = xrealloc (sigbuf, sigsize);
+       len = fread (sigbuf + sigoff, sizeof *sigbuf, sigsize - sigoff,
+                    pipefp);
+       sigoff += len;
+       /* Fewer bytes than requested means EOF or error.  */
+    } while (sigsize == sigoff);
+
+    if (ferror (pipefp))
+       error (1, ferror (pipefp), "Error reading from sign program.");
+
+    pipestatus = pclose (pipefp);
+    if (pipestatus == -1)
+       error (1, errno,
+              "failed to obtain exit status from signature program");
+    else if (pipestatus)
+    {
+       if (WIFEXITED (pipestatus))
+           error (1, 0, "sign program exited with error code %d",
+                  WEXITSTATUS (pipestatus));
+       else
+           error (1, 0, "sign program exited via signal %d",
+                  WTERMSIG (pipestatus));
+    }
+
+    *len = sigoff;
+    return sigbuf;
+}




reply via email to

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