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 = NULL;
153 struct mqelem *elem, *prev, **parts = arg;
154 int avail = atoi(argv[NFS_SIZE]) - atoi(argv[NFS_ALLOC]);
156 /* Dup the argv into a new mqelem. */
157 StoreInfo(argc, argv, &new);
165 /* Find the right place in parts for it. */
170 char **xargv = elem->q_data;
171 if (atoi(xargv[NFS_SIZE]) - atoi(xargv[NFS_ALLOC]) < avail)
181 new->q_forw = *parts;
182 (*parts)->q_back = new;
189 static int AddImapPartitions(char *server, struct mqelem **parts)
197 status = do_mr_query("get_nfsphys", 2, argv, InsertSortedImapPart, parts);
200 com_err(program_name, status, " in AddImapPartitions");
206 char *CreateImapBox(char *user)
209 struct mqelem *elem = NULL, *servers = NULL, *partitions = NULL;
210 char *server = NULL, *partition = NULL;
211 char *argv[11], *fsname, temp_buf[BUFSIZ];
212 static char *default_imap_quota = NULL;
214 if (!default_imap_quota)
217 argv[0] = "def_imap_quota";
218 status = do_mr_query("get_value", 1, argv, StoreInfo, &elem);
221 com_err(program_name, status, " getting default IMAP quota");
222 return (char *)SUB_ERROR;
224 vargv = elem->q_data;
225 default_imap_quota = strdup(vargv[0]);
229 argv[0] = "POSTOFFICE";
230 status = do_mr_query("get_server_locations", 1, argv, StoreInfo, &servers);
233 com_err(program_name, status, " in GetImapBox.");
234 return (char *)SUB_ERROR;
236 servers = QueueTop(servers);
238 /* Get an IMAP server. */
241 server = strdup("[ANY]");
242 if (GetValueFromUser("IMAP Server? ['?' for a list]", &server) !=
247 return (char *)SUB_ERROR;
250 if (!strcmp(server, "?"))
255 char **sargv = elem->q_data;
256 sprintf(temp_buf, " %s\n", sargv[1]);
257 Put_message(temp_buf);
264 server = canonicalize_hostname(server);
266 /* Get the partitions on that server. */
267 if (!strcasecmp(server, "[ANY]"))
272 while (elem && !status)
274 sargv = elem->q_data;
275 status = AddImapPartitions(sargv[1], &partitions);
281 sargv = partitions->q_data;
282 server = strdup(sargv[NFS_NAME]);
283 partition = strdup(sargv[NFS_DIR]);
287 status = AddImapPartitions(server, &partitions);
288 partitions = QueueTop(partitions);
291 if (status || !partitions)
294 com_err(program_name, 0, "No registered nfsphys on %s.", server);
296 FreeQueue(partitions);
298 return (char *)SUB_ERROR;
301 /* Pick a partition */
304 char **pargv = partitions->q_data;
305 partition = strdup(pargv[NFS_DIR]);
306 if (GetValueFromUser("Partition? ['?' for a list]", &partition) !=
311 FreeQueue(partitions);
312 return (char *)SUB_ERROR;
316 if (!strcmp(partition, "?"))
320 char **pargv = elem->q_data;
321 sprintf(temp_buf, " %s (%s available, %d free)",
322 pargv[NFS_DIR], pargv[NFS_SIZE],
323 atoi(pargv[NFS_SIZE]) - atoi(pargv[NFS_ALLOC]));
324 Put_message(temp_buf);
334 char **pargv = elem->q_data;
335 if (!strcmp(partition, pargv[NFS_DIR]))
341 com_err(program_name, 0, "No such partition %s", partition);
347 FreeQueue(partitions);
349 fsname = malloc(strlen(user) + 4);
350 sprintf(fsname, "%s.po", user);
351 argv[FS_NAME] = fsname;
352 argv[FS_TYPE] = "IMAP";
353 argv[FS_MACHINE] = server;
354 argv[FS_PACK] = partition;
355 argv[FS_M_POINT] = "";
356 argv[FS_ACCESS] = "w";
357 argv[FS_COMMENTS] = "IMAP box";
358 argv[FS_OWNER] = user;
359 argv[FS_OWNERS] = "wheel";
360 argv[FS_CREATE] = "1";
361 argv[FS_L_TYPE] = "USER";
363 status = do_mr_query("add_filesys", 11, argv, NULL, NULL);
369 com_err(program_name, status, " creating IMAP filesys in CreateImapBox");
371 return (char *)SUB_ERROR;
374 argv[Q_FILESYS] = fsname;
375 argv[Q_TYPE] = "USER";
377 argv[Q_QUOTA] = default_imap_quota;
379 status = do_mr_query("add_quota", 4, argv, NULL, NULL);
382 com_err(program_name, status, " setting quota in CreateImapBox");
384 return (char *)SUB_ERROR;
390 /* Function Name: SetUserPOBox
391 * Description: Addes or Chnages the P.O. Box for a user.
392 * Arguments: argc, argv - the login name of the user in argv[1].
393 * Returns: DM_NORMAL.
396 int SetUserPOBox(int argc, char **argv)
399 char *type, temp_buf[BUFSIZ], *local_user, *args[10], *box;
400 struct mqelem *top = NULL;
402 local_user = argv[1];
403 if (!ValidName(local_user))
406 /* Print the current PO Box info */
407 switch ((status = do_mr_query("get_pobox", 1, argv + 1, StoreInfo, &top)))
410 sprintf(temp_buf, "Current pobox for user %s: \n", local_user);
413 Loop(top, PrintPOBox); /* should only return 1 box. */
417 Put_message("This user has no P.O. Box.");
420 com_err(program_name, status, " in get_pobox.");
426 sprintf(temp_buf, "Assign %s a local PO Box (y/n)", local_user);
427 switch (YesNoQuestion(temp_buf, TRUE))
430 switch (YesNoQuestion("Use Previous Local Box (y/n)", TRUE))
433 switch ((status = do_mr_query("set_pobox_pop", 1,
434 &local_user, NULL, NULL)))
439 sprintf(temp_buf, "%s did not have a previous local PO Box.",
441 Put_message(temp_buf);
443 com_err(program_name, status, " in set_pobox_pop.");
446 /* Fall through from MR_MACHINE case. */
448 type = strdup("IMAP");
449 if (GetValueFromUser("Kind of Local PO Box?", &type) == SUB_ERROR)
454 if (!strcasecmp(type, "POP"))
458 if ((box = GetNewLocalPOBox(local_user)) == (char *) SUB_ERROR)
461 else if (!strcasecmp(type, "IMAP"))
465 switch (YesNoQuestion("Create IMAP filesystem (y/n)", TRUE))
468 if ((box = CreateImapBox(local_user)) == (char *) SUB_ERROR)
472 box = malloc(strlen(local_user) + 4);
473 sprintf(box, "%s.po", local_user);
481 sprintf(temp_buf, "Unknown local PO Box type %s", type);
482 Put_message(temp_buf);
493 sprintf(temp_buf, "Set up a foreign PO Box for %s (y/n)", local_user);
494 switch (YesNoQuestion(temp_buf, TRUE))
497 if (!Prompt_input("Foreign PO Box for this user? ", temp_buf, BUFSIZ))
499 if (mrcl_validate_pobox_smtp(local_user, temp_buf, &box) !=
502 if (mrcl_get_message())
503 Put_message(mrcl_get_message());
509 return DM_NORMAL; /* ^C hit. */
512 default: /* ^C hit. */
513 Put_message("Aborted.");
517 args[PO_NAME] = local_user;
518 args[PO_TYPE] = type;
521 if ((status = do_mr_query("set_pobox", CountArgs(args), args,
523 com_err(program_name, status, " in ChangeUserPOBox");
525 Put_message("PO Box assigned.");
531 /* Function Name: SplitUserPOBox
532 * Description: Splits the user's PO Box between local and SMTP
533 * Arguments: argc, argv - name of user in argv[1].
534 * Returns: DM_NORMAL.
537 int SplitUserPOBox(int argc, char **argv)
539 char temp_buf[BUFSIZ], *args[3], *box;
542 if (!ValidName(argv[1]))
545 if (!Prompt_input("Foreign PO Box for this user? ", temp_buf, BUFSIZ))
547 if (mrcl_validate_pobox_smtp(argv[1], temp_buf, &box) !=
550 if (mrcl_get_message())
551 Put_message(mrcl_get_message());
559 status = do_mr_query("set_pobox", 3, args, NULL, NULL);
560 if (status == MR_MACHINE)
561 Put_message("User has no local PO Box--PO Box unchanged.");
563 com_err(program_name, status, " in SplitUserPOBox");
565 Put_message("PO Box split.");
571 /* Function Name: RemoveUserPOBox
572 * Description: Removes this users POBox.
573 * Arguments: argc, argv - name of user in argv[1].
574 * Returns: DM_NORMAL.
577 int RemoveUserPOBox(int argc, char **argv)
580 char temp_buf[BUFSIZ];
582 if (!ValidName(argv[1]))
585 sprintf(temp_buf, "Are you sure that you want to remove %s's PO Box (y/n)",
588 if (Confirm(temp_buf))
590 if ((status = do_mr_query("delete_pobox", 1, argv + 1,
592 com_err(program_name, status, " in delete_pobox.");
594 Put_message("PO Box removed.");