]> andersk Git - moira.git/blobdiff - clients/blanche/blanche.c
many new options for list creation and changing info
[moira.git] / clients / blanche / blanche.c
index 119e12b76117a6d21e28cc6e9e6e3bd9108b9dd0..0d0a69062f5a3c0d877c948e64fefc107652710f 100644 (file)
    Do we need to improve the support for queue operations? */
 
 #include <mit-copyright.h>
+#include <errno.h>
 #include <stdio.h>
+#include <stdlib.h>
 #include <ctype.h>
+#include <string.h>
 #include <moira.h>
 #include <moira_site.h>
 
@@ -41,19 +44,23 @@ struct member {
 #define argis(a,b) ((strcmp(*arg+1, a) == 0) || (strcmp(*arg+1, b) == 0))
 
 /* flags from command line */
-int infoflg, verbose, syncflg, memberflg, recursflg, debugflg, noauth;
+int infoflg, verbose, syncflg, memberflg, recursflg, noauth;
 int showusers, showstrings, showkerberos, showlists;
+int createflag, setinfo, active, public, hidden, maillist, grouplist;
+struct member *owner;
+char *desc, *newname;
 
 /* various member lists */
 struct save_queue *addlist, *dellist, *memberlist, *synclist;
 
 char *listname, *whoami;
 
-extern char *index();
+#ifndef POSIX
 extern int errno;
+#endif
 
 int show_list_info(), show_list_count(), get_list_members(), scream();
-int show_list_members(), membercmp();
+int show_list_members(), membercmp(), save_list_info();
 struct member *parse_member();
 
 
@@ -62,22 +69,27 @@ main(argc, argv)
 int argc;
 char **argv;
 {
-    int status;
+    int status, success;
     char **arg = argv;
     char *membervec[3], *motd;
     struct member *memberstruct;
     char *server = NULL, *p;
 
     /* clear all flags & lists */
-    infoflg = verbose = syncflg = memberflg = debugflg = recursflg = 0;
+    infoflg = verbose = syncflg = memberflg = recursflg = 0;
     noauth = showusers = showstrings = showkerberos = showlists = 0;
-    listname = NULL;
+    createflag = setinfo = 0;
+    active = public = hidden = maillist = grouplist = -1;
+    listname = newname = desc = NULL;
+    owner = NULL;
     addlist = sq_create();
     dellist = sq_create();
     memberlist = sq_create();
     synclist = sq_create();
     whoami = argv[0];
 
+    success = 1;
+
     /* parse args, building addlist, dellist, & synclist */
     while (++arg - argv < argc) {
        if  (**arg == '-')
@@ -92,8 +104,6 @@ char **argv;
                showlists++;
            else if (argis("k", "kerberos"))
                showkerberos++;
-           else if (argis("D", "debug"))
-               debugflg++;
            else if (argis("i","info"))
              infoflg++;
            else if (argis("n","noauth"))
@@ -102,7 +112,7 @@ char **argv;
              verbose++;
            else if (argis("r","recursive"))
              recursflg++;
-           else if (argis("S","server"))
+           else if (argis("S","server") || argis("db","database"))
                if (arg - argv < argc - 1) {
                    ++arg;
                    server = *arg;
@@ -141,6 +151,60 @@ char **argv;
                    get_members_from_file(*arg, synclist);
                } else
                  usage(argv);
+           else if (argis("C", "create"))
+               createflag++;
+           else if (argis("P", "public")) {
+               setinfo++;
+               public = 1;
+           } else if (argis("NP", "private")) {
+               setinfo++;
+               public = 0;
+           } else if (argis("A", "active")) {
+               setinfo++;
+               active = 1;
+           } else if (argis("I", "inactive")) {
+               setinfo++;
+               active = 0;
+           } else if (argis("V", "visible")) {
+               setinfo++;
+               hidden = 0;
+           } else if (argis("H", "hidden")) {
+               setinfo++;
+               hidden = 1;
+           } else if (argis("M", "mail")) {
+               setinfo++;
+               maillist = 1;
+           } else if (argis("NM", "notmail")) {
+               setinfo++;
+               maillist = 0;
+           } else if (argis("G", "group")) {
+               setinfo++;
+               grouplist = 1;
+           } else if (argis("NG", "notgroup")) {
+               setinfo++;
+               grouplist = 0;
+           } else if (argis("D", "desc"))
+               if (arg - argv < argc - 1) {
+                   setinfo++;
+                   ++arg;
+                   desc = *arg;
+               } else
+                 usage(argv);
+           else if (argis("O", "owner"))
+               if (arg - argv < argc - 1) {
+                   setinfo++;
+                   ++arg;
+                   owner = parse_member(*arg);
+               } else
+                 usage(argv);
+           else if (argis("R", "rename"))
+               if (arg - argv < argc - 1) {
+                   setinfo++;
+                   ++arg;
+                   newname = *arg;
+               } else
+                 usage(argv);
+               
            else
                usage(argv);
        }
@@ -153,7 +217,7 @@ char **argv;
       usage(argv);
 
     /* if no other options specified, turn on list members flag */
-    if (!(infoflg || syncflg ||
+    if (!(infoflg || syncflg || createflag || setinfo ||
          addlist->q_next != addlist || dellist->q_next != dellist))
       memberflg++;
 
@@ -187,6 +251,96 @@ char **argv;
        }
     }
 
+    /* create if needed */
+    if (createflag) {
+       char *argv[10];
+
+       argv[0] = listname;
+       argv[1] = (active == 0) ? "0" : "1";
+       argv[2] = (public == 1) ? "1" : "0";
+       argv[3] = (hidden == 1) ? "1" : "0";
+       argv[4] = (maillist == 0) ? "0" : "1";
+       argv[5] = (grouplist == 1) ? "1" : "0";
+       argv[6] = UNIQUE_GID;
+       argv[9] = desc ? desc : "none";
+
+       if (owner) {
+           argv[8] = owner->name;
+           switch (owner->type) {
+               case M_ANY:
+               case M_USER:
+                   argv[7] = "USER";
+                   status = mr_query("add_list", 10, argv, scream, NULL);
+                   if (owner->type != M_ANY || status != MR_USER)
+                       break;
+
+               case M_LIST:
+                   argv[7] = "LIST";
+                   status = mr_query("add_list", 10, argv, scream, NULL);
+                   break;
+
+               case M_KERBEROS:
+                   argv[7] = "KERBEROS";
+                   status = mr_query("add_list", 10, argv, scream, NULL);
+                   break;
+           }
+       } else {
+           argv[7] = "USER";
+           argv[8] = getenv("USER");
+
+           status = mr_query("add_list", 10, argv, scream, NULL);
+       }
+       
+       if (status) {
+           com_err(whoami, status, "while creating list.");
+           exit(1);
+       }
+    } else if (setinfo) {
+       char *argv[11];
+
+       status = mr_query("get_list_info", 1, &listname,
+                         save_list_info, (char *)argv);
+       if (status) {
+           com_err(whoami, status, "while getting list information");
+           exit(1);
+       }
+
+       argv[0] = listname;
+       if (newname) argv[1] = newname;
+       if (active != -1) argv[2] = active ? "1" : "0";
+       if (public != -1) argv[3] = public ? "1" : "0";
+       if (hidden != -1) argv[4] = hidden ? "1" : "0";
+       if (maillist != -1) argv[5] = maillist ? "1" : "0";
+       if (grouplist != -1) argv[6] = grouplist ? "1" : "0";
+       if (desc) argv[10] = desc;
+
+       if (owner) {
+           argv[9] = owner->name;
+           switch (owner->type) {
+               case M_ANY:
+               case M_USER:
+                   argv[8] = "USER";
+                   status = mr_query("update_list", 11, argv, scream, NULL);
+                   if (owner->type != M_ANY || status != MR_USER)
+                       break;
+
+               case M_LIST:
+                   argv[8] = "LIST";
+                   status = mr_query("update_list", 11, argv, scream, NULL);
+                   break;
+
+               case M_KERBEROS:
+                   argv[8] = "KERBEROS";
+                   status = mr_query("update_list", 11, argv, scream, NULL);
+                   break;
+           }
+       } else status = mr_query("update_list", 11, argv, scream, NULL);
+
+       if (status)
+           com_err(whoami, status, "while updating list.");
+       else if (newname) listname = newname;
+    }
+
     /* display list info if requested to */
     if (infoflg) {
        status = mr_query("get_list_info", 1, &listname, show_list_info,NULL);
@@ -211,8 +365,10 @@ char **argv;
     if (syncflg) {
        status = mr_query("get_members_of_list", 1, &listname,
                           get_list_members, (char *)memberlist);
-       if (status)
-         com_err(whoami, status, "getting members of list %s", listname);
+       if (status) {
+           com_err(whoami, status, "getting members of list %s", listname);
+           exit (2);
+       }
        while (sq_get_data(synclist, &memberstruct)) {
            struct save_queue *q;
            int removed = 0;
@@ -238,7 +394,7 @@ char **argv;
     while (sq_get_data(addlist, &memberstruct)) {
        /* canonicalize string if necessary */
        if (memberstruct->type == M_STRING &&
-           (p = index(memberstruct->name, '@'))) {
+           (p = strchr(memberstruct->name, '@'))) {
            char *host = canonicalize_hostname(strsave(++p));
            static char **mailhubs = NULL;
            char *argv[4];
@@ -250,7 +406,8 @@ char **argv;
                argv[2] = "*";
                mailhubs = (char **)malloc(sizeof(char *));
                mailhubs[0] = NULL;
-               status = mr_query("get_alias", 3, argv, collect, &mailhubs);
+               status = mr_query("get_alias", 3, argv, collect,
+                                  (char *)&mailhubs);
                if (status != MR_SUCCESS && status != MR_NO_MATCH) {
                    com_err(whoami, status,
                            " while reading list of MAILHUB servers");
@@ -260,7 +417,7 @@ char **argv;
            for (i = 0; p = mailhubs[i]; i++) {
                if (!strcasecmp(p, host)) {
                    host = strsave(memberstruct->name);
-                   *(index(memberstruct->name, '@')) = 0;
+                   *(strchr(memberstruct->name, '@')) = 0;
                    memberstruct->type = M_ANY;
                    fprintf(stderr, "Warning: \"STRING:%s\" converted to \"%s\" because it is a local name.\n",
                            host, memberstruct->name);
@@ -286,34 +443,62 @@ char **argv;
            else if (status != MR_USER || memberstruct->type != M_ANY) {
                com_err(whoami, status, "while adding member %s to %s",
                        memberstruct->name, listname);
+               success = 0;
                break;
            }
        case M_LIST:
            membervec[1] = "LIST";
            status = mr_query("add_member_to_list", 3, membervec,
                               scream, NULL);
-           if (status == MR_SUCCESS)
-             break;
-           else if (status != MR_LIST || memberstruct->type != M_ANY) {
+           if (status == MR_SUCCESS) {
+               if (!strcmp(membervec[0], getenv("USER"))) {
+                   fprintf(stderr, "\nWARNING: \"LIST:%s\" was just added to list \"%s\".\n",
+                           membervec[2], membervec[0]);
+                   fprintf(stderr, "If you meant to add yourself to the list \"%s\", type:\n", membervec[2]);
+                   fprintf(stderr, "\tblanche %s -d %s\t(to undo this)\n",
+                           membervec[0], membervec[2]);
+                   fprintf(stderr, "\tblanche %s -a %s\t(to add yourself to that list)\n",
+                           membervec[2], membervec[0]);
+               }
+               break;
+           } else if (status != MR_LIST || memberstruct->type != M_ANY) {
                com_err(whoami, status, "while adding member %s to %s",
                        memberstruct->name, listname);
+               success = 0;
                break;
            }
        case M_STRING:
+           if (memberstruct->type == M_ANY &&
+               !strchr(memberstruct->name, '@') &&
+               !strchr(memberstruct->name, '!') &&
+               !strchr(memberstruct->name, '%')) {
+               /* if user is trying to add something which isn't a
+                  remote string, or a list, or a user, and didn't
+                  explicitly specify `STRING:', it's probably a typo */
+               com_err(whoami, MR_NO_MATCH, "while adding member %s to %s",
+                       memberstruct->name, listname);
+               success = 0;
+               break;
+           }
+                           
            membervec[1] = "STRING";
            status = mr_query("add_member_to_list", 3, membervec,
                               scream, NULL);
-           if (status != MR_SUCCESS)
+           if (status != MR_SUCCESS) {
              com_err(whoami, status, "while adding member %s to %s",
                      memberstruct->name, listname);
+             success = 0;
+           }
            break;
        case M_KERBEROS:
            membervec[1] = "KERBEROS";
            status = mr_query("add_member_to_list", 3, membervec,
                               scream, NULL);
-           if (status != MR_SUCCESS)
+           if (status != MR_SUCCESS) {
              com_err(whoami, status, "while adding member %s to %s",
                      memberstruct->name, listname);
+             success = 0;
+           }
        }
     }
 
@@ -337,6 +522,7 @@ char **argv;
                     memberstruct->type != M_ANY) {
                com_err(whoami, status, "while deleting member %s from %s",
                        memberstruct->name, listname);
+               success = 0;
                break;
            }
        case M_LIST:
@@ -347,28 +533,54 @@ char **argv;
              break;
            else if ((status != MR_LIST && status != MR_NO_MATCH) ||
                     memberstruct->type != M_ANY) {
+               if (status == MR_PERM && memberstruct->type == M_ANY &&
+                   !strcmp(membervec[2], getenv("USER")))  {
+                   /* M_ANY means we've fallen through from the user
+                    * case. The user is trying to remove himself from
+                    * a list, but we got MR_USER or MR_NO_MATCH above,
+                    * meaning he's not really on it, and we got MR_PERM
+                    * when trying to remove LIST:$USER because he's not
+                    * on the acl. That error is useless, so return
+                    * MR_NO_MATCH instead. However, this will generate the
+                    * wrong error if the user was trying to remove the list
+                    * with his username from a list he doesn't administrate
+                    * without explicitly specifying "list:".
+                    */
+                 status = MR_NO_MATCH;
+               }
                com_err(whoami, status, "while deleting member %s from %s",
                        memberstruct->name, listname);
+               success = 0;
                break;
            }
        case M_STRING:
            membervec[1] = "STRING";
            status = mr_query("delete_member_from_list", 3, membervec,
                               scream, NULL);
-           if (status == MR_STRING && memberstruct->type == M_ANY)
+           if (status == MR_STRING && memberstruct->type == M_ANY) {
              com_err(whoami, 0, " Unable to find member %s to delete from %s",
                      memberstruct->name, listname);
-           else if (status != MR_SUCCESS)
+             success = 0;
+             if (!strcmp(membervec[0], getenv("USER"))) {
+               fprintf(stderr, "(If you were trying to remove yourself from the list \"%s\",\n", membervec[2]);
+               fprintf(stderr, "the correct command is \"blanche %s -d %s\".)\n",
+                       membervec[2], membervec[0]);
+             }
+           } else if (status != MR_SUCCESS) {
              com_err(whoami, status, "while deleting member %s from %s",
                      memberstruct->name, listname);
+             success = 0;
+           }
            break;
        case M_KERBEROS:
            membervec[1] = "KERBEROS";
            status = mr_query("delete_member_from_list", 3, membervec,
                               scream, NULL);
-           if (status != MR_SUCCESS)
+           if (status != MR_SUCCESS) {
              com_err(whoami, status, "while deleting member %s from %s",
                      memberstruct->name, listname);
+             success = 0;
+           }
        }
     }
 
@@ -389,30 +601,44 @@ char **argv;
 
     /* We're done! */
     mr_disconnect();
-    exit(0);
+    exit(success?0:1);
 }
 
 usage(argv)
 char **argv;
 {
-    fprintf(stderr, "Usage: %s [options] listname [options]\n",argv[0]);
+    fprintf(stderr, "Usage: %s listname [options]\n",argv[0]);
     fprintf(stderr, "Options are\n");
-    fprintf(stderr, "   -v | -verbose\n");
-    fprintf(stderr, "   -m | -members\n");
-    fprintf(stderr, "   -u | -users\n");
-    fprintf(stderr, "   -l | -lists\n");
-    fprintf(stderr, "   -s | -strings\n");
-    fprintf(stderr, "   -k | -kerberos\n");
-    fprintf(stderr, "   -i | -info\n");
-    fprintf(stderr, "   -r | -recursive\n");
-    fprintf(stderr, "   -a | -add member\n");
-    fprintf(stderr, "   -d | -delete member\n");
-    fprintf(stderr, "   -al | -addlist filename\n");
-    fprintf(stderr, "   -dl | -deletelist filename\n");
-    fprintf(stderr, "   -f | -file filename\n");
-    fprintf(stderr, "   -n | -noauth\n");
-    fprintf(stderr, "   -S | -server host[:port]\n");
-    fprintf(stderr, "   -D | -debug\n");
+    fprintf(stderr, "  %-39s%-39s\n", "-v  | -verbose",
+           "-C  | -create");
+    fprintf(stderr, "  %-39s%-39s\n", "-m  | -members",
+           "-R  | -rename newname");
+    fprintf(stderr, "  %-39s%-39s\n", "-u  | -users",
+           "-P  | -public");
+    fprintf(stderr, "  %-39s%-39s\n", "-l  | -lists",
+           "-NP | -private");
+    fprintf(stderr, "  %-39s%-39s\n", "-s  | -strings",
+           "-A  | -active");
+    fprintf(stderr, "  %-39s%-39s\n", "-k  | -kerberos",
+           "-I  | -inactive");
+    fprintf(stderr, "  %-39s%-39s\n", "-i  | -info",
+           "-V  | -visible");
+    fprintf(stderr, "  %-39s%-39s\n", "-r  | -recursive",
+           "-H  | -hidden");
+    fprintf(stderr, "  %-39s%-39s\n", "-a  | -add member",
+           "-M  | -mail");
+    fprintf(stderr, "  %-39s%-39s\n", "-d  | -delete member",
+           "-NM | -notmail");
+    fprintf(stderr, "  %-39s%-39s\n", "-al | -addlist filename",
+           "-G  | -group");
+    fprintf(stderr, "  %-39s%-39s\n", "-dl | -deletelist filename",
+           "-NG | -notgroup");
+    fprintf(stderr, "  %-39s%-39s\n", "-f  | -file filename",
+           "-D  | -desc description");
+    fprintf(stderr, "  %-39s%-39s\n", "-n  | -noauth",
+           "-O  | -owner owner");
+    fprintf(stderr, "  %-39s%-39s\n", "-db | -database host[:port]",
+           "");
     exit(1);
 }
 
@@ -458,7 +684,7 @@ struct member *memberstruct;
        else if (memberstruct->type == M_KERBEROS)
          printf("KERBEROS:%s\n", memberstruct->name);
        else if (memberstruct->type == M_STRING &&
-                !index(memberstruct->name, '@'))
+                !strchr(memberstruct->name, '@'))
          printf("STRING:%s\n", memberstruct->name);
        else
          printf("%s\n", memberstruct->name);
@@ -492,6 +718,20 @@ int hint;
 }
 
 
+/* Copy retrieved information about a list into a new argv */
+
+save_list_info(argc, argv, hint)
+int argc;
+char **argv;
+int hint;
+{
+    char **nargv = (char **)hint;
+    
+    for(argc = 0; argc < 10; argc++)
+       nargv[argc+1] = strdup(argv[argc]);
+    return MR_CONT;
+}
+
 /* Show the retrieve list member count */
 
 show_list_count(argc, argv, hint)
@@ -521,8 +761,6 @@ recursive_display_list_members()
     while (sq_get_data(lists, &m)) {
        sq_destroy(memberlist);
        memberlist = sq_create();
-       if (debugflg)
-         fprintf(stderr, "Fetching members of %s\n", m->name);
        status = mr_query("get_members_of_list", 1, &(m->name),
                           get_list_members, (char *)memberlist);
        if (status)
@@ -538,7 +776,7 @@ recursive_display_list_members()
     data = (struct member *) malloc(count * sizeof(struct member));
     count = 0;
     while (sq_get_data(members, &m))
-      bcopy(m, &data[count++], sizeof(struct member));
+      memcpy(&data[count++], m, sizeof(struct member));
     qsort(data, count, sizeof(struct member), membercmp);
     for (count = 0; count < savecount; count++) {
        show_list_member(&data[count]);
@@ -623,8 +861,10 @@ struct save_queue *queue;
     while (fgets(buf, BUFSIZ, in))
       if (memberstruct = parse_member(buf))
        sq_save_data(queue, memberstruct);
-    if (!feof(in))
+    if (!feof(in)) {
       com_err(whoami, errno, "while reading from %s", filename);
+      exit(2);
+    }
 }
 
 
@@ -671,7 +911,7 @@ register char *s;
     if ((m = (struct member *) malloc(sizeof(struct member))) == NULL)
       return(NULL);
 
-    if (p = index(s, ':')) {
+    if (p = strchr(s, ':')) {
        *p = 0;
        m->name = ++p;
        if (!strcasecmp("user", s))
@@ -683,17 +923,14 @@ register char *s;
        else if (!strcasecmp("kerberos", s))
          m->type = M_KERBEROS;
        else {
-           m->type = M_STRING;
+           m->type = M_ANY;
            *(--p) = ':';
            m->name = s;
        }
        m->name = strsave(m->name);
     } else {
        m->name = strsave(s);
-       if (index(s, '@') || index(s, '!') || index(s, '%') || index(s, ' '))
-         m->type = M_STRING;
-       else
-         m->type = M_ANY;
+       m->type = M_ANY;
     }
     return(m);
 }
This page took 0.108986 seconds and 4 git commands to generate.