]> andersk Git - moira.git/blobdiff - clients/moira/pobox.c
Dribbles of missing EXCHANGE support. This should probably look up the
[moira.git] / clients / moira / pobox.c
index c19e20ddf3dbef8e0749fbc1c878f0b712bf607b..ea55de52e6b807ce5ff0580ddec1e332a07ac08c 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id $
+/* $Id$
  *
  *     This is the file pobox.c for the Moira Client, which allows users
  *      to quickly and easily maintain most parts of the Moira database.
@@ -15,6 +15,7 @@
 #include <mit-copyright.h>
 #include <moira.h>
 #include <moira_site.h>
+#include <mrclient.h>
 #include "defs.h"
 #include "f_defs.h"
 #include "globals.h"
@@ -25,9 +26,6 @@
 
 RCSID("$Header$");
 
-#define FOREIGN_BOX ("SMTP")
-#define LOCAL_BOX ("POP")
-
 /*     Function Name: PrintPOBox
  *     Description: Yet another specialized print function.
  *     Arguments: info - all info about this PO_box.
@@ -38,11 +36,21 @@ static void PrintPOBox(char **info)
 {
   char buf[BUFSIZ];
 
-  sprintf(buf, "Address: %-10s Box: %-35s Type: %s", info[PO_NAME],
+  sprintf(buf, "User: %-10s Box: %-35s Type: %s", info[PO_NAME],
          info[PO_BOX], info[PO_TYPE]);
   Put_message(buf);
-  sprintf(buf, MOD_FORMAT, info[4], info[3], info[5]);
-  Put_message(buf);
+  if (info[6])
+    {
+      sprintf(buf, "Address: %s", info[PO_ADDR]);
+      Put_message(buf);
+      sprintf(buf, MOD_FORMAT, info[5], info[4], info[6]);
+      Put_message(buf);
+    }
+  else
+    {
+      sprintf(buf, MOD_FORMAT, info[4], info[3], info[5]);
+      Put_message(buf);
+    }
 }
 
 /*     Function Name: RealPrintPOMachines
@@ -66,7 +74,7 @@ static int PrintPOMachines(void)
 {
   int status;
   static char *args[] = {"pop", NULL};
-  struct qelem *top = NULL;
+  struct mqelem *top = NULL;
 
   if ((status = do_mr_query("get_server_locations", CountArgs(args), args,
                            StoreInfo, &top)))
@@ -90,7 +98,7 @@ static int PrintPOMachines(void)
 int GetUserPOBox(int argc, char **argv)
 {
   int status;
-  struct qelem *top = NULL;
+  struct mqelem *top = NULL;
   char buf[BUFSIZ];
 
   if (!ValidName(argv[1]))
@@ -139,6 +147,246 @@ static char *GetNewLocalPOBox(char *local_user)
   return (char *) SUB_ERROR;
 }
 
+static int InsertSortedImapPart(int argc, char **argv, void *arg)
+{
+  struct mqelem *new = NULL;
+  struct mqelem *elem, *prev, **parts = arg;
+  int avail = atoi(argv[NFS_SIZE]) - atoi(argv[NFS_ALLOC]);
+
+  /* Dup the argv into a new mqelem. */
+  StoreInfo(argc, argv, &new);
+
+  if (!*parts)
+    {
+      *parts = new;
+      return MR_CONT;
+    }
+
+  /* Find the right place in parts for it. */
+  elem = *parts;
+  prev = NULL;
+  while (elem)
+    {
+      char **xargv = elem->q_data;
+      if (atoi(xargv[NFS_SIZE]) - atoi(xargv[NFS_ALLOC]) < avail)
+       break;
+      prev = elem;
+      elem = elem->q_forw;
+    }
+
+  if (prev)
+    AddQueue(new, prev);
+  else
+    {
+      new->q_forw = *parts;
+      (*parts)->q_back = new;
+      *parts = new;
+    }
+
+  return MR_CONT;
+}
+
+static int AddImapPartitions(char *server, struct mqelem **parts)
+{
+  char *argv[2];
+  int status;
+
+  argv[0] = server;
+  argv[1] = "*";
+
+  status = do_mr_query("get_nfsphys", 2, argv, InsertSortedImapPart, parts);
+  if (status)
+    {
+      com_err(program_name, status, " in AddImapPartitions");
+      return SUB_ERROR;
+    }
+  return SUB_NORMAL;
+}
+
+char *CreateImapBox(char *user)
+{
+  int status;
+  struct mqelem *elem = NULL, *servers = NULL, *partitions = NULL;
+  char *server = NULL, *partition = NULL;
+  char *argv[11], *fsname, temp_buf[BUFSIZ];
+  static char *default_imap_quota = NULL;
+
+  if (!default_imap_quota)
+    {
+      char **vargv;
+      argv[0] = "def_imap_quota";
+      status = do_mr_query("get_value", 1, argv, StoreInfo, &elem);
+      if (status)
+       {
+         com_err(program_name, status, " getting default IMAP quota");
+         return (char *)SUB_ERROR;
+       }
+      vargv = elem->q_data;
+      default_imap_quota = strdup(vargv[0]);
+      FreeQueue(elem);
+    }
+
+  argv[0] = "POSTOFFICE";
+  status = do_mr_query("get_server_locations", 1, argv, StoreInfo, &servers);
+  if (status)
+    {
+      com_err(program_name, status, " in GetImapBox.");
+      return (char *)SUB_ERROR;
+    }
+  servers = QueueTop(servers);
+
+  /* Get an IMAP server. */
+  while (!server)
+    {
+      server = strdup("[ANY]");
+      if (GetValueFromUser("IMAP Server? ['?' for a list]", &server) !=
+         SUB_NORMAL)
+       {
+         free(server);
+         FreeQueue(servers);
+         return (char *)SUB_ERROR;
+       }
+
+      if (!strcmp(server, "?"))
+       {
+         elem = servers;
+         while (elem)
+           {
+             char **sargv = elem->q_data;
+             sprintf(temp_buf, "  %s\n", sargv[1]);
+             Put_message(temp_buf);
+             elem = elem->q_forw;
+           }
+         free(server);
+         server = NULL;
+       }
+    }
+  server = canonicalize_hostname(server);
+
+  /* Get the partitions on that server. */
+  if (!strcasecmp(server, "[ANY]"))
+    {
+      char **sargv;
+
+      elem = servers;
+      while (elem && !status)
+       {
+         sargv = elem->q_data;
+         status = AddImapPartitions(sargv[1], &partitions);
+         elem = elem->q_forw;
+       }
+
+      if (partitions)
+       {
+         sargv = partitions->q_data;
+         server = strdup(sargv[NFS_NAME]);
+         partition = strdup(sargv[NFS_DIR]);
+       }
+    }
+  else
+    status = AddImapPartitions(server, &partitions);
+  partitions = QueueTop(partitions);
+
+  FreeQueue(servers);
+  if (status || !partitions)
+    {
+      if (!partitions)
+       com_err(program_name, 0, "No registered nfsphys on %s.", server);
+      else
+       FreeQueue(partitions);
+      free(server);
+      return (char *)SUB_ERROR;
+    }
+
+  /* Pick a partition */
+  while (!partition)
+    {
+      char **pargv = partitions->q_data;
+      partition = strdup(pargv[NFS_DIR]);
+      if (GetValueFromUser("Partition? ['?' for a list]", &partition) !=
+         SUB_NORMAL)
+       {
+         free(server);
+         free(partition);
+         FreeQueue(partitions);
+         return (char *)SUB_ERROR;
+       }
+
+      elem = partitions;
+      if (!strcmp(partition, "?"))
+       {
+         while (elem)
+           {
+             char **pargv = elem->q_data;
+             sprintf(temp_buf, "  %s (%s available, %d free)",
+                     pargv[NFS_DIR], pargv[NFS_SIZE],
+                     atoi(pargv[NFS_SIZE]) - atoi(pargv[NFS_ALLOC]));
+             Put_message(temp_buf);
+             elem = elem->q_forw;
+           }
+         free(partition);
+         partition = NULL;
+       }
+      else
+       {
+         while (elem)
+           {
+             char **pargv = elem->q_data;
+             if (!strcmp(partition, pargv[NFS_DIR]))
+               break;
+             elem = elem->q_forw;
+           }
+         if (!elem)
+           {
+             com_err(program_name, 0, "No such partition %s", partition);
+             free(partition);
+             partition = NULL;
+           }
+       }
+    }
+  FreeQueue(partitions);
+
+  fsname = malloc(strlen(user) + 4);
+  sprintf(fsname, "%s.po", user);
+  argv[FS_NAME] = fsname;
+  argv[FS_TYPE] = "IMAP";
+  argv[FS_MACHINE] = server;
+  argv[FS_PACK] = partition;
+  argv[FS_M_POINT] = "";
+  argv[FS_ACCESS] = "w";
+  argv[FS_COMMENTS] = "IMAP box";
+  argv[FS_OWNER] = user;
+  argv[FS_OWNERS] = "wheel";
+  argv[FS_CREATE] = "1";
+  argv[FS_L_TYPE] = "USER";
+
+  status = do_mr_query("add_filesys", 11, argv, NULL, NULL);
+  free(server);
+  free(partition);
+
+  if (status)
+    {
+      com_err(program_name, status, " creating IMAP filesys in CreateImapBox");
+      free(fsname);
+      return (char *)SUB_ERROR;
+    }
+
+  argv[Q_FILESYS] = fsname;
+  argv[Q_TYPE] = "USER";
+  argv[Q_NAME] = user;
+  argv[Q_QUOTA] = default_imap_quota;
+
+  status = do_mr_query("add_quota", 4, argv, NULL, NULL);
+  if (status)
+    {
+      com_err(program_name, status, " setting quota in CreateImapBox");
+      free(fsname);
+      return (char *)SUB_ERROR;
+    }
+  else
+    return fsname;
+}
+
 /*     Function Name: SetUserPOBox
  *     Description: Addes or Chnages the P.O. Box for a user.
  *     Arguments: argc, argv - the login name of the user in argv[1].
@@ -148,11 +396,10 @@ static char *GetNewLocalPOBox(char *local_user)
 int SetUserPOBox(int argc, char **argv)
 {
   int status;
-  char *type, temp_buf[BUFSIZ], *local_user, *args[10], box[BUFSIZ];
-  char *temp_box;
-  struct qelem *top = NULL;
-  local_user = argv[1];
+  char *type, temp_buf[BUFSIZ], *local_user, *args[10], *box;
+  struct mqelem *top = NULL;
 
+  local_user = argv[1];
   if (!ValidName(local_user))
     return DM_NORMAL;
 
@@ -174,11 +421,12 @@ int SetUserPOBox(int argc, char **argv)
       return DM_NORMAL;
     }
 
+  Put_message("");
+
   sprintf(temp_buf, "Assign %s a local PO Box (y/n)", local_user);
   switch (YesNoQuestion(temp_buf, TRUE))
     {
     case TRUE:
-      type = LOCAL_BOX;
       switch (YesNoQuestion("Use Previous Local Box (y/n)", TRUE))
        {
        case TRUE:
@@ -191,42 +439,76 @@ int SetUserPOBox(int argc, char **argv)
              sprintf(temp_buf, "%s did not have a previous local PO Box.",
                      local_user);
              Put_message(temp_buf);
-             if ((temp_box = GetNewLocalPOBox(local_user)) !=
-                 (char *) SUB_ERROR)
-               {
-                 strcpy(box, temp_box);
-                 free(temp_box);
-               }
-             else
-               return DM_NORMAL;
-             break;
            default:
              com_err(program_name, status, " in set_pobox_pop.");
              return DM_NORMAL;
            }
-         break;
+         /* Fall through from MR_MACHINE case. */
        case FALSE:
