]> andersk Git - moira.git/blob - clients/moira/pobox.c
moved from clients/passwd to clients/chfn
[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, *elem, *prev, **parts = arg;
153   int avail = atoi(argv[NFS_SIZE]) - atoi(argv[NFS_ALLOC]);
154
155   /* Dup the argv into a new mqelem. */
156   StoreInfo(argc, argv, &new);
157
158   if (!*parts)
159     {
160       *parts = new;
161       return MR_CONT;
162     }
163
164   /* Find the right place in parts for it. */
165   elem = *parts;
166   prev = NULL;
167   while (elem)
168     {
169       char **xargv = elem->q_data;
170       if (atoi(xargv[NFS_SIZE]) - atoi(xargv[NFS_ALLOC]) < avail)
171         break;
172       prev = elem;
173       elem = elem->q_forw;
174     }
175
176   if (prev)
177     AddQueue(new, prev);
178   else
179     {
180       new->q_forw = *parts;
181       (*parts)->q_back = new;
182       *parts = new;
183     }
184
185   return MR_CONT;
186 }
187
188 static int AddImapPartitions(char *server, struct mqelem **parts)
189 {
190   char *argv[2];
191   int status;
192
193   argv[0] = server;
194   argv[1] = "*";
195
196   status = do_mr_query("get_nfsphys", 2, argv, InsertSortedImapPart, parts);
197   if (status)
198     {
199       com_err(program_name, status, " in AddImapPartitions");
200       return SUB_ERROR;
201     }
202   return SUB_NORMAL;
203 }
204
205 char *CreateImapBox(char *user)
206 {
207   int status;
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;
212
213   if (!default_imap_quota)
214     {
215       char **vargv;
216       argv[0] = "def_imap_quota";
217       status = do_mr_query("get_value", 1, argv, StoreInfo, &elem);
218       if (status)
219         {
220           com_err(program_name, status, " getting default IMAP quota");
221           return (char *)SUB_ERROR;
222         }
223       vargv = elem->q_data;
224       default_imap_quota = strdup(vargv[0]);
225       FreeQueue(elem);
226     }
227
228   argv[0] = "POSTOFFICE";
229   status = do_mr_query("get_server_locations", 1, argv, StoreInfo, &servers);
230   if (status)
231     {
232       com_err(program_name, status, " in GetImapBox.");
233       return (char *)SUB_ERROR;
234     }
235   servers = QueueTop(servers);
236
237   /* Get an IMAP server. */
238   while (!server)
239     {
240       server = strdup("[ANY]");
241       if (GetValueFromUser("IMAP Server? ['?' for a list]", &server) !=
242           SUB_NORMAL)
243         {
244           free(server);
245           FreeQueue(servers);
246           return (char *)SUB_ERROR;
247         }
248
249       if (!strcmp(server, "?"))
250         {
251           elem = servers;
252           while (elem)
253             {
254               char **sargv = elem->q_data;
255               sprintf(temp_buf, "  %s\n", sargv[1]);
256               Put_message(temp_buf);
257               elem = elem->q_forw;
258             }
259           free(server);
260           server = NULL;
261         }
262     }
263   server = canonicalize_hostname(server);
264
265   /* Get the partitions on that server. */
266   if (!strcasecmp(server, "[ANY]"))
267     {
268       char **sargv;
269
270       elem = servers;
271       while (elem && !status)
272         {
273           sargv = elem->q_data;
274           status = AddImapPartitions(sargv[1], &partitions);
275           elem = elem->q_forw;
276         }
277
278       if (partitions)
279         {
280           sargv = partitions->q_data;
281           server = strdup(sargv[NFS_NAME]);
282           partition = strdup(sargv[NFS_DIR]);
283         }
284     }
285   else
286     status = AddImapPartitions(server, &partitions);
287   partitions = QueueTop(partitions);
288
289   FreeQueue(servers);
290   if (status || !partitions)
291     {
292       if (!partitions)
293         com_err(program_name, 0, "No registered nfsphys on %s.", server);
294       else
295         FreeQueue(partitions);
296       free(server);
297       return (char *)SUB_ERROR;
298     }
299
300   /* Pick a partition */
301   while (!partition)
302     {
303       char **pargv = partitions->q_data;
304       partition = strdup(pargv[NFS_DIR]);
305       if (GetValueFromUser("Partition? ['?' for a list]", &partition) !=
306           SUB_NORMAL)
307         {
308           free(server);
309           free(partition);
310           FreeQueue(partitions);
311           return (char *)SUB_ERROR;
312         }
313
314       elem = partitions;
315       if (!strcmp(partition, "?"))
316         {
317           while (elem)
318             {
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);
324               elem = elem->q_forw;
325             }
326           free(partition);
327           partition = NULL;
328         }
329       else
330         {
331           while (elem)
332             {
333               char **pargv = elem->q_data;
334               if (!strcmp(partition, pargv[NFS_DIR]))
335                 break;
336             }
337           if (!elem)
338             {
339               com_err(program_name, 0, "No such partition %s", partition);
340               free(partition);
341               partition = NULL;
342             }
343         }
344     }
345   FreeQueue(partitions);
346
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";
360
361   status = do_mr_query("add_filesys", 11, argv, NULL, NULL);
362   free(server);
363   free(partition);
364
365   if (status)
366     {
367       com_err(program_name, status, " creating IMAP filesys in CreateImapBox");
368       free(fsname);
369       return (char *)SUB_ERROR;
370     }
371
372   argv[Q_FILESYS] = fsname;
373   argv[Q_TYPE] = "USER";
374   argv[Q_NAME] = user;
375   argv[Q_QUOTA] = default_imap_quota;
376
377   status = do_mr_query("add_quota", 4, argv, NULL, NULL);
378   if (status)
379     {
380       com_err(program_name, status, " setting quota in CreateImapBox");
381       free(fsname);
382       return (char *)SUB_ERROR;
383     }
384   else
385     return fsname;
386 }
387
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.
392  */
393
394 int SetUserPOBox(int argc, char **argv)
395 {
396   int status;
397   char *type, temp_buf[BUFSIZ], *local_user, *args[10], *box;
398   struct mqelem *top = NULL;
399
400   local_user = argv[1];
401   if (!ValidName(local_user))
402     return DM_NORMAL;
403
404   /* Print the current PO Box info */
405   switch ((status = do_mr_query("get_pobox", 1, argv + 1, StoreInfo, &top)))
406     {
407     case MR_SUCCESS:
408       sprintf(temp_buf, "Current pobox for user %s: \n", local_user);
409       Put_message("");
410       top = QueueTop(top);
411       Loop(top, PrintPOBox);    /* should only return 1 box. */
412       FreeQueue(top);
413       break;
414     case MR_NO_MATCH:
415       Put_message("This user has no P.O. Box.");
416       break;
417     default:
418       com_err(program_name, status, " in get_pobox.");
419       return DM_NORMAL;
420     }
421
422   Put_message("");
423
424   sprintf(temp_buf, "Assign %s a local PO Box (y/n)", local_user);
425   switch (YesNoQuestion(temp_buf, TRUE))
426     {
427     case TRUE:
428       switch (YesNoQuestion("Use Previous Local Box (y/n)", TRUE))
429         {
430         case TRUE:
431           switch ((status = do_mr_query("set_pobox_pop", 1,
432                                         &local_user, NULL, NULL)))
433             {
434             case MR_SUCCESS:
435               return DM_NORMAL;
436             case MR_MACHINE:
437               sprintf(temp_buf, "%s did not have a previous local PO Box.",
438                       local_user);
439               Put_message(temp_buf);
440             default:
441               com_err(program_name, status, " in set_pobox_pop.");
442               return DM_NORMAL;
443             }
444           /* Fall through from MR_MACHINE case. */
445         case FALSE:
446           type = strdup("IMAP");
447           if (GetValueFromUser("Kind of Local PO Box?", &type) == SUB_ERROR)
448             {
449               free(type);
450               return DM_NORMAL;
451             }
452           if (!strcasecmp(type, "POP"))
453             {
454               free(type);
455               type = "POP";
456               if ((box = GetNewLocalPOBox(local_user)) == (char *) SUB_ERROR)
457                 return DM_NORMAL;
458             }
459           else if (!strcasecmp(type, "IMAP"))
460             {
461               free(type);
462               type = "IMAP";
463               if ((box = CreateImapBox(local_user)) == (char *) SUB_ERROR)
464                 return DM_NORMAL;
465             }
466           else
467             {
468               sprintf(temp_buf, "Unknown local PO Box type %s", type);
469               Put_message(temp_buf);
470               free(type);
471               return DM_NORMAL;
472             }
473           break;
474         default:
475           return DM_NORMAL;
476         }
477       break;
478     case FALSE:
479       type = "SMTP";
480       sprintf(temp_buf, "Set up a foreign PO Box for %s (y/n)", local_user);
481       switch (YesNoQuestion(temp_buf, TRUE))
482         {
483         case TRUE:
484           if (!Prompt_input("Foreign PO Box for this user? ", temp_buf, BUFSIZ))
485             return DM_NORMAL;
486           if (mrcl_validate_pobox_smtp(local_user, temp_buf, &box) !=
487               MRCL_SUCCESS)
488             return DM_NORMAL;
489           break;
490         case FALSE:
491         default:
492           return DM_NORMAL;     /* ^C hit. */
493         }
494       break;
495     default:                    /* ^C hit. */
496       Put_message("Aborted.");
497       return DM_NORMAL;
498     }
499
500   args[PO_NAME] = local_user;
501   args[PO_TYPE] = type;
502   args[PO_BOX] = box;
503   args[3] = NULL;
504   if ((status = do_mr_query("set_pobox", CountArgs(args), args,
505                             NULL, NULL)))
506     com_err(program_name, status, " in ChangeUserPOBox");
507   else
508     Put_message("PO Box assigned.");
509   free(box);
510
511   return DM_NORMAL;
512 }
513
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.
518  */
519
520 int SplitUserPOBox(int argc, char **argv)
521 {
522   char temp_buf[BUFSIZ], *args[3], *box;
523   int status;
524
525   if (!ValidName(argv[1]))
526     return DM_NORMAL;
527
528   if (!Prompt_input("Foreign PO Box for this user? ", temp_buf, BUFSIZ))
529     return DM_NORMAL;
530   if (mrcl_validate_pobox_smtp(argv[1], temp_buf, &box) !=
531       MRCL_SUCCESS)
532     return DM_NORMAL;
533
534   args[0] = argv[1];
535   args[1] = "SPLIT";
536   args[2] = box;
537
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.");
541   else if (status)
542     com_err(program_name, status, " in SplitUserPOBox");
543   else
544     Put_message("PO Box split.");
545   free(box);
546
547   return DM_NORMAL;
548 }
549
550 /*      Function Name: RemoveUserPOBox
551  *      Description: Removes this users POBox.
552  *      Arguments: argc, argv - name of user in argv[1].
553  *      Returns: DM_NORMAL.
554  */
555
556 int RemoveUserPOBox(int argc, char **argv)
557 {
558   int status;
559   char temp_buf[BUFSIZ];
560
561   if (!ValidName(argv[1]))
562     return DM_NORMAL;
563
564   sprintf(temp_buf, "Are you sure that you want to remove %s's PO Box (y/n)",
565           argv[1]);
566
567   if (Confirm(temp_buf))
568     {
569       if ((status = do_mr_query("delete_pobox", 1, argv + 1,
570                                 NULL, NULL)))
571         com_err(program_name, status, " in delete_pobox.");
572       else
573         Put_message("PO Box removed.");
574     }
575   return DM_NORMAL;
576 }
This page took 0.158794 seconds and 5 git commands to generate.