]> andersk Git - moira.git/commitdiff
stella, a command line client for manipulating the machine table.
authorzacheiss <zacheiss>
Thu, 10 Feb 2000 05:33:43 +0000 (05:33 +0000)
committerzacheiss <zacheiss>
Thu, 10 Feb 2000 05:33:43 +0000 (05:33 +0000)
clients/stella/Makefile.in [new file with mode: 0644]
clients/stella/stella.c [new file with mode: 0644]

diff --git a/clients/stella/Makefile.in b/clients/stella/Makefile.in
new file mode 100644 (file)
index 0000000..3dc1b04
--- /dev/null
@@ -0,0 +1,46 @@
+# $Id$
+
+SHELL=/bin/sh
+@SET_MAKE@
+
+CC=@CC@
+CPPFLAGS=@CPPFLAGS@
+CFLAGS=@CFLAGS@
+DEFS=@DEFS@
+ALL_CFLAGS=$(CPPFLAGS) $(CFLAGS) $(DEFS)
+LDFLAGS=@LDFLAGS@
+LIBS=../lib/libmrclient.a @LIBS@
+MR_LIBDEP=@MR_LIBDEP@
+INSTALL=@INSTALL@
+INSTALL_PROGRAM=@INSTALL_PROGRAM@
+
+srcdir=@srcdir@
+VPATH=@srcdir@
+SRCTOP=@top_srcdir@
+BUILDTOP=../..
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+bindir=@bindir@
+
+OBJS=stella.o
+
+TARGET=stella
+
+.c.o:
+       $(CC) -c $(ALL_CFLAGS) $<
+
+all: $(TARGET)
+
+clean:
+       rm -f $(OBJS) $(TARGET)
+
+cleandir distclean: clean
+       rm -f Makefile
+
+depend:
+
+install: all
+       $(INSTALL_PROGRAM) stella $(bindir)
+
+$(TARGET): $(OBJS) ../lib/libmrclient.a $(MR_LIBDEP)
+       $(CC) -o $@ $(LDFLAGS) $(OBJS) $(LIBS)
diff --git a/clients/stella/stella.c b/clients/stella/stella.c
new file mode 100644 (file)
index 0000000..1281c2d
--- /dev/null
@@ -0,0 +1,790 @@
+/*
+ * Command line oriented Moira host tool.
+ *
+ * kolya@MIT.EDU, January 2000
+ *
+ * Somewhat based on blanche
+ *
+ * Copyright (C) 2000 by the Massachusetts Institute of Technology.
+ * For copying and distribution information, please see the file
+ * <mit-copyright.h>.
+ */
+
+#include <mit-copyright.h>
+#include <moira.h>
+#include <moira_site.h>
+#include <mrclient.h>
+
+#include <ctype.h>
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+RCSID("$Header$");
+
+struct owner_type {
+  int type;
+  char *name;
+};
+
+struct mqelem {
+  struct mqelem *q_forw;
+  struct mqelem *q_back;
+  void *q_data;
+};
+
+struct string_list {
+  char *string;
+  struct string_list *next;
+};
+
+/* It is important to membercmp that M_USER < M_LIST < M_STRING */
+#define M_ANY          0
+#define M_USER         1
+#define M_LIST         2
+#define M_STRING       3
+#define M_KERBEROS     4
+#define        M_NONE          5
+
+/* argument parsing macro */
+#define argis(a, b) (!strcmp(*arg + 1, a) || !strcmp(*arg + 1, b))
+
+/* flags from command line */
+int info_flag, update_flag, create_flag, delete_flag, list_map_flag;
+int update_map_flag, verbose, noauth;
+
+struct string_list *alias_add_queue, *alias_remove_queue;
+struct string_list *map_add_queue, *map_remove_queue;
+
+char *hostname, *whoami;
+
+char *newname, *address, *network, *h_status, *vendor, *model;
+char *os, *location, *contact, *adm_cmt, *op_cmt;
+
+struct owner_type *owner;
+
+void usage(char **argv);
+int store_host_info(int argc, char **argv, void *hint);
+void show_host_info(char **argv);
+int show_machine_in_cluster(int argc, char **argv, void *hint);
+struct owner_type *parse_member(char *s);
+struct string_list *add_to_string_list(struct string_list *old_list, char *s);
+int wrap_mr_query(char *handle, int argc, char **argv,
+                 int (*callback)(int, char **, void *), void *callarg);
+void print_query(char *query_name, int argc, char **argv);
+
+int main(int argc, char **argv)
+{
+  int status, success;
+  char **arg = argv;
+  char *server = NULL, *p;
+
+  /* clear all flags & lists */
+  info_flag = update_flag = create_flag = list_map_flag = update_map_flag = 0;
+  verbose = noauth = 0;
+  newname = address = network = h_status = vendor = model = NULL;
+  os = location = contact = adm_cmt = op_cmt = NULL;
+  owner = NULL;
+  alias_add_queue = alias_remove_queue = NULL;
+  map_add_queue = map_remove_queue = NULL;
+  whoami = argv[0];
+
+  success = 1;
+
+  /* parse args, building addlist, dellist, & synclist */
+  while (++arg - argv < argc)
+    {
+      if (**arg == '-')
+       {
+         if (argis("i", "info"))
+           info_flag++;
+         else if (argis("C", "create"))
+           create_flag++;
+         else if (argis("D", "delete"))
+           delete_flag++;
+         else if (argis("R", "rename")) {
+           if (arg - argv < argc - 1) {
+             arg++;
+             update_flag++;
+             newname = *arg;
+           } else
+             usage(argv);
+         }
+         else if (argis("A", "address")) {
+           if (arg - argv < argc - 1) {
+             arg++;
+             update_flag++;
+             address = *arg;
+           } else
+             usage(argv);
+         }
+         else if (argis("O", "owner")) {
+           if (arg - argv < argc - 1) {
+             arg++;
+             update_flag++;
+             owner = parse_member(*arg);
+           } else
+             usage(argv);
+         }
+         else if (argis("N", "network")) {
+           if (arg - argv < argc - 1) {
+             arg++;
+             update_flag++;
+             network = *arg;
+           } else
+             usage(argv);
+         }
+         else if (argis("S", "status")) {
+           if (arg - argv < argc - 1) {
+             int i;
+
+             arg++;
+             update_flag++;
+             h_status = *arg;
+
+             for(i=0; i<strlen(h_status); i++) {
+               if(!isdigit(h_status[i])) {
+                 printf("Error: status code %s is not numeric.\n", h_status);
+                 exit(1);
+               }
+             }
+           } else
+             usage(argv);
+         }
+         else if (argis("V", "vendor")) {
+           if (arg - argv < argc - 1) {
+             arg++;
+             update_flag++;
+             vendor = *arg;
+           } else
+             usage(argv);
+         }
+         else if (argis("M", "model")) {
+           if (arg - argv < argc - 1) {
+             arg++;
+             update_flag++;
+             model = *arg;
+           } else
+             usage(argv);
+         }
+         else if (argis("o", "os")) {
+           if (arg - argv < argc - 1) {
+             arg++;
+             update_flag++;
+             os = *arg;
+           } else
+             usage(argv);
+         }
+         else if (argis("L", "location")) {
+           if (arg - argv < argc - 1) {
+             arg++;
+             update_flag++;
+             location = *arg;
+           } else
+             usage(argv);
+         }
+         else if (argis("c", "contact")) {
+           if (arg - argv < argc - 1) {
+             arg++;
+             update_flag++;
+             contact = *arg;
+           } else
+             usage(argv);
+         }
+         else if (argis("ac", "admcmt")) {
+           if (arg - argv < argc - 1) {
+             arg++;
+             update_flag++;
+             adm_cmt = *arg;
+           } else
+             usage(argv);
+         }
+         else if (argis("oc", "opcmt")) {
+           if (arg - argv < argc - 1) {
+             arg++;
+             update_flag++;
+             op_cmt = *arg;
+           } else
+             usage(argv);
+         }
+         else if (argis("a", "aliasadd")) {
+           if (arg - argv < argc - 1) {
+             arg++;
+             alias_add_queue=add_to_string_list(alias_add_queue, *arg);
+           } else
+             usage(argv);
+         }
+         else if (argis("d", "aliasdelete")) {
+           if (arg - argv < argc - 1) {
+             arg++;
+             alias_remove_queue=add_to_string_list(alias_remove_queue, *arg);
+           } else
+             usage(argv);
+         }
+         else if (argis("am", "addmap")) {
+           if (arg - argv < argc - 1) {
+             arg++;
+             map_add_queue=add_to_string_list(map_add_queue, *arg);
+           } else
+             usage(argv);
+           update_map_flag++;
+         }
+         else if (argis("dm", "deletemap")) {
+           if (arg - argv < argc - 1) {
+             arg++;
+             map_remove_queue=add_to_string_list(map_remove_queue, *arg);
+           } else
+             usage(argv);
+           update_map_flag++;
+         }
+         else if (argis("lm", "listmap"))
+           list_map_flag++;
+         else if (argis("n", "noauth"))
+           noauth++;
+         else if (argis("v", "verbose"))
+           verbose++;
+         else if (argis("db", "database"))
+           {
+             if (arg - argv < argc - 1)
+               {
+                 ++arg;
+                 server = *arg;
+               }
+             else
+               usage(argv);
+           }
+         else
+           usage(argv);
+       }
+      else if (hostname == NULL)
+       hostname = *arg;
+      else
+       usage(argv);
+    }
+  if (hostname == NULL)
+    usage(argv);
+
+  /* default to info_flag if nothing else was specified */
+  if(!(info_flag   || update_flag   || create_flag     || \
+       delete_flag || list_map_flag || update_map_flag )) {
+    info_flag++;
+  }
+
+  /* fire up Moira */
+  status = mrcl_connect(server, "stella", 2, !noauth);
+  if (status == MRCL_AUTH_ERROR)
+    {
+      com_err(whoami, 0, "Try the -noauth flag if you don't "
+             "need authentication.");
+    }
+  if (status)
+    exit(2);
+
+  /* create if needed */
+  if (create_flag)
+    {
+      char *argv[30];
+      int cnt;
+
+      for (cnt = 0; cnt < 15; cnt++) {
+       argv[cnt] = "";
+      }
+
+      argv[0] = canonicalize_hostname(strdup(hostname));
+
+      if (vendor)
+       argv[1] = vendor;
+      if (model)
+       argv[2] = model;
+      if (os)
+       argv[3] = os;
+      if (location)
+       argv[4] = location;
+      if (contact)
+       argv[5] = contact;
+      /* The use field always gets set to "0" */
+      argv[6] = "0";
+      if (h_status)
+       argv[7] = h_status;
+      else
+       argv[7] = "1";
+      if (network)
+       argv[8] = network;
+      if (address)
+       argv[9] = address;
+      if (adm_cmt)
+       argv[12] = adm_cmt;
+      if (op_cmt)
+       argv[13] = op_cmt;
+
+      if (owner)
+       {
+         argv[11] = owner->name;
+         switch (owner->type)
+           {
+           case M_ANY:
+           case M_USER:
+             argv[10] = "USER";
+             status = wrap_mr_query("add_host", 14, argv, NULL, NULL);
+             if (owner->type != M_ANY || status != MR_USER)
+               break;
+
+           case M_LIST:
+             argv[10] = "LIST";
+             status = wrap_mr_query("add_host", 14, argv, NULL, NULL);
+             break;
+
+           case M_KERBEROS:
+             argv[10] = "KERBEROS";
+             status = wrap_mr_query("add_host", 14, argv, NULL, NULL);
+             break;
+
+           case M_NONE:
+             argv[10] = "NONE";
+             status = wrap_mr_query("add_host", 14, argv, NULL, NULL);
+             break;
+           }
+       }
+      else
+       {
+         argv[10] = "NONE";
+         argv[11] = "NONE";
+
+         status = wrap_mr_query("add_host", 14, argv, NULL, NULL);
+       }
+
+      if (status)
+       {
+         com_err(whoami, status, "while creating host.");
+         exit(1);
+       }
+
+    }
+  else if (update_flag)
+    {
+      char *old_argv[30];
+      char *argv[16];
+      char *args[5];
+      int cnt;
+
+      args[0] = canonicalize_hostname(strdup(hostname));
+      args[1] = args[2] = args[3] = "*";
+
+      status = wrap_mr_query("get_host", 4, args, store_host_info, old_argv);
+      if (status)
+       {
+         com_err(whoami, status, "while getting list information");
+         exit(1);
+       }
+
+      argv[1] = old_argv[0];
+      argv[2] = old_argv[1];
+      argv[3] = old_argv[2];
+      argv[4] = old_argv[3];
+      argv[5] = old_argv[4];
+      argv[6] = old_argv[5];
+      argv[7] = old_argv[6];
+      argv[8] = old_argv[7];
+      argv[9] = old_argv[9];
+      argv[10] = old_argv[10];
+      argv[11] = old_argv[11];
+      argv[12] = old_argv[12];
+      argv[13] = old_argv[13];
+      argv[14] = old_argv[14];
+
+      argv[0] = canonicalize_hostname(strdup(hostname));
+      if (newname)
+       argv[1] = newname;
+      if (vendor)
+       argv[2] = vendor;
+      if (model)
+       argv[3] = model;
+      if (os)
+       argv[4] = os;
+      if (location)
+       argv[5] = location;
+      if (contact)
+       argv[6] = contact;
+      if (h_status)
+       argv[8] = h_status;
+      if (network)
+       argv[9] = network;
+      if (address)
+       argv[10] = address;
+      if (adm_cmt)
+       argv[13] = adm_cmt;
+      if (op_cmt)
+       argv[14] = op_cmt;
+
+      if (owner)
+       {
+         argv[12] = owner->name;
+         switch (owner->type)
+           {
+           case M_ANY:
+           case M_USER:
+             argv[11] = "USER";
+             status = wrap_mr_query("update_host", 15, argv, NULL, NULL);
+             if (owner->type != M_ANY || status != MR_USER)
+               break;
+
+           case M_LIST:
+             argv[11] = "LIST";
+             status = wrap_mr_query("update_host", 15, argv, NULL, NULL);
+             break;
+
+           case M_KERBEROS:
+             argv[11] = "KERBEROS";
+             status = wrap_mr_query("update_host", 15, argv, NULL, NULL);
+             break;
+
+           case M_NONE:
+             argv[11] = "NONE";
+             status = wrap_mr_query("update_host", 15, argv, NULL, NULL);
+             break;
+           }
+       }
+      else
+       status = wrap_mr_query("update_host", 15, argv, NULL, NULL);
+
+      if (status)
+       com_err(whoami, status, "while updating host.");
+      else if (newname)
+       hostname = newname;
+    }
+
+  /* create aliases if necessary */
+  if (alias_add_queue) {
+    struct string_list *q = alias_add_queue;
+
+    while(q) {
+      char *alias = q->string;
+      char *args[2];
+
+      args[0] = canonicalize_hostname(strdup(alias));
+      args[1] = canonicalize_hostname(strdup(hostname));
+      status = wrap_mr_query("add_hostalias", 2, args, NULL, NULL);
+      if (status) {
+       com_err(whoami, status, "while adding host alias");
+       exit(1);
+      }
+
+      q = q->next;
+    }
+  }
+
+  /* delete aliases if necessary */
+  if (alias_remove_queue) {
+    struct string_list *q = alias_remove_queue;
+
+    while(q) {
+      char *alias = q->string;
+      char *args[2];
+
+      args[0] = canonicalize_hostname(strdup(alias));
+      args[1] = canonicalize_hostname(strdup(hostname));
+      status = wrap_mr_query("delete_hostalias", 2, args, NULL, NULL);
+      if (status) {
+       com_err(whoami, status, "while deleting host alias");
+       exit(1);
+      }
+
+      q = q->next;
+    }
+  }
+
+  /* create cluster mappings */
+  if (map_add_queue) {
+    struct string_list *q = map_add_queue;
+
+    while(q) {
+      char *clustername = q->string;
+      char *args[2];
+
+      args[0] = canonicalize_hostname(strdup(hostname));
+      args[1] = clustername;
+      status = wrap_mr_query("add_machine_to_cluster", 2, args, NULL, NULL);
+      if (status) {
+       com_err(whoami, status, "while adding cluster mapping");
+       exit(1);
+      }
+
+      q = q->next;
+    }
+  }
+
+  /* delete cluster mappings */
+  if (map_remove_queue) {
+    struct string_list *q = map_remove_queue;
+
+    while(q) {
+      char *clustername = q->string;
+      char *args[2];
+
+      args[0] = canonicalize_hostname(strdup(hostname));
+      args[1] = clustername;
+      status = wrap_mr_query("delete_machine_from_cluster", 2, args,
+                            NULL, NULL);
+      if (status) {
+       com_err(whoami, status, "while deleting cluster mapping");
+       exit(1);
+      }
+
+      q = q->next;
+    }
+  }
+
+  /* display list info if requested to */
+  if (info_flag) {
+    struct mqelem *elem = NULL;
+    char *args[5];
+    char *argv[30];
+
+    args[0] = canonicalize_hostname(strdup(hostname));
+    args[1] = args[2] = args[3] = "*";
+    status = wrap_mr_query("get_host", 4, args, store_host_info, argv);
+    if (status) {
+      com_err(whoami, status, "while getting host information");
+      exit(1);
+    }
+    show_host_info(argv);
+  }
+
+  /* list cluster mappings if needed */
+  if (list_map_flag) {
+    char *args[3];
+
+    args[0] = canonicalize_hostname(strdup(hostname));
+    args[1] = "*";
+    status = wrap_mr_query("get_machine_to_cluster_map", 2, args,
+                     show_machine_in_cluster, NULL);
+    if (status)
+      if (status != MR_NO_MATCH) {
+        com_err(whoami, status, "while getting cluster mappings");
+        exit(1);
+      }
+  }
+
+  if (delete_flag) {
+    char *argv[1];
+
+    argv[0] = canonicalize_hostname(strdup(hostname));
+    status = wrap_mr_query("delete_host", 1, argv, NULL, NULL);
+    if (status) {
+      com_err(whoami, status, "while deleting host");
+      exit(1);
+    }
+  }
+
+  /* We're done! */
+  mr_disconnect();
+  exit(success ? 0 : 1);
+}
+
+void usage(char **argv)
+{
+  fprintf(stderr, "Usage: %s hostname [options]\n", argv[0]);
+  fprintf(stderr, "Options are\n");
+  fprintf(stderr, "  %-39s%-39s\n", "-C   | -create",
+         "-O   | -owner owner");
+  fprintf(stderr, "  %-39s%-39s\n", "-D   | -delete",
+         "-S   | -status status");
+  fprintf(stderr, "  %-39s%-39s\n", "-R   | -rename newname",
+         "-V   | -vendor vendor");
+  fprintf(stderr, "  %-39s%-39s\n", "-a   | -addalias alias",
+         "-M   | -model model");
+  fprintf(stderr, "  %-39s%-39s\n", "-d   | -deletealias alias",
+         "-L   | -location location");
+  fprintf(stderr, "  %-39s%-39s\n", "-i   | -info",
+         "-o   | -os os");
+  fprintf(stderr, "  %-39s%-39s\n", "-oc  | -opcmt op_cmt",
+         "-c   | -contact contact");
+  fprintf(stderr, "  %-39s%-39s\n", "-ac  | -admcmt adm_cmt",
+         "-A   | -address address");
+  fprintf(stderr, "  %-39s%-39s\n", "-am  | -addmap cluster",
+         "-N   | -network network");
+  fprintf(stderr, "  %-39s%-39s\n", "-dm  | -deletemap cluster",
+         "-lm  | -listmap");
+  fprintf(stderr, "  %-39s%-39s\n", "-db  | -database host[:port]",
+         "-n   | -noauth");
+  fprintf(stderr, "  %-39s%-39s\n", "-v   | -verbose",
+         "");
+  exit(1);
+}
+
+/* Show alias information */
+
+static int show_has_aliases;
+
+int show_alias_info(int argc, char **argv, void *hint)
+{
+  if(!show_has_aliases++)
+    printf("Aliases:  %s", argv[0]);
+  else
+    printf(", %s", argv[0]);
+
+  return MR_CONT;
+}
+
+static char *states[] = {
+  "Reserved (0)",
+  "Active (1)",
+  "None (2)",
+  "Deleted (3)"
+};
+
+static char *MacState(int state)
+{
+  static char buf[BUFSIZ];
+
+  if (state < 0 || state > 3)
+    {
+      sprintf(buf, "Unknown (%d)", state);
+      return buf;
+    }
+  return states[state];
+}
+
+/* Retrieve information about a host */
+
+int store_host_info(int argc, char **argv, void *hint)
+{
+  int i;
+  char **nargv = hint;
+
+  for(i=0; i<argc; i++)
+    nargv[i] = strdup(argv[i]);
+
+  return MR_CONT;
+}
+
+void show_host_info(char **argv)
+{
+  char tbuf[256];
+  char *args[3];
+  struct mqelem *elem = NULL;
+  int stat;
+
+  printf("Machine:  %s\n", argv[M_NAME]);
+  args[0] = "*";
+  args[1] = argv[M_NAME];
+  show_has_aliases = 0;
+  stat = wrap_mr_query("get_hostalias", 2, args, show_alias_info, &elem);
+  printf("\n");
+  if (stat) {
+    if (stat != MR_NO_MATCH)
+      com_err(whoami, stat, "while getting aliases");
+  } else {
+    printf("\n");
+  }
+  sprintf(tbuf, "%s %s", argv[M_OWNER_TYPE],
+          strcmp(argv[M_OWNER_TYPE], "NONE") ? argv[M_OWNER_NAME] : "");
+  printf("Address:  %-16s    Network:    %-16s\n",
+          argv[M_ADDR], argv[M_SUBNET]);
+  printf("Owner:    %-16s    Use data:   %s\n", tbuf, argv[M_INUSE]);
+  printf("Status:   %-16s    Changed:    %s\n",
+          MacState(atoi(argv[M_STAT])), argv[M_STAT_CHNG]);
+  printf("\n");
+
+  printf("Vendor:   %-16s    Model:      %-20s  OS:  %s\n",
+          argv[M_VENDOR], argv[M_MODEL], argv[M_OS]);
+  printf("Location: %-16s    Contact:    %-20s  Opt: %s\n",
+          argv[M_LOC], argv[M_CONTACT], argv[M_USE]);
+  printf("\nAdm cmt: %s\n", argv[M_ACOMMENT]);
+  printf("Op cmt:  %s\n", argv[M_OCOMMENT]);
+  printf("\n");
+  printf("Created  by %s on %s\n", argv[M_CREATOR], argv[M_CREATED]);
+  printf("Last mod by %s at %s with %s.\n", argv[M_MODBY], argv[M_MODTIME], argv[M_MODWITH]);
+}
+
+int show_machine_in_cluster(int argc, char **argv, void *hint)
+{
+  printf("Machine: %-30s Cluster: %-30s\n", argv[0], argv[1]);
+
+  return MR_CONT;
+}
+
+/* Parse a line of input, fetching a member.  NULL is returned if a member
+ * is not found.  ';' is a comment character.
+ */
+
+struct owner_type *parse_member(char *s)
+{
+  struct owner_type *m;
+  char *p, *lastchar;
+
+  while (*s && isspace(*s))
+    s++;
+  lastchar = p = s;
+  while (*p && *p != '\n' && *p != ';')
+    {
+      if (isprint(*p) && !isspace(*p))
+       lastchar = p++;
+      else
+       p++;
+    }
+  lastchar++;
+  *lastchar = '\0';
+  if (p == s || strlen(s) == 0)
+    return NULL;
+
+  if (!(m = malloc(sizeof(struct owner_type))))
+    return NULL;
+
+  if ((p = strchr(s, ':')))
+    {
+      *p = '\0';
+      m->name = ++p;
+      if (!strcasecmp("user", s))
+       m->type = M_USER;
+      else if (!strcasecmp("list", s))
+       m->type = M_LIST;
+      else if (!strcasecmp("string", s))
+       m->type = M_STRING;
+      else if (!strcasecmp("kerberos", s))
+       m->type = M_KERBEROS;
+      else if (!strcasecmp("none", s))
+       m->type = M_NONE;
+      else
+       {
+         m->type = M_ANY;
+         *(--p) = ':';
+         m->name = s;
+       }
+      m->name = strdup(m->name);
+    }
+  else
+    {
+      m->name = strdup(s);
+      m->type = strcasecmp(s, "none") ? M_ANY : M_NONE;
+    }
+  return m;
+}
+
+struct string_list *add_to_string_list(struct string_list *old_list, char *s) {
+  struct string_list *new_list;
+
+  new_list = (struct string_list *)malloc(sizeof(struct string_list *));
+  new_list->next = old_list;
+  new_list->string = s;
+
+  return new_list;
+}
+
+int wrap_mr_query(char *handle, int argc, char **argv,
+                  int (*callback)(int, char **, void *), void *callarg) {
+  if (verbose)
+    print_query(handle, argc, argv);
+
+  return mr_query(handle, argc, argv, callback, callarg);
+}
+
+void print_query(char *query_name, int argc, char **argv) {
+  int cnt;
+
+  printf("qy %s", query_name);
+  for(cnt=0; cnt<argc; cnt++)
+    printf(" <%s>", argv[cnt]);
+  printf("\n");
+}
This page took 0.140492 seconds and 5 git commands to generate.