-         if ((temp_box = GetNewLocalPOBox(local_user)) !=
-             (char *) SUB_ERROR)
+         type = strdup("IMAP");
+         if (GetValueFromUser("Kind of Local PO Box?", &type) == SUB_ERROR)
+           {
+             free(type);
+             return DM_NORMAL;
+           }
+         if (!strcasecmp(type, "POP"))
+           {
+             free(type);
+             type = "POP";
+             if ((box = GetNewLocalPOBox(local_user)) == (char *) SUB_ERROR)
+               return DM_NORMAL;
+           }
+         else if (!strcasecmp(type, "IMAP"))
            {
-             strcpy(box, temp_box);
-             free(temp_box);
+             free(type);
+             type = "IMAP";
+             switch (YesNoQuestion("Create IMAP filesystem (y/n)", TRUE))
+               {
+               case TRUE:
+                 if ((box = CreateImapBox(local_user)) == (char *) SUB_ERROR)
+                   return DM_NORMAL;
+                 break;
+               case FALSE:
+                 box = malloc(strlen(local_user) + 4);
+                 sprintf(box, "%s.po", local_user);
+                 break;
+               default:
+                 return DM_NORMAL;
+               }
+           }
+         else if (!strcasecmp(type, "EXCHANGE"))
+           {
+             free(type);
+             type = "EXCHANGE";
+             box = "EXCHANGE.MIT.EDU";
            }
          else
