-#if (!defined(lint) && !defined(SABER))
- static char rcsid_module_c[] = "$Header$";
-#endif lint
-
-/* This is the file pobox.c for the MOIRA Client, which allows a nieve
- * user to quickly and easily maintain most parts of the MOIRA database.
+/* $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.
* It Contains: Functions for handling the poboxes.
- *
+ *
* Created: 7/10/88
* By: Chris D. Peterson
*
- * $Source$
- * $Author$
- * $Header$
- *
- * Copyright 1988 by the Massachusetts Institute of Technology.
- *
- * For further information on copyright and distribution
- * see the file mit-copyright.h
+ * Copyright (C) 1988-1998 by the Massachusetts Institute of Technology.
+ * For copying and distribution information, please see the file
+ * <mit-copyright.h>.
*/
-#include <stdio.h>
-#include <strings.h>
-#include <ctype.h>
+#include <mit-copyright.h>
#include <moira.h>
#include <moira_site.h>
-#include <menu.h>
-
-#include "mit-copyright.h"
+#include <mrclient.h>
#include "defs.h"
#include "f_defs.h"
#include "globals.h"
-#define FOREIGN_BOX ("SMTP")
-#define LOCAL_BOX ("POP")
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+RCSID("$Header$");
/* Function Name: PrintPOBox
* Description: Yet another specialized print function.
* Returns: MR_CONT
*/
-static void
-PrintPOBox(info)
-char ** info;
+static void PrintPOBox(char **info)
{
- char buf[BUFSIZ];
-
- sprintf(buf, "Address: %-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);
+ char buf[BUFSIZ];
+
+ sprintf(buf, "User: %-10s Box: %-35s Type: %s", info[PO_NAME],
+ info[PO_BOX], info[PO_TYPE]);
+ 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
* Returns: none.
*/
-static void
-RealPrintPOMachines(info)
-char ** info;
+static void RealPrintPOMachines(char **info)
{
- Print(1, info + 1, (char *) NULL);
+ Print(1, info + 1, NULL);
}
/* Function Name: PrintPOMachines
* Returns: SUB_ERROR if the machines could not be printed.
*/
-static int
-PrintPOMachines()
+static int PrintPOMachines(void)
{
- register int status;
- static char * args[] = {"pop", NULL};
- struct qelem * top = NULL;
-
- if ( (status = do_mr_query("get_server_locations", CountArgs(args), args,
- StoreInfo, (char *)&top)) != MR_SUCCESS) {
- com_err(program_name, status, " in get_server_locations.");
- return(SUB_ERROR);
+ int status;
+ static char *args[] = {"pop", NULL};
+ struct mqelem *top = NULL;
+
+ if ((status = do_mr_query("get_server_locations", CountArgs(args), args,
+ StoreInfo, &top)))
+ {
+ com_err(program_name, status, " in get_server_locations.");
+ return SUB_ERROR;
}
-
- top = QueueTop(top);
- Loop(top, RealPrintPOMachines);
- FreeQueue(top);
- return(SUB_NORMAL);
+
+ top = QueueTop(top);
+ Loop(top, RealPrintPOMachines);
+ FreeQueue(top);
+ return SUB_NORMAL;
}
/* Function Name: GetUserPOBox
* Returns: DM_NORMAL.
*/
-/* ARGSUSED */
-int
-GetUserPOBox(argc, argv)
-int argc;
-char ** argv;
+int GetUserPOBox(int argc, char **argv)
{
- register int status;
- struct qelem * top = NULL;
- char buf[BUFSIZ];
-
- if (!ValidName(argv[1]))
- return(DM_NORMAL);
-
- switch (status = do_mr_query("get_pobox", 1, argv + 1, StoreInfo,
- (char *)&top)) {
+ int status;
+ struct mqelem *top = NULL;
+ char buf[BUFSIZ];
+
+ if (!ValidName(argv[1]))
+ return DM_NORMAL;
+
+ switch ((status = do_mr_query("get_pobox", 1, argv + 1, StoreInfo, &top)))
+ {
case MR_NO_MATCH:
- Put_message("This user has no P.O. Box.");
- break;
+ Put_message("This user has no P.O. Box.");
+ break;
case MR_SUCCESS:
- sprintf(buf,"Current pobox for user %s: \n", argv[1]);
- Put_message("");
- top = QueueTop(top);
- Loop(top, PrintPOBox); /* should only return 1 box. */
- FreeQueue(top);
- break;
+ sprintf(buf, "Current pobox for user %s: \n", argv[1]);
+ Put_message("");
+ top = QueueTop(top);
+ Loop(top, PrintPOBox); /* should only return 1 box. */
+ FreeQueue(top);
+ break;
default:
- com_err(program_name, status, " in get_pobox.");
+ com_err(program_name, status, " in get_pobox.");
}
- return(DM_NORMAL);
+ return DM_NORMAL;
}
/* Function Name: GetNewLocalPOBox
* Returns: machine - name of the machine for then new pop box, or NULL.
*/
-static char *
-GetNewLocalPOBox(local_user)
-char * local_user;
+static char *GetNewLocalPOBox(char *local_user)
+{
+ char temp_buf[BUFSIZ];
+
+ sprintf(temp_buf, "%s %s", "Pick one of the following",
+ "machines for this user's Post Office.");
+ Put_message(temp_buf);
+ Put_message("");
+ if (PrintPOMachines() == SUB_NORMAL)
+ {
+ Put_message("");
+ if (!Prompt_input("Which Machine? ", temp_buf, BUFSIZ))
+ return (char *) SUB_ERROR;
+ return canonicalize_hostname(strdup(temp_buf));
+ }
+ Put_message("Could not get machines to choose from, quitting.");
+ return (char *) SUB_ERROR;
+}
+
+static int InsertSortedImapPart(int argc, char **argv, void *arg)
{
- char temp_buf[BUFSIZ];
-
- sprintf(temp_buf,"%s %s", "Pick one of the following",
- "machines for this user's Post Office.");
- Put_message(temp_buf);
- Put_message("");
- if (PrintPOMachines() == SUB_NORMAL) {
- Put_message("");
- if (!Prompt_input("Which Machine? ", temp_buf, BUFSIZ))
- return((char *) SUB_ERROR);
- return(canonicalize_hostname(strsave(temp_buf)));
+ 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;
}
- Put_message("Could not get machines to choose from, quitting.");
- 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
* Returns: DM_NORMAL.
*/
-int
-SetUserPOBox(argc, argv)
-int argc;
-char **argv;
+int SetUserPOBox(int argc, char **argv)
{
- register int status;
- char *type, temp_buf[BUFSIZ], *local_user, *args[10], box[BUFSIZ];
- char *temp_box;
- local_user = argv[1];
-
- if (!ValidName(local_user))
- return(DM_NORMAL);
-
- (void) GetUserPOBox(argc, argv); /* print current info. */
-
- sprintf(temp_buf, "Assign %s a local PO Box (y/n)", local_user);
- switch (YesNoQuestion(temp_buf, TRUE)) {
+ int status;
+ 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;
+
+ /* Print the current PO Box info */
+ switch ((status = do_mr_query("get_pobox", 1, argv + 1, StoreInfo, &top)))
+ {
+ case MR_SUCCESS:
+ sprintf(temp_buf, "Current pobox for user %s: \n", local_user);
+ Put_message("");
+ top = QueueTop(top);
+ Loop(top, PrintPOBox); /* should only return 1 box. */
+ FreeQueue(top);
+ break;
+ case MR_NO_MATCH:
+ Put_message("This user has no P.O. Box.");
+ break;
+ default:
+ com_err(program_name, status, " in get_pobox.");
+ 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)) {
+ switch (YesNoQuestion("Use Previous Local Box (y/n)", TRUE))
+ {
case TRUE:
- switch (status = do_mr_query("set_pobox_pop", 1,
- &local_user, Scream, NULL)) {
+ switch ((status = do_mr_query("set_pobox_pop", 1,
+ &local_user, NULL, NULL)))
+ {
case MR_SUCCESS:
- return(DM_NORMAL);
+ return DM_NORMAL;
case MR_MACHINE:
- 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;
+ sprintf(temp_buf, "%s did not have a previous local PO Box.",
+ local_user);
+ Put_message(temp_buf);
default:
- com_err(program_name, status, "in set_pobox_pop.");
- return(DM_NORMAL);
+ 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) {
- strcpy(box, temp_box);
- free(temp_box);
+ 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"))
+ {
+ 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
+ {
+ sprintf(temp_buf, "Unknown local PO Box type %s", type);
+ Put_message(temp_buf);
+ free(type);
+ return DM_NORMAL;
}
- else
- return(DM_NORMAL);
- break;
+ break;
default:
- return(DM_NORMAL);
+ return DM_NORMAL;
}
- break;
+ break;
case FALSE:
- type = FOREIGN_BOX;
- sprintf(temp_buf, "Set up a foreign PO Box for %s (y/n)", local_user);
- switch( YesNoQuestion(temp_buf, TRUE)) {
+ 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))
- return(DM_NORMAL);
- break;
+ 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:
- return(DM_NORMAL); /* ^C hit. */
+ return DM_NORMAL; /* ^C hit. */
}
- break;
+ break;
default: /* ^C hit. */
- Put_message("Aborted.");
- return(DM_NORMAL);
+ Put_message("Aborted.");
+ return DM_NORMAL;
}
- args[PO_NAME] = local_user;
- args[PO_TYPE] = type;
- args[PO_BOX] = box;
- args[PO_END] = NULL;
- if ( (status = do_mr_query("set_pobox", CountArgs(args), args,
- Scream, NULL)) != MR_SUCCESS )
- com_err(program_name, status, " in ChangeUserPOBox");
- else
- Put_message("PO Box assigned.");
-
- return (DM_NORMAL);
+ args[PO_NAME] = local_user;
+ args[PO_TYPE] = type;
+ args[PO_BOX] = box;
+ 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;
}
/* Function Name: RemoveUserPOBox
* Returns: DM_NORMAL.
*/
-/*ARGSUSED */
-int
-RemoveUserPOBox(argc, argv)
-int argc;
-char ** argv;
+int RemoveUserPOBox(int argc, char **argv)
{
- register int status;
- char temp_buf[BUFSIZ];
-
- if (!ValidName(argv[1]))
- return(DM_NORMAL);
-
- sprintf(temp_buf,
- "Are you sure that you want to remove %s's PO Box (y/n)", argv[1]);
-
- if (Confirm(temp_buf)) {
- if ( (status = do_mr_query("delete_pobox", 1, argv + 1,
- Scream, NULL)) != MR_SUCCESS)
- com_err(program_name, status, "in delete_pobox.");
- else
- Put_message("PO Box removed.");
+ int status;
+ char temp_buf[BUFSIZ];
+
+ if (!ValidName(argv[1]))
+ return DM_NORMAL;
+
+ sprintf(temp_buf, "Are you sure that you want to remove %s's PO Box (y/n)",
+ argv[1]);
+
+ if (Confirm(temp_buf))
+ {
+ if ((status = do_mr_query("delete_pobox", 1, argv + 1,
+ NULL, NULL)))
+ com_err(program_name, status, " in delete_pobox.");
+ else
+ Put_message("PO Box removed.");
}
- return(DM_NORMAL);
+ return DM_NORMAL;
}