3 * This is the file pobox.c for the Moira Client, which allows users
4 * to quickly and easily maintain most parts of the Moira database.
5 * It Contains: Functions for handling the poboxes.
8 * By: Chris D. Peterson
10 * Copyright (C) 1988-1998 by the Massachusetts Institute of Technology.
11 * For copying and distribution information, please see the file
15 #include <mit-copyright.h>
17 #include <moira_site.h>
29 /* Function Name: PrintPOBox
30 * Description: Yet another specialized print function.
31 * Arguments: info - all info about this PO_box.
35 static void PrintPOBox(char **info)
39 sprintf(buf, "User: %-10s Box: %-35s Type: %s", info[PO_NAME],
40 info[PO_BOX], info[PO_TYPE]);
44 sprintf(buf, "Address: %s", info[PO_ADDR]);
46 sprintf(buf, MOD_FORMAT, info[5], info[4], info[6]);
51 sprintf(buf, MOD_FORMAT, info[4], info[3], info[5]);
56 /* Function Name: RealPrintPOMachines
57 * Description: Actually does the printing for PrintPOMachines.
58 * Arguments: info, - name of machines in info[1].
62 static void RealPrintPOMachines(char **info)
64 Print(1, info + 1, NULL);
67 /* Function Name: PrintPOMachines
68 * Description: Prints all current post offices.
70 * Returns: SUB_ERROR if the machines could not be printed.
73 static int PrintPOMachines(void)
76 static char *args[] = {"pop", NULL};
77 struct mqelem *top = NULL;
79 if ((status = do_mr_query("get_server_locations", CountArgs(args), args,
82 com_err(program_name, status, " in get_server_locations.");
87 Loop(top, RealPrintPOMachines);
92 /* Function Name: GetUserPOBox
93 * Description: prints the users POBox information.
94 * Arguments: argc, argv - name of the user in argv[1].
98 int GetUserPOBox(int argc, char **argv)
101 struct mqelem *top = NULL;
104 if (!ValidName(argv[1]))
107 switch ((status = do_mr_query("get_pobox", 1, argv + 1, StoreInfo, &top)))
110 Put_message("This user has no P.O. Box.");
113 sprintf(buf, "Current pobox for user %s: \n", argv[1]);
116 Loop(top, PrintPOBox); /* should only return 1 box. */
120 com_err(program_name, status, " in get_pobox.");
125 /* Function Name: GetNewLocalPOBox
126 * Description: get the machine for a new local pop Box for the user.
127 * Arguments: local_user - name of the local user.
128 * Returns: machine - name of the machine for then new pop box, or NULL.
131 static char *GetNewLocalPOBox(char *local_user)
133 char temp_buf[BUFSIZ];
135 sprintf(temp_buf, "%s %s", "Pick one of the following",
136 "machines for this user's Post Office.");
137 Put_message(temp_buf);
139 if (PrintPOMachines() == SUB_NORMAL)
142 if (!Prompt_input("Which Machine? ", temp_buf, BUFSIZ))
143 return (char *) SUB_ERROR;
144 return canonicalize_hostname(strdup(temp_buf));
146 Put_message("Could not get machines to choose from, quitting.");
147 return (char *) SUB_ERROR;
150 static int InsertSortedImapPart(int argc, char **argv, void *arg)
152 struct mqelem *new, *elem, *prev, **parts = arg;
153 int avail = atoi(argv[NFS_SIZE]) - atoi(argv[NFS_ALLOC]);
155 /* Dup the argv into a new mqelem. */
156 StoreInfo(argc, argv, &new);
164 /* Find the right place in parts for it. */
169 char **xargv = elem->q_data;
170 if (atoi(xargv[NFS_SIZE]) - atoi(xargv[NFS_ALLOC]) < avail)
180 new->q_forw = *parts;
181 (*parts)->q_back = new;
188 static int AddImapPartitions(char *server, struct mqelem **parts)
196 status = do_mr_query("get_nfsphys", 2, argv, InsertSortedImapPart, parts);
199 com_err(program_name, status, " in AddImapPartitions");
205 char *CreateImapBox(char *user)
208 struct mqelem *elem = NULL, *servers = NULL, *partitions = NULL;
209 char *server = NULL, *partition = NULL;
210 char *argv[11], *fsname, temp_buf[BUFSIZ];
211 static char *default_imap_quota = NULL;
213 if (!default_imap_quota)
216 argv[0] = "def_imap_quota";
217 status = do_mr_query("get_value", 1, argv, StoreInfo, &elem);
220 com_err(program_name, status, " getting default IMAP quota");
221 return (char *)SUB_ERROR;
223 vargv = elem->q_data;
224 default_imap_quota = strdup(vargv[0]);
228 argv[0] = "POSTOFFICE";
229 status = do_mr_query("get_server_locations", 1, argv, StoreInfo, &servers);
232 com_err(program_name, status, " in GetImapBox.");
233 return (char *)SUB_ERROR;
235 servers = QueueTop(servers);
237 /* Get an IMAP server. */
240 server = strdup("[ANY]");
241 if (GetValueFromUser("IMAP Server? ['?' for a list]", &server) !=
246 return (char *)SUB_ERROR;
249 if (!strcmp(server, "?"))
254 char **sargv = elem->q_data;
255 sprintf(temp_buf, " %s\n", sargv[1]);
256 Put_message(temp_buf);
263 server = canonicalize_hostname(server);
265 /* Get the partitions on that server. */
266 if (!strcasecmp(server, "[ANY]"))
271 while (elem && !status)
273 sargv = elem->q_data;
274 status = AddImapPartitions(sargv[1], &partitions);
280 sargv = partitions->q_data;
281 server = strdup(sargv[NFS_NAME]);
282 partition = strdup(sargv[NFS_DIR]);
286 status = AddImapPartitions(server, &partitions);
287 partitions = QueueTop(partitions);
290 if (status || !partitions)
293 com_err(program_name, 0, "No registered nfsphys on %s.", server);
295 FreeQueue(partitions);
297 return (char *)SUB_ERROR;
300 /* Pick a partition */
303 char **pargv = partitions->q_data;
304 partition = strdup(pargv[NFS_DIR]);
305 if (GetValueFromUser("Partition? ['?' for a list]", &partition) !=
310 FreeQueue(partitions);
311 return (char *)SUB_ERROR;
315 if (!strcmp(partition, "?"))
319 char **pargv = elem->q_data;
320 sprintf(temp_buf, " %s (%s available, %d free)",
321 pargv[NFS_DIR], pargv[NFS_SIZE],
322 atoi(pargv[NFS_SIZE]) - atoi(pargv[NFS_ALLOC]));
323 Put_message(temp_buf);
333 char **pargv = elem->q_data;
334 if (!strcmp(partition, pargv[NFS_DIR]))
339 com_err(program_name, 0, "No such partition %s", partition);
345 FreeQueue(partitions);
347 fsname = malloc(strlen(user) + 4);
348 sprintf(fsname, "%s.po", user);
349 argv[FS_NAME] = fsname;
350 argv[FS_TYPE] = "IMAP";
351 argv[FS_MACHINE] = server;
352 argv[FS_PACK] = partition;
353 argv[FS_M_POINT] = "";
354 argv[FS_ACCESS] = "w";
355 argv[FS_COMMENTS] = "IMAP box";
356 argv[FS_OWNER] = user;
357 argv[FS_OWNERS] = "wheel";
358 argv[FS_CREATE] = "1";
359 argv[FS_L_TYPE] = "USER";
361 status = do_mr_query("add_filesys", 11, argv, NULL, NULL);
367 com_err(program_name, status, " creating IMAP filesys in CreateImapBox");
369 return (char *)SUB_ERROR;
372 argv[Q_FILESYS] = fsname;
373 argv[Q_TYPE] = "USER";
375 argv[Q_QUOTA] = default_imap_quota;
377 status = do_mr_query("add_quota", 4, argv, NULL, NULL);
380 com_err(program_name, status, " setting quota in CreateImapBox");
382 return (char *)SUB_ERROR;
388 /* Function Name: SetUserPOBox
389 * Description: Addes or Chnages the P.O. Box for a user.
390 * Arguments: argc, argv - the login name of the user in argv[1].
391 * Returns: DM_NORMAL.
394 int SetUserPOBox(int argc, char **argv)
397 char *type, temp_buf[BUFSIZ], *local_user, *args[10], *box;
398 struct mqelem *top = NULL;
400 local_user = argv[1];
401 if (!ValidName(local_user))
404 /* Print the current PO Box info */
405 switch ((status = do_mr_query("get_pobox", 1, argv + 1, StoreInfo, &top)))
408 sprintf(temp_buf, "Current pobox for user %s: \n", local_user);
411 Loop(top, PrintPOBox); /* should only return 1 box. */
415 Put_message("This user has no P.O. Box.");
418 com_err(program_name, status, " in get_pobox.");
424 sprintf(temp_buf, "Assign %s a local PO Box (y/n)", local_user);
425 switch (YesNoQuestion(temp_buf, TRUE))
428 switch (YesNoQuestion("Use Previous Local Box (y/n)", TRUE))
431 switch ((status = do_mr_query("set_pobox_pop", 1,
432 &local_user, NULL, NULL)))
437 sprintf(temp_buf, "%s did not have a previous local PO Box.",
439 Put_message(temp_buf);
441 com_err(program_name, status, " in set_pobox_pop.");
444 /* Fall through from MR_MACHINE case. */
446 type = strdup("IMAP");
447 if (GetValueFromUser("Kind of Local PO Box?", &type) == SUB_ERROR)
452 if (!strcasecmp(type, "POP"))
456 if ((box = GetNewLocalPOBox(local_user)) == (char *) SUB_ERROR)
459 else if (!strcasecmp(type, "IMAP"))
463 if ((box = CreateImapBox(local_user)) == (char *) SUB_ERROR)
468 sprintf(temp_buf, "Unknown local PO Box type %s", type);
469 Put_message(temp_buf);
480 sprintf(temp_buf, "Set up a foreign PO Box for %s (y/n)", local_user);
481 switch (YesNoQuestion(temp_buf, TRUE))
484 if (!Prompt_input("Foreign PO Box for this user? ", temp_buf, BUFSIZ))
486 if (mrcl_validate_pobox_smtp(local_user, temp_buf, &box) !=
492 return DM_NORMAL; /* ^C hit. */
495 default: /* ^C hit. */
496 Put_message("Aborted.");
500 args[PO_NAME] = local_user;
501 args[PO_TYPE] = type;
504 if ((status = do_mr_query("set_pobox", CountArgs(args), args,
506 com_err(program_name, status, " in ChangeUserPOBox");
508 Put_message("PO Box assigned.");
514 /* Function Name: SplitUserPOBox
515 * Description: Splits the user's PO Box between local and SMTP
516 * Arguments: argc, argv - name of user in argv[1].
517 * Returns: DM_NORMAL.
520 int SplitUserPOBox(int argc, char **argv)
522 char temp_buf[BUFSIZ], *args[3], *box;
525 if (!ValidName(argv[1]))
528 if (!Prompt_input("Foreign PO Box for this user? ", temp_buf, BUFSIZ))
530 if (mrcl_validate_pobox_smtp(argv[1], temp_buf, &box) !=
538 status = do_mr_query("set_pobox", 3, args, NULL, NULL);
539 if (status == MR_MACHINE)
540 Put_message("User has no local PO Box--PO Box unchanged.");
542 com_err(program_name, status, " in SplitUserPOBox");
544 Put_message("PO Box split.");
550 /* Function Name: RemoveUserPOBox
551 * Description: Removes this users POBox.
552 * Arguments: argc, argv - name of user in argv[1].
553 * Returns: DM_NORMAL.
556 int RemoveUserPOBox(int argc, char **argv)
559 char temp_buf[BUFSIZ];
561 if (!ValidName(argv[1]))
564 sprintf(temp_buf, "Are you sure that you want to remove %s's PO Box (y/n)",
567 if (Confirm(temp_buf))
569 if ((status = do_mr_query("delete_pobox", 1, argv + 1,
571 com_err(program_name, status, " in delete_pobox.");
573 Put_message("PO Box removed.");