-           return DM_NORMAL;
+           {
+             sprintf(temp_buf, "Unknown local PO Box type %s", type);
+             Put_message(temp_buf);
+             free(type);
+             return DM_NORMAL;
+           }
          break;
        default:
          return DM_NORMAL;
        }
       break;
     case FALSE:
-      type = FOREIGN_BOX;
+      type = "SMTP";
       sprintf(temp_buf, "Set up a foreign PO Box for %s (y/n)", local_user);
       switch (YesNoQuestion(temp_buf, TRUE))
        {
        case TRUE:
-         if (!Prompt_input("Foreign PO Box for this user? ", box, BUFSIZ))
+         if (!Prompt_input("Foreign PO Box for this user? ", temp_buf, BUFSIZ))
            return DM_NORMAL;
+         if (mrcl_validate_pobox_smtp(local_user, temp_buf, &box) !=
+             MRCL_SUCCESS)
+           {
+             if (mrcl_get_message())
+               Put_message(mrcl_get_message());
+             return DM_NORMAL;
+           }
          break;
        case FALSE:
        default:
@@ -241,12 +523,53 @@ int SetUserPOBox(int argc, char **argv)
   args[PO_NAME] = local_user;
   args[PO_TYPE] = type;
   args[PO_BOX] = box;
-  args[PO_END] = NULL;
+  args[3] = NULL;
   if ((status = do_mr_query("set_pobox", CountArgs(args), args,
                            NULL, NULL)))
     com_err(program_name, status, " in ChangeUserPOBox");
   else
     Put_message("PO Box assigned.");
+  free(box);
+
+  return DM_NORMAL;
+}
+
+/*     Function Name: SplitUserPOBox
+ *     Description: Splits the user's PO Box between local and SMTP
+ *     Arguments: argc, argv - name of user in argv[1].
+ *     Returns: DM_NORMAL.
+ */
+
+int SplitUserPOBox(int argc, char **argv)
+{
+  char temp_buf[BUFSIZ], *args[3], *box;
+  int status;
+
+  if (!ValidName(argv[1]))
+    return DM_NORMAL;
+
+  if (!Prompt_input("Foreign PO Box for this user? ", temp_buf, BUFSIZ))
+    return DM_NORMAL;
+  if (mrcl_validate_pobox_smtp(argv[1], temp_buf, &box) !=
+      MRCL_SUCCESS)
+    {
+      if (mrcl_get_message())
+       Put_message(mrcl_get_message());
+      return DM_NORMAL;
+    }
+
+  args[0] = argv[1];
+  args[1] = "SPLIT";
+  args[2] = box;
+
+  status = do_mr_query("set_pobox", 3, args, NULL, NULL);
+  if (status == MR_MACHINE)
+    Put_message("User has no local PO Box--PO Box unchanged.");
+  else if (status)
+    com_err(program_name, status, " in SplitUserPOBox");
+  else
+    Put_message("PO Box split.");
+  free(box);
 
   return DM_NORMAL;
 }
This page took 0.06773 seconds and 4 git commands to generate.