]> andersk Git - moira.git/blob - clients/moira/lists.c
a398ef02b8af7771aa63945b2637593e4ecd7c4e
[moira.git] / clients / moira / lists.c
1 /* $Id$
2  *
3  *      This is the file lists.c for the Moira Client, which allows users
4  *      to quickly and easily maintain most parts of the Moira database.
5  *      It Contains: All list manipulation functions, except delete.
6  *
7  *      Created:        4/12/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 <mrclient.h>
18 #include <moira_site.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 struct mqelem *GetListInfo(int type, char *name1, char *name2);
30 char **AskListInfo(char **info, Bool name);
31 int AddList(int argc, char **argv);
32 void ListMembersByType(char *type, int tags);
33 int GetMemberInfo(char *action, char **ret_argv);
34
35 #define LIST    0
36 #define MEMBERS 1
37 #define GLOM    2
38 #define ACE_USE 3
39
40 #define DEFAULT_ACTIVE      DEFAULT_YES
41 #define DEFAULT_PUBLIC      DEFAULT_YES
42 #define DEFAULT_HIDDEN      DEFAULT_NO
43 #define DEFAULT_MAILLIST    DEFAULT_YES
44 #define DEFAULT_GROUP       DEFAULT_NO
45 #define DEFAULT_GID         UNIQUE_GID
46 #define DEFAULT_NFSGROUP    DEFAULT_NO
47 #define DEFAULT_ACE_TYPE    "user"
48 #define DEFAULT_ACE_NAME    (user)
49 #define DEFAULT_MEMACE_TYPE "NONE"
50 #define DEFAULT_MEMACE_NAME "NONE"
51 #define DEFAULT_DESCRIPTION DEFAULT_COMMENT
52
53 /* globals only for this file. */
54
55 static char current_list[BUFSIZ];
56
57
58 /*      Function Name: PrintListAce
59  *      Description: This function prints the list ace information.
60  *      Arguments: info - an info structure.
61  *      Returns: none.
62  */
63
64 static void PrintListAce(char **info)
65 {
66   char buf[BUFSIZ];
67
68   sprintf(buf, "Item: %-20s Name: %s", info[ACE_TYPE], info[ACE_NAME]);
69   Put_message(buf);
70 }
71
72 /*      Function Name: PrintListInfo
73  *      Description: This function Prints out the List info in a coherent form.
74  *      Arguments: info - the List info.
75  *      Returns: none.
76  */
77
78 static void PrintListInfo(char **info)
79 {
80   char buf[BUFSIZ];
81
82   Put_message(" ");
83   sprintf(buf, "%20sList: %s", "", info[L_NAME]);
84   Put_message(buf);
85   sprintf(buf, "Description: %s", info[L_DESC]);
86   Put_message(buf);
87   if (atoi(info[L_MAILLIST]))
88     Put_message("This list is a mailing list.");
89   else
90     Put_message("This list is NOT a mailing list.");
91   if (atoi(info[L_GROUP]))
92     {
93       sprintf(buf, "This list is a Group%s and its ID number is %s",
94               atoi(info[L_NFSGROUP]) ? " and an NFS Group," : "",
95               info[L_GID]);
96       Put_message(buf);
97     }
98   else
99     Put_message("This list is NOT a Group.");
100
101   if (!strcmp(info[L_ACE_TYPE], "NONE"))
102     Put_message("This list has no Administrator, how strange?!");
103   else
104     {
105       sprintf(buf, "The Administrator of this list is the %s: %s",
106               info[L_ACE_TYPE], info[L_ACE_NAME]);
107       Put_message(buf);
108     }
109
110   if (strcmp(info[L_MEMACE_TYPE], "NONE"))
111     {
112       sprintf(buf, "The Membership Administrator of this list is the %s: %s",
113               info[L_MEMACE_TYPE], info[L_MEMACE_NAME]);
114       Put_message(buf);
115     }
116
117   sprintf(buf, "This list is: %s, %s, and %s",
118           atoi(info[L_ACTIVE]) ? "active" : "inactive",
119           atoi(info[L_PUBLIC]) ? "public" : "private",
120           atoi(info[L_HIDDEN]) ? "hidden" : "visible");
121   Put_message(buf);
122   sprintf(buf, MOD_FORMAT, info[L_MODBY], info[L_MODTIME], info[L_MODWITH]);
123   Put_message(buf);
124 }
125
126 /*      Function Name: GetListInfo
127  *      Description: Stores all info about a group of lists in a queue.
128  *      Arguments: type - type of info to store.
129  *                 name - name of the info.
130  *      Returns: the first element in the queue.
131  */
132
133 struct mqelem *GetListInfo(int type, char *name1, char *name2)
134 {
135   char *args[2];
136   struct mqelem *elem = NULL;
137   int status;
138
139   switch (type)
140     {
141     case LIST:
142       args[0] = name1;
143       if ((status = do_mr_query("get_list_info", 1, args, StoreInfo, &elem)))
144         {
145           com_err(program_name, status, " in get_list_info");
146           return NULL;
147         }
148       break;
149     case MEMBERS:
150       args[0] = name1;
151       if ((status = do_mr_query("get_members_of_list", 1, args,
152                                 StoreInfo, &elem)))
153         {
154           com_err(program_name, status, " in get_members_of_list");
155           return NULL;
156         }
157       break;
158     case GLOM:
159       args[0] = name1;
160       args[1] = name2;
161       if (!strcmp(name1, "MACHINE"))
162           args[1] = canonicalize_hostname(strdup(name2));
163       if ((status = do_mr_query("get_lists_of_member", 2, args,
164                                 StoreInfo, &elem)))
165         {
166           com_err(program_name, status, " in get_list_of_members");
167           return NULL;
168         }
169       break;
170     case ACE_USE:
171       args[0] = name1;
172       args[1] = name2;
173       if ((status = do_mr_query("get_ace_use", 2, args, StoreInfo, &elem)))
174         {
175           com_err(program_name, status, " in get_ace_use");
176           return NULL;
177         }
178       break;
179     }
180   return QueueTop(elem);
181 }
182
183 /*      Function Name: AskListInfo.
184  *      Description: This function askes the user for information about a
185  *                   machine and saves it into a structure.
186  *      Arguments: info - a pointer the the structure to put the
187  *                             info into.
188  *                 name - add a newname field? (T/F)
189  *      Returns: SUB_ERROR or SUB_NORMAL.
190  */
191
192 char **AskListInfo(char **info, Bool name)
193 {
194   char temp_buf[BUFSIZ], *newname;
195
196   Put_message(" ");
197   sprintf(temp_buf, "Setting information of list %s.", info[L_NAME]);
198   Put_message(temp_buf);
199   Put_message(" ");
200
201   if (name)
202     {
203       while (1)
204         {
205           newname = strdup(info[L_NAME]);
206           if (GetValueFromUser("The new name for this list", &newname) ==
207               SUB_ERROR)
208             return NULL;
209           if (ValidName(newname))
210             break;
211         }
212     }
213   if (GetYesNoValueFromUser("Is this an active list", &info[L_ACTIVE]) ==
214       SUB_ERROR)
215     return NULL;
216   if (GetYesNoValueFromUser("Is this a public list", &info[L_PUBLIC]) ==
217       SUB_ERROR)
218     return NULL;
219   if (GetYesNoValueFromUser("Is this a hidden list", &info[L_HIDDEN]) ==
220       SUB_ERROR)
221     return NULL;
222   if (GetYesNoValueFromUser("Is this a maillist", &info[L_MAILLIST]) ==
223       SUB_ERROR)
224     return NULL;
225   if (GetYesNoValueFromUser("Is this a group", &info[L_GROUP]) == SUB_ERROR)
226     return NULL;
227   if (atoi(info[L_GROUP]))
228     {
229       if (GetYesNoValueFromUser("Is this an NFS group", &info[L_NFSGROUP]) == 
230           SUB_ERROR)
231         return NULL;
232       if (GetValueFromUser("What is the GID for this group.", &info[L_GID]) ==
233           SUB_ERROR)
234         return NULL;
235     }
236
237   do {
238     if (GetTypeFromUser("What Type of Administrator", "ace_type",
239                         &info[L_ACE_TYPE]) == SUB_ERROR)
240       return NULL;
241     if (strcasecmp(info[L_ACE_TYPE], "none"))
242       {
243         sprintf(temp_buf, "Which %s will be the administrator of this list: ",
244                 info[L_ACE_TYPE]);
245         if (GetValueFromUser(temp_buf, &info[L_ACE_NAME]) == SUB_ERROR)
246           return NULL;
247       }
248     else
249       {
250         Put_message("Setting the administrator of this list to 'NONE'");
251         Put_message("will make you unable to further modify the list.");
252         if (YesNoQuestion("Do you really want to do this?", FALSE) == TRUE)
253           break;
254       }
255   } while (!strcasecmp(info[L_ACE_TYPE], "none"));
256         
257   if (!strcasecmp(info[L_ACE_TYPE], "kerberos"))
258     {
259       char *canon;
260       
261       mrcl_validate_kerberos_member(info[L_ACE_NAME], &canon);
262       if (mrcl_get_message())
263         Put_message(mrcl_get_message());
264       free(info[L_ACE_NAME]);
265       info[L_ACE_NAME] = canon;
266     }
267   if (GetTypeFromUser("What Type of Membership Administrator", "ace_type",
268                       &info[L_MEMACE_TYPE]) == SUB_ERROR)
269     return NULL;
270   if (strcasecmp(info[L_MEMACE_TYPE], "none"))
271     {
272       sprintf(temp_buf, "Which %s will be the membership administrator of this list: ",
273               info[L_MEMACE_TYPE]);
274       if (GetValueFromUser(temp_buf, &info[L_MEMACE_NAME]) == SUB_ERROR)
275         return NULL;
276     }
277   if (!strcasecmp(info[L_MEMACE_TYPE], "kerberos"))
278     {
279       char *canon;
280
281       mrcl_validate_kerberos_member(info[L_MEMACE_NAME], &canon);
282       if (mrcl_get_message())
283         Put_message(mrcl_get_message());
284       free(info[L_MEMACE_NAME]);
285       info[L_MEMACE_NAME] = canon;
286     }
287   if (GetValueFromUser("Description: ", &info[L_DESC]) == SUB_ERROR)
288     return NULL;
289
290   FreeAndClear(&info[L_MODTIME], TRUE);
291   FreeAndClear(&info[L_MODBY], TRUE);
292   FreeAndClear(&info[L_MODWITH], TRUE);
293   /*
294    * Slide the newname into the #2 slot, this screws up all future references
295    * to this list.
296    */
297   if (name)                     /* slide the newname into the #2 slot. */
298     SlipInNewName(info, newname);
299
300   return info;
301 }
302
303 /* -------------- List functions. -------------- */
304
305 /*      Function Name: ShowListInfo.
306  *      Description: shows info on a list.
307  *      Arguments: argc, argv - name of list in argv[1].
308  *      Returns: DM status code.
309  */
310
311 int ShowListInfo(int argc, char **argv)
312 {
313   struct mqelem *top, *list;
314
315   top = list = GetListInfo(LIST, argv[1], NULL);
316   while (list)
317     {
318       PrintListInfo(list->q_data);
319       list = list->q_forw;
320     }
321
322   FreeQueue(top);
323   return DM_NORMAL;
324 }
325
326 /*      Function Name: RealUpdateList
327  *      Description: performs the actual update of the list.
328  *      Arguments: info - all information needed to update the list.
329  *                 junk - an UNUSED boolean.
330  *      Returns: none.
331  */
332
333 static void RealUpdateList(char **info, Bool junk)
334 {
335   int stat;
336   char **args;
337   struct mqelem *elem = NULL;
338
339   if (!(args = AskListInfo(info, TRUE)))
340     {
341       Put_message("Aborted.");
342       return;
343     }
344
345   /*
346    * If the new list name is less than 8 characters, make sure it doesn't
347    * collide with a username.
348    */
349   if ((strlen(args[2]) <= 8) &&
350       do_mr_query("get_user_account_by_login", 1, args + 1,
351                   StoreInfo, &elem) != MR_NO_MATCH)
352     {
353       char buf[256];
354
355       sprintf(buf, "\nA user by the name `%s' already exists in the database.",
356               args[1]);
357       Put_message(buf);
358       Loop(QueueTop(elem), FreeInfo);
359       FreeQueue(elem);
360       if (YesNoQuestion("Do you still want to rename this list to that name",
361                         FALSE) != TRUE)
362         {
363           Put_message("List ** NOT ** Updated.");
364           return;
365         }
366     }
367
368   if ((stat = do_mr_query("update_list", CountArgs(args), args,
369                           NULL, NULL)) != MR_SUCCESS)
370     {
371       com_err(program_name, stat, " in UpdateList.");
372       Put_message("List ** NOT ** Updated.");
373     }
374   else
375     Put_message("List successfully updated.");
376 }
377
378 /*      Function Name: UpdateList
379  *      Description: updates the information on a list.
380  *      Arguments: argc, argv - name of list in argv[1].
381  *      Returns: DM Status code.
382  */
383
384 int UpdateList(int argc, char **argv)
385 {
386   struct mqelem *top;
387
388   top = GetListInfo(LIST, argv[1], (char *) NULL);
389   QueryLoop(top, NullPrint, RealUpdateList, "Update the list");
390
391   FreeQueue(top);
392   return DM_NORMAL;
393 }
394
395 /*      Function Name: SetDefaults
396  *      Description: sets defaults for AddList function
397  *      Arguments: info - the array to add them to.
398  *                 name - name of the program to add.
399  *      Returns: defaults - the default information.
400  */
401
402 static char **SetDefaults(char **info, char *name)
403 {
404   info[L_NAME] =     strdup(name);
405   info[L_ACTIVE] =   strdup(DEFAULT_ACTIVE);
406   info[L_PUBLIC] =   strdup(DEFAULT_PUBLIC);
407   info[L_HIDDEN] =   strdup(DEFAULT_HIDDEN);
408   info[L_MAILLIST] = strdup(DEFAULT_MAILLIST);
409   info[L_GROUP] =    strdup(DEFAULT_GROUP);
410   info[L_GID] =      strdup(DEFAULT_GID);
411   info[L_NFSGROUP] = strdup(DEFAULT_NFSGROUP);
412   info[L_ACE_TYPE] = strdup(DEFAULT_ACE_TYPE);
413   info[L_ACE_NAME] = strdup(DEFAULT_ACE_NAME);
414   info[L_MEMACE_TYPE] = strdup(DEFAULT_MEMACE_TYPE);
415   info[L_MEMACE_NAME] = strdup(DEFAULT_MEMACE_NAME);
416   info[L_DESC] =     strdup(DEFAULT_DESCRIPTION);
417   info[L_MODTIME] = info[L_MODBY] = info[L_MODWITH] = info[L_END] = NULL;
418   return info;
419 }
420
421 /*      Function Name: AddList
422  *      Description:
423  *      Arguments: argc, argv - name of list in argv[1].
424  *      Returns: SUB_ERROR if list not created.
425  */
426
427 int AddList(int argc, char **argv)
428 {
429   static char *info[MAX_ARGS_SIZE], **add_args;
430   int status, ret_code = SUB_NORMAL;
431   struct mqelem *elem = NULL;
432
433   if (!ValidName(argv[1]))
434     return DM_NORMAL;
435   status = do_mr_query("get_list_info", 1, argv + 1, NULL, NULL);
436   if (status != MR_NO_MATCH)
437     {
438       if (status == MR_SUCCESS)
439         Put_message("This list already exists.");
440       else
441         com_err(program_name, status, " in AddList.");
442       return SUB_ERROR;
443     }
444
445   /*
446    * If the listname is less than 8 characters, make sure it doesn't
447    * collide with a username.
448    */
449   if ((strlen(argv[1]) <= 8) &&
450       do_mr_query("get_user_account_by_login", 1, argv + 1,
451                   StoreInfo, &elem) != MR_NO_MATCH)
452     {
453       char buf[256];
454
455       sprintf(buf, "\nA user by the name `%s' already exists in the database.",
456               argv[1]);
457       Put_message(buf);
458       Loop(QueueTop(elem), FreeInfo);
459       FreeQueue(elem);
460       if (YesNoQuestion("Create a list with the same name", FALSE) != TRUE)
461         return SUB_ERROR;
462     }
463
464   if (!(add_args = AskListInfo(SetDefaults(info, argv[1]), FALSE)))
465     {
466       Put_message("Aborted.");
467       return SUB_ERROR;
468     }
469
470   if ((status = do_mr_query("add_list", CountArgs(add_args), add_args,
471                             NULL, NULL)) != MR_SUCCESS)
472     {
473       com_err(program_name, status, " in AddList.");
474       Put_message("List Not Created.");
475       ret_code = SUB_ERROR;
476     }
477
478   FreeInfo(info);
479   return ret_code;
480 }
481
482 /*      Function Name: Instructions
483  *      Description: This func prints out instruction on manipulating lists.
484  *      Arguments: none
485  *      Returns: DM Status Code.
486  */
487
488 int ListHelp(int argc, char **argv)
489 {
490   static char *message[] = {
491     "Listmaint handles the creation, deletion, and updating of lists.",
492     "A list can be a mailing list, a group list, or both.",
493     "The concept behind lists is that a list has an owner",
494     "- administrator -  and members.",
495     "The administrator of a list may be another list.",
496     "The members of a list can be users (login names), other lists,",
497     "or address strings.",
498     "You can use certain keys to do the following:",
499     "    Refresh the screen - Type ctrl-L.",
500     "    Escape from a function - Type ctrl-C.",
501     "    Suspend the program (temporarily) - Type ctrl-Z.",
502     NULL,
503   };
504
505   return PrintHelp(message);
506 }
507
508 /*-*-* LISTMAINT UPDATE MENU *-*-*/
509
510 /*      Function Name: ListmaintMemberMenuEntry
511  *      Description: entry routine into the listmaint member menu.
512  *      Arguments: m - the member menu.
513  *                 argc, argv - name of the list in argv[1].
514  *      Returns: none.
515  */
516
517 int ListmaintMemberMenuEntry(Menu *m, int argc, char **argv)
518 {
519   char temp_buf[BUFSIZ];
520   char *list_name = argv[1];
521   int stat;
522
523   if (!ValidName(list_name))
524     return DM_QUIT;
525
526   if (*argv[0] == 'a')
527     {   /* add_list */
528       if (AddList(argc, argv) == SUB_ERROR)
529         return DM_QUIT;
530       sprintf(temp_buf, "List '%s' created. Do you want to %s", list_name,
531               "change its membership (y/n)? ");
532       if (YesNoQuestion(temp_buf, TRUE) != TRUE)
533         return DM_QUIT;
534     }
535   else
536     /* All we want to know is if it exists. */
537     switch ((stat = do_mr_query("count_members_of_list", 1, argv + 1,
538                                 NULL, NULL)))
539       {
540       case MR_SUCCESS:
541         break;
542       case MR_LIST:
543         Put_message("This list does not exist.");
544         return DM_QUIT;
545       case MR_PERM:
546         Put_message("You are not allowed to view this list.");
547         break;
548       default:
549         com_err(program_name, stat, " in get_list_info");
550         return DM_QUIT;
551       }
552
553   sprintf(temp_buf, "Change/Display membership of '%s'", list_name);
554   m->m_title = strdup(temp_buf);
555   strcpy(current_list, list_name);
556   return DM_NORMAL;
557 }
558
559 /*      Function Name: ListmaintMemberMenuExit
560  *      Description: This is the function called when the member menu is
561  *                   exited, it frees the memory that is storing the name.
562  *      Arguments: m - the menu
563  *      Returns: DM_NORMAL
564  */
565
566 int ListmaintMemberMenuExit(Menu *m)
567 {
568   free(m->m_title);
569   strcpy(current_list, "");
570   return DM_NORMAL;
571 }
572
573 /*      Function Name: ListMembersByType
574  *      Description: This function lists the users of a list by type.
575  *      Arguments: type - the type of the list "USER", "LIST", or "STRING".
576  *                 tags - whether or not to display tags
577  *      Returns: none.
578  *      NOTE: if type is NULL, all lists members are listed.
579  */
580
581 void ListMembersByType(char *type, int tags)
582 {
583   char temp_buf[BUFSIZ];
584   int status;
585   char *args[10];
586
587   args[0] = current_list;
588   args[1] = NULL;
589
590   found_some = FALSE;
591   if ((status = do_mr_query(tags ? "get_tagged_members_of_list" :
592                             "get_members_of_list", CountArgs(args),
593                             args, PrintByType, type)))
594     com_err(program_name, status, " in ListMembersByType");
595   if (!found_some)
596     {
597       if (!type)
598         Put_message("List is empty (no members).");
599       else
600         {
601           sprintf(temp_buf, "No %s Members", type);
602           Put_message(temp_buf);
603         }
604     }
605 }
606
607 /*      Function Name: ListAllMembers
608  *      Description: lists all members of the current list.
609  *      Arguments:
610  *      Returns: DM_NORMAL
611  */
612
613 int ListAllMembers(int argc, char **argv)
614 {
615   ListMembersByType(NULL, 0);
616   return DM_NORMAL;
617 }
618
619 /*      Function Name: ListUserMembers
620  *      Description: This function lists all members of a list of type "USER".
621  *      Arguments: none
622  *      Returns: DM_NORMAL.
623  */
624
625 int ListUserMembers(int argc, char **argv)
626 {
627   ListMembersByType("USER", 0);
628   return DM_NORMAL;
629 }
630
631 /*      Function Name: ListListMembers
632  *      Description: This function lists all members of a list of type "LIST".
633  *      Arguments: none
634  *      Returns: DM_NORMAL.
635  */
636
637 int ListListMembers(int argc, char **argv)
638 {
639   ListMembersByType("LIST", 0);
640   return DM_NORMAL;
641 }
642
643 /*      Function Name: ListStringMembers
644  *      Description:This function lists all members of a list of type "STRING".
645  *      Arguments: none
646  *      Returns: DM_NORMAL.
647  */
648
649 int ListStringMembers(int argc, char **argv)
650 {
651   ListMembersByType("STRING", 0);
652   return DM_NORMAL;
653 }
654
655 /*      Function Name: GetMemberInfo
656  *      Description: This function gets the information needed to
657  *                   add or delete a user from a list.
658  *      Arguments: argc, argv - standard.
659  *                 action - name of the action to be performed either
660  *                          "add" or "delete".
661  *                 ret_argc, ret_argv - the returned value of argc and argv.
662  *      Returns: SUB_ERROR or SUB_NORMAL.
663  */
664
665 int GetMemberInfo(char *action, char **ret_argv)
666 {
667   char temp_buf[BUFSIZ];
668
669   ret_argv[LM_LIST] = strdup(current_list);
670
671   ret_argv[LM_TYPE] = strdup("user");
672   if (GetTypeFromUser("Type of member", "member", &ret_argv[LM_TYPE]) ==
673       SUB_ERROR)
674     return SUB_ERROR;
675
676   sprintf(temp_buf, "Name of %s to %s", ret_argv[LM_TYPE], action);
677   ret_argv[LM_MEMBER] = strdup(user);
678   if (GetValueFromUser(temp_buf, &ret_argv[LM_MEMBER]) == SUB_ERROR)
679     return SUB_ERROR;
680   ret_argv[LM_END] = NULL;              /* NULL terminate this list. */
681
682   if (strcasecmp(ret_argv[LM_TYPE], "string") &&
683       !ValidName(ret_argv[LM_MEMBER]))
684     {
685       FreeInfo(ret_argv);
686       return SUB_ERROR;
687     }
688   return SUB_NORMAL;
689 }
690
691 /*      Function Name: AddMember
692  *      Description: This function adds a member to a list.
693  *      Arguments: none.
694  *      Returns: DM_NORMAL.
695  */
696
697 int AddMember(int argc, char **argv)
698 {
699   char *args[10], temp_buf[BUFSIZ], *p;
700   int status;
701   struct mqelem *mailhubs, *elem;
702
703   if (GetMemberInfo("add", args) == SUB_ERROR)
704     return DM_NORMAL;
705
706   if (!strcmp(args[LM_TYPE], "STRING"))
707     {
708       status = mrcl_validate_string_member(args[LM_MEMBER]);
709       if (status != MRCL_SUCCESS)
710         Put_message(mrcl_get_message());
711       if (status == MRCL_REJECT)
712         return DM_NORMAL;
713     }
714   else if (!strcmp(args[LM_TYPE], "KERBEROS"))
715     {
716       char *canon;
717
718       mrcl_validate_kerberos_member(args[LM_MEMBER], &canon);
719       if (mrcl_get_message())
720         Put_message(mrcl_get_message());
721       free(args[LM_MEMBER]);
722       args[LM_MEMBER] = canon;
723     }
724   else if (!strcmp(args[LM_TYPE], "MACHINE"))
725     {
726       char *canon;
727       canon = canonicalize_hostname(strdup(args[LM_MEMBER]));
728       free(args[LM_MEMBER]);
729       args[LM_MEMBER] = canon;
730     }
731
732   if ((status = do_mr_query("add_member_to_list", CountArgs(args), args,
733                             NULL, NULL)) != MR_SUCCESS)
734     {
735       if (status == MR_EXISTS)
736         {
737           sprintf(temp_buf, "The %s %s is already a member of LIST %s.",
738                   args[LM_TYPE], args[LM_MEMBER], args[LM_LIST]);
739           Put_message(temp_buf);
740         }
741       else
742         com_err(program_name, status, " in AddMember");
743     }
744
745   FreeInfo(args);
746   return DM_NORMAL;
747 }
748
749 /*      Function Name: DeleteMember
750  *      Description: This function deletes a member from a list.
751  *      Arguments: none.
752  *      Returns: DM_NORMAL
753  */
754
755 int DeleteMember(int argc, char **argv)
756 {
757   char *args[10];
758   int status;
759
760   if (GetMemberInfo("delete", args) == SUB_ERROR)
761     return DM_NORMAL;
762
763   if (Confirm("Are you sure you want to delete this member?"))
764     {
765       if ((status = do_mr_query("delete_member_from_list", CountArgs(args),
766                                 args, NULL, NULL)))
767         {
768           if ((status == MR_STRING || status == MR_NO_MATCH) &&
769               !strcmp(args[LM_TYPE], "KERBEROS"))
770             {
771               char *canon;
772               mrcl_validate_kerberos_member(args[LM_MEMBER], &canon);
773               if (mrcl_get_message())
774                 {
775                   free(args[LM_MEMBER]);
776                   args[LM_MEMBER] = canon;
777                   if (do_mr_query("delete_member_from_list", CountArgs(args),
778                                   args, NULL, NULL) == MR_SUCCESS)
779                     {
780                       Put_message(mrcl_get_message());
781                       status = MR_SUCCESS;
782                     }
783                 }
784             }
785           else if ((status == MR_MACHINE || status == MR_NO_MATCH) &&
786                    !strcmp(args[LM_TYPE], "MACHINE"))
787             {
788               char *canon;
789               canon = canonicalize_hostname(args[LM_MEMBER]);
790               free(args[LM_MEMBER]);
791               args[LM_MEMBER] = canon;
792               if (do_mr_query("delete_member_from_list", CountArgs(args),
793                               args, NULL, NULL) == MR_SUCCESS)
794                 status = MR_SUCCESS;
795             }
796         }
797       if (status)
798         com_err(program_name, status, " in DeleteMember");
799       else
800         Put_message("Deletion Completed.");
801     }
802   else
803     Put_message("Deletion has been Aborted.");
804
805   FreeInfo(args);
806   return DM_NORMAL;
807 }
808
809 /*      Function Name: TagMember
810  *      Description: Add a tag to a list member
811  *      Arguments:
812  *      Returns: DM_NORMAL
813  */
814
815 int TagMember(int argc, char **argv)
816 {
817   char *args[10];
818   int status;
819
820   if (GetMemberInfo("tag", args) == SUB_ERROR)
821     return DM_NORMAL;
822
823   args[LM_TAG] = strdup("");
824   if (GetValueFromUser("Tag" , &args[LM_TAG]) == SUB_ERROR)
825     {
826       Put_message("Aborted.");
827       return DM_NORMAL;
828     }
829   args[LM_TAG_END] = NULL;              /* NULL terminate this list. */
830
831   if ((status = do_mr_query("tag_member_of_list", CountArgs(args),
832                             args, NULL, NULL)))
833     com_err(program_name, status, " in TagMember");
834
835   FreeInfo(args);
836   return DM_NORMAL;
837 }
838
839 /*      Function Name: ListAllMembers
840  *      Description: lists all members of the current list.
841  *      Arguments:
842  *      Returns: DM_NORMAL
843  */
844
845 int ListMembersWithTags(int argc, char **argv)
846 {
847   ListMembersByType(NULL, 1);
848   return DM_NORMAL;
849 }
850
851 /*      Function Name: InterRemoveItemFromLists
852  *      Description: This function allows interactive removal of an item
853  *                   (user, string, list) for all list  that it is on.
854  *      Arguments: none.
855  *      Returns: DM_NORMAL.
856  *      NOTES: QueryLoop() does not work here because info does not have
857  *             enough information in it to delete the member from the list.
858  */
859
860 int InterRemoveItemFromLists(int argc, char **argv)
861 {
862   int status;
863   char *type, *name, *args[10], buf[BUFSIZ];
864   struct mqelem *top, *elem;
865
866   type = strdup("USER");
867   if (GetTypeFromUser("Type of member", "member", &type) == SUB_ERROR)
868     return DM_NORMAL;
869
870   sprintf(buf, "Name of %s", type);
871   name = strdup(user);
872   if (GetValueFromUser(buf, &name) == SUB_ERROR)
873     return DM_NORMAL;
874
875   if (!ValidName(name))
876     return DM_NORMAL;
877
878   top = elem = GetListInfo(GLOM, type, name);
879
880   while (elem)
881     {
882       char line[BUFSIZ];
883       char **info = elem->q_data;
884       sprintf(line, "Delete %s %s from the list \"%s\" (y/n/q)? ", type,
885               name, info[GLOM_NAME]);
886       switch (YesNoQuitQuestion(line, FALSE))
887         {
888         case TRUE:
889           Put_message("deleting...");
890           args[DM_LIST] = info[GLOM_NAME];
891           args[DM_TYPE] = type;
892           args[DM_MEMBER] = name;
893           if (!strcmp("MACHINE", type))
894               args[DM_MEMBER] = canonicalize_hostname(strdup(name));
895           if ((status = do_mr_query("delete_member_from_list", 3, args,
896                                     NULL, NULL)))
897             {
898               /* should probabally check to delete list. */
899               com_err(program_name, status, " in delete_member");
900             }
901           break;
902         case FALSE:
903           break;
904         default:
905           Put_message("Aborting...");
906           FreeQueue(top);
907           return DM_NORMAL;
908         }
909       elem = elem->q_forw;
910     }
911   FreeQueue(top);
912   return DM_NORMAL;
913 }
914
915 /*-*-* LIST MENU *-*-*/
916
917 /*      Function Name: ListByMember
918  *      Description: This gets all lists that a given member is a member of.
919  *      Arguments: none.
920  *      Returns: DM_NORMAL.
921  */
922
923 int ListByMember(int argc, char **argv)
924 {
925   char buf[BUFSIZ], temp_buf[BUFSIZ], *type, *name, **info;
926   Bool maillist, group, neither;
927   struct mqelem *top, *elem;
928
929   type = strdup("USER");
930   if (GetTypeFromUser("Type of member", "member", &type) == SUB_ERROR)
931     return DM_NORMAL;
932
933   sprintf(buf, "Name of %s", type);
934   name = strdup(user);
935   if (GetValueFromUser(buf, &name) == SUB_ERROR)
936     return DM_NORMAL;
937
938   switch (YesNoQuestion("Do you want a recursive search (y/n)", TRUE))
939     {
940     case TRUE:
941       sprintf(temp_buf, "R%s", type);   /* "USER" to "RUSER" etc. */
942       free(type);
943       type = strdup(temp_buf);
944       break;
945     case FALSE:
946       break;
947     default:
948       return DM_NORMAL;
949     }
950
951   if ((maillist = YesNoQuestion("Show Lists that are Maillists (y/n) ?",
952                                 TRUE)) == -1)
953     return DM_NORMAL;
954   if ((group = YesNoQuestion("Show Lists that are Groups (y/n) ?",
955                              TRUE)) == -1)
956     return DM_NORMAL;
957
958   if ((neither = YesNoQuestion("Show Lists that are neither Maillists nor Groups (y/n) ?",
959                                TRUE)) == -1)
960     return DM_NORMAL;
961
962   elem = top = GetListInfo(GLOM, type, name);
963
964   while (elem)
965     {
966       info = elem->q_data;
967       if ((maillist == TRUE && !strcmp(info[GLOM_MAILLIST], "1")) ||
968           (group == TRUE && !strcmp(info[GLOM_GROUP], "1")))
969         Put_message(info[GLOM_NAME]);
970       if (neither == TRUE && !strcmp(info[GLOM_MAILLIST], "0") &&
971            !strcmp(info[GLOM_GROUP], "0"))
972         Put_message(info[GLOM_NAME]);
973       elem = elem->q_forw;
974     }
975   FreeQueue(top);
976   return DM_NORMAL;
977 }
978
979 /*      Function Name: ListByAdministrator
980  *      Description: This function prints all lists which a given user or
981  *                   group administers.
982  *      Arguments: none.
983  *      Returns: DM_NORMAL.
984  */
985
986 int ListByAdministrator(int argc, char **argv)
987 {
988   char buf[BUFSIZ], temp_buf[BUFSIZ], *type, *name;
989   struct mqelem *top;
990
991   type = strdup("USER");
992   if (GetTypeFromUser("Type of member", "member", &type) == SUB_ERROR)
993     return DM_NORMAL;
994
995   sprintf(buf, "Name of %s", type);
996   name = strdup(user);
997   if (GetValueFromUser(buf, &name) == SUB_ERROR)
998     return DM_NORMAL;
999
1000   switch (YesNoQuestion("Do you want a recursive search (y/n)", FALSE))
1001     {
1002     case TRUE:
1003       sprintf(temp_buf, "R%s", type);   /* "USER" to "RUSER" etc. */
1004       free(type);
1005       type = strdup(temp_buf);
1006       break;
1007     case FALSE:
1008       break;
1009     default:
1010       return DM_NORMAL;
1011     }
1012
1013   top = GetListInfo(ACE_USE, type, name);
1014   Loop(top, PrintListAce);
1015
1016   FreeQueue(top);
1017   return DM_NORMAL;
1018 }
1019
1020 /*      Function Name: ListAllPublicMailLists
1021  *      Description: This function lists all public mailing lists.
1022  *      Arguments: none
1023  *      Returns: DM_NORMAL.
1024  */
1025
1026 int ListAllPublicMailLists(int argc, char **argv)
1027 {
1028   int status;
1029   static char *args[] = {
1030     "TRUE",                     /* active */
1031     "TRUE",                     /* public */
1032     "FALSE",                    /* hidden */
1033     "TRUE",                     /* maillist */
1034     "DONTCARE",                 /* group. */
1035   };
1036
1037   if (YesNoQuestion("This query will take a while. Do you wish to continue?",
1038                     TRUE) == TRUE)
1039     {
1040       if ((status = do_mr_query("qualified_get_lists", 5, args,
1041                                 Print, NULL)) != MR_SUCCESS)
1042         com_err(program_name, status, " in ListAllGroups");
1043     }
1044
1045   return DM_NORMAL;
1046 }
This page took 0.13319 seconds and 3 git commands to generate.