]> andersk Git - moira.git/blob - clients/moira/pobox.c
2199d3bbc8949c909bc0856a93c167bccd9e59a0
[moira.git] / clients / moira / pobox.c
1 /* $Id$
2  *
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.
6  *
7  *      Created:        7/10/88
8  *      By:             Chris D. Peterson
9  *
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>.
13  */
14
15 #include <mit-copyright.h>
16 #include <moira.h>
17 #include <moira_site.h>
18 #include <mrclient.h>
19 #include "defs.h"
20 #include "f_defs.h"
21 #include "globals.h"
22
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <string.h>
26
27 RCSID("$Header$");
28
29 /*      Function Name: PrintPOBox
30  *      Description: Yet another specialized print function.
31  *      Arguments: info - all info about this PO_box.
32  *      Returns: MR_CONT
33  */
34
35 static void PrintPOBox(char **info)
36 {
37   char buf[BUFSIZ];
38
39   sprintf(buf, "User: %-10s Box: %-35s Type: %s", info[PO_NAME],
40           info[PO_BOX], info[PO_TYPE]);
41   Put_message(buf);
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     }
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
62 static void RealPrintPOMachines(char **info)
63 {
64   Print(1, info + 1, NULL);
65 }
66
67 /*      Function Name: PrintPOMachines
68  *      Description: Prints all current post offices.
69  *      Arguments: none.
70  *      Returns: SUB_ERROR if the machines could not be printed.
71  */
72
73 static int PrintPOMachines(void)
74 {
75   int status;
76   static char *args[] = {"pop", NULL};
77   struct mqelem *top = NULL;
78
79   if ((status = do_mr_query("get_server_locations", CountArgs(args), args,
80                             StoreInfo, &top)))
81     {
82       com_err(program_name, status, " in get_server_locations.");
83       return SUB_ERROR;
84     }
85
86   top = QueueTop(top);
87   Loop(top, RealPrintPOMachines);
88   FreeQueue(top);
89   return SUB_NORMAL;
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
98 int GetUserPOBox(int argc, char **argv)
99 {
100   int status;
101   struct mqelem *top = NULL;
102   char buf[BUFSIZ];
103
104   if (!ValidName(argv[1]))
105     return DM_NORMAL;
106
107   switch ((status = do_mr_query("get_pobox", 1, argv + 1, StoreInfo, &top)))
108     {
109     case MR_NO_MATCH:
110       Put_message("This user has no P.O. Box.");
111       break;
112     case MR_SUCCESS:
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;
119     default:
120       com_err(program_name, status, " in get_pobox.");
121     }
122   return DM_NORMAL;
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.
128  *      Returns: machine - name of the machine for then new pop box, or NULL.
129  */
130
131 static char *GetNewLocalPOBox(char *local_user)
132 {
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;
144       return canonicalize_hostname(strdup(temp_buf));
145     }
146   Put_message("Could not get machines to choose from, quitting.");
147   return (char *) SUB_ERROR;
148 }
149
150 static int InsertSortedImapPart(int argc, char **argv, void *arg)
151 {
152   struct mqelem *new = NULL;
153   struct mqelem *elem, *prev, **parts = arg;
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
189 static 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
206 char *CreateImapBox(char *user)
207 {
208   int status;
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;
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;
337               elem = elem->q_forw;
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
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
396 int SetUserPOBox(int argc, char **argv)
397 {
398   int status;
399   char *type, temp_buf[BUFSIZ], *local_user, *args[10], *box;
400   struct mqelem *top = NULL;
401
402   local_user = argv[1];
403   if (!ValidName(local_user))
404     return DM_NORMAL;
405
406   /* Print the current PO Box info */
407   switch ((status = do_mr_query("get_pobox", 1, argv + 1, StoreInfo, &top)))
408     {
409     case MR_SUCCESS:
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;
416     case MR_NO_MATCH:
417       Put_message("This user has no P.O. Box.");
418       break;
419     default:
420       com_err(program_name, status, " in get_pobox.");
421       return DM_NORMAL;
422     }
423
424   Put_message("");
425
426   sprintf(temp_buf, "Assign %s a local PO Box (y/n)", local_user);
427   switch (YesNoQuestion(temp_buf, TRUE))
428     {
429     case TRUE:
430       switch (YesNoQuestion("Use Previous Local Box (y/n)", TRUE))
431         {
432         case TRUE:
433           switch ((status = do_mr_query("set_pobox_pop", 1,
434                                         &local_user, NULL, NULL)))
435             {
436             case MR_SUCCESS:
437               return DM_NORMAL;
438             case MR_MACHINE:
439               sprintf(temp_buf, "%s did not have a previous local PO Box.",
440                       local_user);
441               Put_message(temp_buf);
442             default:
443               com_err(program_name, status, " in set_pobox_pop.");
444               return DM_NORMAL;
445             }
446           /* Fall through from MR_MACHINE case. */
447         case FALSE:
448           type = strdup("IMAP");
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";
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                 }
478             }
479           else
480             {
481               sprintf(temp_buf, "Unknown local PO Box type %s", type);
482               Put_message(temp_buf);
483               free(type);
484               return DM_NORMAL;
485             }
486           break;
487         default:
488           return DM_NORMAL;
489         }
490       break;
491     case FALSE:
492       type = "SMTP";
493       sprintf(temp_buf, "Set up a foreign PO Box for %s (y/n)", local_user);
494       switch (YesNoQuestion(temp_buf, TRUE))
495         {
496         case TRUE:
497           if (!Prompt_input("Foreign PO Box for this user? ", temp_buf, BUFSIZ))
498             return DM_NORMAL;
499           if (mrcl_validate_pobox_smtp(local_user, temp_buf, &box) !=
500               MRCL_SUCCESS)
501             {
502               if (mrcl_get_message())
503                 Put_message(mrcl_get_message());
504               return DM_NORMAL;
505             }
506           break;
507         case FALSE:
508         default:
509           return DM_NORMAL;     /* ^C hit. */
510         }
511       break;
512     default:                    /* ^C hit. */
513       Put_message("Aborted.");
514       return DM_NORMAL;
515     }
516
517   args[PO_NAME] = local_user;
518   args[PO_TYPE] = type;
519   args[PO_BOX] = box;
520   args[3] = NULL;
521   if ((status = do_mr_query("set_pobox", CountArgs(args), args,
522                             NULL, NULL)))
523     com_err(program_name, status, " in ChangeUserPOBox");
524   else
525     Put_message("PO Box assigned.");
526   free(box);
527
528   return DM_NORMAL;
529 }
530
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.
535  */
536
537 int SplitUserPOBox(int argc, char **argv)
538 {
539   char temp_buf[BUFSIZ], *args[3], *box;
540   int status;
541
542   if (!ValidName(argv[1]))
543     return DM_NORMAL;
544
545   if (!Prompt_input("Foreign PO Box for this user? ", temp_buf, BUFSIZ))
546     return DM_NORMAL;
547   if (mrcl_validate_pobox_smtp(argv[1], temp_buf, &box) !=
548       MRCL_SUCCESS)
549     {
550       if (mrcl_get_message())
551         Put_message(mrcl_get_message());
552       return DM_NORMAL;
553     }
554
555   args[0] = argv[1];
556   args[1] = "SPLIT";
557   args[2] = box;
558
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.");
562   else if (status)
563     com_err(program_name, status, " in SplitUserPOBox");
564   else
565     Put_message("PO Box split.");
566   free(box);
567
568   return DM_NORMAL;
569 }
570
571 /*      Function Name: RemoveUserPOBox
572  *      Description: Removes this users POBox.
573  *      Arguments: argc, argv - name of user in argv[1].
574  *      Returns: DM_NORMAL.
575  */
576
577 int RemoveUserPOBox(int argc, char **argv)
578 {
579   int status;
580   char temp_buf[BUFSIZ];
581
582   if (!ValidName(argv[1]))
583     return DM_NORMAL;
584
585   sprintf(temp_buf, "Are you sure that you want to remove %s's PO Box (y/n)",
586           argv[1]);
587
588   if (Confirm(temp_buf))
589     {
590       if ((status = do_mr_query("delete_pobox", 1, argv + 1,
591                                 NULL, NULL)))
592         com_err(program_name, status, " in delete_pobox.");
593       else
594         Put_message("PO Box removed.");
595     }
596   return DM_NORMAL;
597 }
This page took 0.068757 seconds and 3 git commands to generate.