]> andersk Git - moira.git/blame - clients/moira/pobox.c
Dribbles of missing EXCHANGE support. This should probably look up the
[moira.git] / clients / moira / pobox.c
CommitLineData
c441a31a 1/* $Id$
7ac48069 2 *
3 * This is the file pobox.c for the Moira Client, which allows users
59ec8dae 4 * to quickly and easily maintain most parts of the Moira database.
0a2c64cb 5 * It Contains: Functions for handling the poboxes.
5eaef520 6 *
0a2c64cb 7 * Created: 7/10/88
8 * By: Chris D. Peterson
73c83e3d 9 *
7ac48069 10 * Copyright (C) 1988-1998 by the Massachusetts Institute of Technology.
11 * For copying and distribution information, please see the file
12 * <mit-copyright.h>.
73c83e3d 13 */
14
7ac48069 15#include <mit-copyright.h>
8defc06b 16#include <moira.h>
17#include <moira_site.h>
1bf73297 18#include <mrclient.h>
0a2c64cb 19#include "defs.h"
20#include "f_defs.h"
73c83e3d 21#include "globals.h"
73c83e3d 22
7ac48069 23#include <stdio.h>
24#include <stdlib.h>
25#include <string.h>
26
27RCSID("$Header$");
28
73c83e3d 29/* Function Name: PrintPOBox
30 * Description: Yet another specialized print function.
31 * Arguments: info - all info about this PO_box.
8defc06b 32 * Returns: MR_CONT
73c83e3d 33 */
34
5eaef520 35static void PrintPOBox(char **info)
73c83e3d 36{
5eaef520 37 char buf[BUFSIZ];
38
979b5f38 39 sprintf(buf, "User: %-10s Box: %-35s Type: %s", info[PO_NAME],
5eaef520 40 info[PO_BOX], info[PO_TYPE]);
41 Put_message(buf);
979b5f38 42 if (info[6])
43 {
44 sprintf(buf, "Address: %s", info[PO_ADDR]);
45 Put_message(buf);
46 sprintf(buf, MOD_FORMAT, info[5], info[4], info[6]);
47 Put_message(buf);
48 }
49 else
50 {
51 sprintf(buf, MOD_FORMAT, info[4], info[3], info[5]);
52 Put_message(buf);
53 }
73c83e3d 54}
55
56/* Function Name: RealPrintPOMachines
57 * Description: Actually does the printing for PrintPOMachines.
58 * Arguments: info, - name of machines in info[1].
59 * Returns: none.
60 */
61
5eaef520 62static void RealPrintPOMachines(char **info)
73c83e3d 63{
5eaef520 64 Print(1, info + 1, NULL);
73c83e3d 65}
66
67/* Function Name: PrintPOMachines
68 * Description: Prints all current post offices.
69 * Arguments: none.
0a2c64cb 70 * Returns: SUB_ERROR if the machines could not be printed.
73c83e3d 71 */
72
5eaef520 73static int PrintPOMachines(void)
73c83e3d 74{
44d12d58 75 int status;
5eaef520 76 static char *args[] = {"pop", NULL};
600b459e 77 struct mqelem *top = NULL;
5eaef520 78
79 if ((status = do_mr_query("get_server_locations", CountArgs(args), args,
7ac48069 80 StoreInfo, &top)))
5eaef520 81 {
82 com_err(program_name, status, " in get_server_locations.");
83 return SUB_ERROR;
0a2c64cb 84 }
5eaef520 85
86 top = QueueTop(top);
87 Loop(top, RealPrintPOMachines);
88 FreeQueue(top);
89 return SUB_NORMAL;
73c83e3d 90}
91
92/* Function Name: GetUserPOBox
93 * Description: prints the users POBox information.
94 * Arguments: argc, argv - name of the user in argv[1].
95 * Returns: DM_NORMAL.
96 */
97
5eaef520 98int GetUserPOBox(int argc, char **argv)
73c83e3d 99{
44d12d58 100 int status;
600b459e 101 struct mqelem *top = NULL;
5eaef520 102 char buf[BUFSIZ];
103
104 if (!ValidName(argv[1]))
105 return DM_NORMAL;
106
7ac48069 107 switch ((status = do_mr_query("get_pobox", 1, argv + 1, StoreInfo, &top)))
5eaef520 108 {
8defc06b 109 case MR_NO_MATCH:
5eaef520 110 Put_message("This user has no P.O. Box.");
111 break;
8defc06b 112 case MR_SUCCESS:
5eaef520 113 sprintf(buf, "Current pobox for user %s: \n", argv[1]);
114 Put_message("");
115 top = QueueTop(top);
116 Loop(top, PrintPOBox); /* should only return 1 box. */
117 FreeQueue(top);
118 break;
73c83e3d 119 default:
5eaef520 120 com_err(program_name, status, " in get_pobox.");
73c83e3d 121 }
5eaef520 122 return DM_NORMAL;
73c83e3d 123}
124
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.
0a2c64cb 128 * Returns: machine - name of the machine for then new pop box, or NULL.
73c83e3d 129 */
130
5eaef520 131static char *GetNewLocalPOBox(char *local_user)
73c83e3d 132{
5eaef520 133 char temp_buf[BUFSIZ];
134
135 sprintf(temp_buf, "%s %s", "Pick one of the following",
136 "machines for this user's Post Office.");
137 Put_message(temp_buf);
138 Put_message("");
139 if (PrintPOMachines() == SUB_NORMAL)
140 {
141 Put_message("");
142 if (!Prompt_input("Which Machine? ", temp_buf, BUFSIZ))
143 return (char *) SUB_ERROR;
7ac48069 144 return canonicalize_hostname(strdup(temp_buf));
0a2c64cb 145 }
5eaef520 146 Put_message("Could not get machines to choose from, quitting.");
147 return (char *) SUB_ERROR;
73c83e3d 148}
149
28f51a24 150static int InsertSortedImapPart(int argc, char **argv, void *arg)
151{
5ac2ad94 152 struct mqelem *new = NULL;
153 struct mqelem *elem, *prev, **parts = arg;
28f51a24 154 int avail = atoi(argv[NFS_SIZE]) - atoi(argv[NFS_ALLOC]);
155
156 /* Dup the argv into a new mqelem. */
157 StoreInfo(argc, argv, &new);
158
159 if (!*parts)
160 {
161 *parts = new;
162 return MR_CONT;
163 }
164
165 /* Find the right place in parts for it. */
166 elem = *parts;
167 prev = NULL;
168 while (elem)
169 {
170 char **xargv = elem->q_data;
171 if (atoi(xargv[NFS_SIZE]) - atoi(xargv[NFS_ALLOC]) < avail)
172 break;
173 prev = elem;
174 elem = elem->q_forw;
175 }
176
177 if (prev)
178 AddQueue(new, prev);
179 else
180 {
181 new->q_forw = *parts;
182 (*parts)->q_back = new;
183 *parts = new;
184 }
185
186 return MR_CONT;
187}
188
189static int AddImapPartitions(char *server, struct mqelem **parts)
190{
191 char *argv[2];
192 int status;
193
194 argv[0] = server;
195 argv[1] = "*";
196
197 status = do_mr_query("get_nfsphys", 2, argv, InsertSortedImapPart, parts);
198 if (status)
199 {
200 com_err(program_name, status, " in AddImapPartitions");
201 return SUB_ERROR;
202 }
203 return SUB_NORMAL;
204}
205
206char *CreateImapBox(char *user)
207{
208 int status;
ad386a73 209 struct mqelem *elem = NULL, *servers = NULL, *partitions = NULL;
28f51a24 210 char *server = NULL, *partition = NULL;
211 char *argv[11], *fsname, temp_buf[BUFSIZ];
212 static char *default_imap_quota = NULL;
213
214 if (!default_imap_quota)
215 {
216 char **vargv;
217 argv[0] = "def_imap_quota";
218 status = do_mr_query("get_value", 1, argv, StoreInfo, &elem);
219 if (status)
220 {
221 com_err(program_name, status, " getting default IMAP quota");
222 return (char *)SUB_ERROR;
223 }
224 vargv = elem->q_data;
225 default_imap_quota = strdup(vargv[0]);
226 FreeQueue(elem);
227 }
228
229 argv[0] = "POSTOFFICE";
230 status = do_mr_query("get_server_locations", 1, argv, StoreInfo, &servers);
231 if (status)
232 {
233 com_err(program_name, status, " in GetImapBox.");
234 return (char *)SUB_ERROR;
235 }
236 servers = QueueTop(servers);
237
238 /* Get an IMAP server. */
239 while (!server)
240 {
241 server = strdup("[ANY]");
242 if (GetValueFromUser("IMAP Server? ['?' for a list]", &server) !=
243 SUB_NORMAL)
244 {
245 free(server);
246 FreeQueue(servers);
247 return (char *)SUB_ERROR;
248 }
249
250 if (!strcmp(server, "?"))
251 {
252 elem = servers;
253 while (elem)
254 {
255 char **sargv = elem->q_data;
256 sprintf(temp_buf, " %s\n", sargv[1]);
257 Put_message(temp_buf);
258 elem = elem->q_forw;
259 }
260 free(server);
261 server = NULL;
262 }
263 }
264 server = canonicalize_hostname(server);
265
266 /* Get the partitions on that server. */
267 if (!strcasecmp(server, "[ANY]"))
268 {
269 char **sargv;
270
271 elem = servers;
272 while (elem && !status)
273 {
274 sargv = elem->q_data;
275 status = AddImapPartitions(sargv[1], &partitions);
276 elem = elem->q_forw;
277 }
278
279 if (partitions)
280 {
281 sargv = partitions->q_data;
282 server = strdup(sargv[NFS_NAME]);
283 partition = strdup(sargv[NFS_DIR]);
284 }
285 }
286 else
287 status = AddImapPartitions(server, &partitions);
288 partitions = QueueTop(partitions);
289
290 FreeQueue(servers);
291 if (status || !partitions)
292 {
293 if (!partitions)
294 com_err(program_name, 0, "No registered nfsphys on %s.", server);
295 else
296 FreeQueue(partitions);
297 free(server);
298 return (char *)SUB_ERROR;
299 }
300
301 /* Pick a partition */
302 while (!partition)
303 {
304 char **pargv = partitions->q_data;
305 partition = strdup(pargv[NFS_DIR]);
306 if (GetValueFromUser("Partition? ['?' for a list]", &partition) !=
307 SUB_NORMAL)
308 {
309 free(server);
310 free(partition);
311 FreeQueue(partitions);
312 return (char *)SUB_ERROR;
313 }
314
315 elem = partitions;
316 if (!strcmp(partition, "?"))
317 {
318 while (elem)
319 {
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);
325 elem = elem->q_forw;
326 }
327 free(partition);
328 partition = NULL;
329 }
330 else
331 {
332 while (elem)
333 {
334 char **pargv = elem->q_data;
335 if (!strcmp(partition, pargv[NFS_DIR]))
336 break;
5ac2ad94 337 elem = elem->q_forw;
28f51a24 338 }
339 if (!elem)
340 {
341 com_err(program_name, 0, "No such partition %s", partition);
342 free(partition);
343 partition = NULL;
344 }
345 }
346 }
347 FreeQueue(partitions);
348
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";
362
363 status = do_mr_query("add_filesys", 11, argv, NULL, NULL);
364 free(server);
365 free(partition);
366
367 if (status)
368 {
369 com_err(program_name, status, " creating IMAP filesys in CreateImapBox");
370 free(fsname);
371 return (char *)SUB_ERROR;
372 }
373
374 argv[Q_FILESYS] = fsname;
375 argv[Q_TYPE] = "USER";
376 argv[Q_NAME] = user;
377 argv[Q_QUOTA] = default_imap_quota;
378
379 status = do_mr_query("add_quota", 4, argv, NULL, NULL);
380 if (status)
381 {
382 com_err(program_name, status, " setting quota in CreateImapBox");
383 free(fsname);
384 return (char *)SUB_ERROR;
385 }
386 else
387 return fsname;
388}
389
73c83e3d 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.
394 */
395
5eaef520 396int SetUserPOBox(int argc, char **argv)
73c83e3d 397{
44d12d58 398 int status;
1bf73297 399 char *type, temp_buf[BUFSIZ], *local_user, *args[10], *box;
600b459e 400 struct mqelem *top = NULL;
5eaef520 401
28f51a24 402 local_user = argv[1];
5eaef520 403 if (!ValidName(local_user))
404 return DM_NORMAL;
405
406 /* Print the current PO Box info */
7ac48069 407 switch ((status = do_mr_query("get_pobox", 1, argv + 1, StoreInfo, &top)))
5eaef520 408 {
2f25313c 409 case MR_SUCCESS:
5eaef520 410 sprintf(temp_buf, "Current pobox for user %s: \n", local_user);
411 Put_message("");
412 top = QueueTop(top);
413 Loop(top, PrintPOBox); /* should only return 1 box. */
414 FreeQueue(top);
415 break;
2f25313c 416 case MR_NO_MATCH:
5eaef520 417 Put_message("This user has no P.O. Box.");
418 break;
2f25313c 419 default:
5eaef520 420 com_err(program_name, status, " in get_pobox.");
421 return DM_NORMAL;
2f25313c 422 }
423
28f51a24 424 Put_message("");
425
5eaef520 426 sprintf(temp_buf, "Assign %s a local PO Box (y/n)", local_user);
427 switch (YesNoQuestion(temp_buf, TRUE))
428 {
73c83e3d 429 case TRUE:
5eaef520 430 switch (YesNoQuestion("Use Previous Local Box (y/n)", TRUE))
431 {
73c83e3d 432 case TRUE:
5eaef520 433 switch ((status = do_mr_query("set_pobox_pop", 1,
7ac48069 434 &local_user, NULL, NULL)))
5eaef520 435 {
8defc06b 436 case MR_SUCCESS:
5eaef520 437 return DM_NORMAL;
8defc06b 438 case MR_MACHINE:
5eaef520 439 sprintf(temp_buf, "%s did not have a previous local PO Box.",
440 local_user);
441 Put_message(temp_buf);
73c83e3d 442 default:
5eaef520 443 com_err(program_name, status, " in set_pobox_pop.");
444 return DM_NORMAL;
73c83e3d 445 }
28f51a24 446 /* Fall through from MR_MACHINE case. */
73c83e3d 447 case FALSE:
a41a1a03 448 type = strdup("IMAP");
28f51a24 449 if (GetValueFromUser("Kind of Local PO Box?", &type) == SUB_ERROR)
450 {
451 free(type);
452 return DM_NORMAL;
453 }
454 if (!strcasecmp(type, "POP"))
455 {
456 free(type);
457 type = "POP";
458 if ((box = GetNewLocalPOBox(local_user)) == (char *) SUB_ERROR)
459 return DM_NORMAL;
460 }
461 else if (!strcasecmp(type, "IMAP"))
462 {
463 free(type);
464 type = "IMAP";
73a65411 465 switch (YesNoQuestion("Create IMAP filesystem (y/n)", TRUE))
466 {
467 case TRUE:
468 if ((box = CreateImapBox(local_user)) == (char *) SUB_ERROR)
469 return DM_NORMAL;
470 break;
471 case FALSE:
472 box = malloc(strlen(local_user) + 4);
473 sprintf(box, "%s.po", local_user);
474 break;
475 default:
476 return DM_NORMAL;
477 }
28f51a24 478 }
d1a07800 479 else if (!strcasecmp(type, "EXCHANGE"))
480 {
481 free(type);
482 type = "EXCHANGE";
483 box = "EXCHANGE.MIT.EDU";
484 }
28f51a24 485 else
486 {
487 sprintf(temp_buf, "Unknown local PO Box type %s", type);
488 Put_message(temp_buf);
489 free(type);
490 return DM_NORMAL;
491 }
5eaef520 492 break;
73c83e3d 493 default:
5eaef520 494 return DM_NORMAL;
73c83e3d 495 }
5eaef520 496 break;
73c83e3d 497 case FALSE:
28f51a24 498 type = "SMTP";
5eaef520 499 sprintf(temp_buf, "Set up a foreign PO Box for %s (y/n)", local_user);
500 switch (YesNoQuestion(temp_buf, TRUE))
501 {
73c83e3d 502 case TRUE:
1bf73297 503 if (!Prompt_input("Foreign PO Box for this user? ", temp_buf, BUFSIZ))
504 return DM_NORMAL;
505 if (mrcl_validate_pobox_smtp(local_user, temp_buf, &box) !=
506 MRCL_SUCCESS)
3b5b0aeb 507 {
508 if (mrcl_get_message())
509 Put_message(mrcl_get_message());
510 return DM_NORMAL;
511 }
5eaef520 512 break;
73c83e3d 513 case FALSE:
514 default:
5eaef520 515 return DM_NORMAL; /* ^C hit. */
73c83e3d 516 }
5eaef520 517 break;
73c83e3d 518 default: /* ^C hit. */
5eaef520 519 Put_message("Aborted.");
520 return DM_NORMAL;
73c83e3d 521 }
6f368c99 522
5eaef520 523 args[PO_NAME] = local_user;
524 args[PO_TYPE] = type;
525 args[PO_BOX] = box;
abe26090 526 args[3] = NULL;
5eaef520 527 if ((status = do_mr_query("set_pobox", CountArgs(args), args,
7ac48069 528 NULL, NULL)))
5eaef520 529 com_err(program_name, status, " in ChangeUserPOBox");
530 else
531 Put_message("PO Box assigned.");
1bf73297 532 free(box);
5eaef520 533
534 return DM_NORMAL;
73c83e3d 535}
536
450849e9 537/* Function Name: SplitUserPOBox
538 * Description: Splits the user's PO Box between local and SMTP
539 * Arguments: argc, argv - name of user in argv[1].
540 * Returns: DM_NORMAL.
541 */
542
543int SplitUserPOBox(int argc, char **argv)
544{
545 char temp_buf[BUFSIZ], *args[3], *box;
546 int status;
547
548 if (!ValidName(argv[1]))
549 return DM_NORMAL;
550
551 if (!Prompt_input("Foreign PO Box for this user? ", temp_buf, BUFSIZ))
552 return DM_NORMAL;
553 if (mrcl_validate_pobox_smtp(argv[1], temp_buf, &box) !=
554 MRCL_SUCCESS)
3b5b0aeb 555 {
556 if (mrcl_get_message())
557 Put_message(mrcl_get_message());
558 return DM_NORMAL;
559 }
450849e9 560
561 args[0] = argv[1];
562 args[1] = "SPLIT";
563 args[2] = box;
564
565 status = do_mr_query("set_pobox", 3, args, NULL, NULL);
566 if (status == MR_MACHINE)
567 Put_message("User has no local PO Box--PO Box unchanged.");
568 else if (status)
569 com_err(program_name, status, " in SplitUserPOBox");
570 else
571 Put_message("PO Box split.");
572 free(box);
573
574 return DM_NORMAL;
575}
576
73c83e3d 577/* Function Name: RemoveUserPOBox
578 * Description: Removes this users POBox.
579 * Arguments: argc, argv - name of user in argv[1].
580 * Returns: DM_NORMAL.
581 */
582
5eaef520 583int RemoveUserPOBox(int argc, char **argv)
73c83e3d 584{
44d12d58 585 int status;
5eaef520 586 char temp_buf[BUFSIZ];
587
588 if (!ValidName(argv[1]))
589 return DM_NORMAL;
590
591 sprintf(temp_buf, "Are you sure that you want to remove %s's PO Box (y/n)",
592 argv[1]);
593
594 if (Confirm(temp_buf))
595 {
596 if ((status = do_mr_query("delete_pobox", 1, argv + 1,
7ac48069 597 NULL, NULL)))
5eaef520 598 com_err(program_name, status, " in delete_pobox.");
599 else
600 Put_message("PO Box removed.");
73c83e3d 601 }
5eaef520 602 return DM_NORMAL;
73c83e3d 603}
This page took 0.215581 seconds and 5 git commands to generate.