6 /* (c) Copyright 1988 by the Massachusetts Institute of Technology. */
7 /* For copying and distribution information, please see the file */
8 /* <mit-copyright.h>. */
11 static char rcsid_mailmaint_c[] = "$Header$";
14 /***********************************************************************/
15 /* mailmaint.c - pjlevine - 20 August 1987 */
16 /***********************************************************************/
22 #include <sys/types.h>
28 #include <moira_site.h>
29 #include <mit-copyright.h>
37 #define CTL(ch) ((ch) & 037)
38 #define MAX(A, B) ((A) > (B) ? (A) : (B))
40 char *whoami; /* should not be static, for logging package */
43 void menu_err_hook(const char *who, long code, const char *fmt, va_list args);
45 typedef struct list_info {
59 static char *ascbuff = {"0123456789"};
60 static int print_2(), print_1();
61 static List_info *current_li = (List_info *) NULL;
62 static int get_list_info();
63 static int fetch_list_info();
65 typedef struct _menu {
71 MENU *main_menu, *help_menu;
73 int position[2], oldpos[2];
74 int level, found_some, currow, page, num_members;
75 int moreflg, toggle, first_time;
78 /* This crock is because the original code was very broken and this makes
79 * it work. Someday, we should abandon the code or fix it right.
81 #define mvcur(oy, ox, ny, nx) move(ny, nx)
83 /****************************************************/
85 int main(int argc, char *argv[])
87 void (*old_hook)(const char *, long, const char *, va_list);
89 char buf[BUFSIZ], *motd;
91 if ((whoami = strrchr(argv[0], '/')) == NULL)
95 if (!(current_li = malloc(sizeof(List_info))))
97 sprintf(buf, ": allocating list info");
102 current_li->acl_type = NULL;
103 current_li->acl_name = NULL;
104 current_li->desc = NULL;
105 current_li->modtime = NULL;
106 current_li->modby = NULL;
107 current_li->modwith = NULL;
109 if (!(username = getlogin()))
111 struct passwd *getpwuid();
113 username = getpwuid(getuid())->pw_name;
115 username = (username && strlen(username)) ? strsave(username) : "";
117 printf("Connecting to database for %s...please hold on.\n", username);
119 status = mr_connect(NULL);
122 sprintf(buf, "\nConnection to Moira server failed");
126 status = mr_motd(&motd);
129 com_err(whoami, status, " unable to check server status");
135 fprintf(stderr, "The Moira server is currently unavailable:\n%s\n",
140 status = mr_auth("mailmaint");
143 sprintf(buf, "\nAuthorization failed.\n");
150 if ((LINES < 24) || (COLS < 60))
152 display_buff("Display window too small.\n\n");
154 "Current window parameters are (%d lines, %d columns)\n",
157 display_buff("Please resize your window\n");
158 display_buff("to at least 24 lines and 60 columns.\n");
163 old_hook = set_com_err_hook(menu_err_hook);
164 position[0] = oldpos[0] = 1;
168 display_menu(main_menu);
172 set_com_err_hook(old_hook);
177 com_err(whoami, status, buf);
181 /****************************************************/
182 int get_main_input(void)
189 oldpos[level] = position[level];
191 currow = DISPROW + 2;
193 toggle = num_members = moreflg = 0;
194 c = getchar() & 0x7f; /* mask parity bit */
195 if (c == '\r' || c == '\n')
197 if (position[level] == 7)
200 c = ascbuff[position[level]];
205 case 'L' & 037: /* clear screen */
206 display_menu(main_menu);
211 highlight(main_menu);
218 case '1': /* show all lists */
223 case '2': /* get all members of a list */
228 case '3': /* display list which user is a recipient */
233 case '4': /* show description */
238 case '5': /* add to list */
243 case '6': /* delete */
248 case 27: /* escape */
249 c = getchar() & 0x7f;
252 c = getchar() & 0x7f;
253 if (c == 65) /* up arrow */
256 if (!position[level])
261 if (c == 66) /* down arrow */
264 if (position[level] > 7)
274 highlight(main_menu);
278 /****************************************************/
279 int show_list_info(void)
283 show_text(DISPROW, STARTCOL, "Show information about a list.\n");
284 buf = calloc(1024, 1);
285 if (Prompt("Enter List Name: ", buf, LISTSIZE, 1) == 1)
288 if (fetch_list_info(buf, current_li) == 0)
290 sprintf(buf, "Description: %s\n", current_li->desc);
291 if (strlen(buf) > 60)
294 show_text(currow, STARTCOL, buf);
296 sprintf(buf, "List Administrator: %s %s",
297 current_li->acl_type, current_li->acl_name);
298 show_text(currow, STARTCOL, buf);
300 sprintf(buf, "Modified on %s by user %s with %s",
301 current_li->modtime, current_li->modby,
302 current_li->modwith);
303 show_text(currow, STARTCOL, buf);
308 show_text(currow, STARTCOL, "mailmaint: No such list found.");
311 show_text(currow, STARTCOL, "Press any Key to continue...");
317 /****************************************************/
318 int display_buff(char *buf)
327 printbuf = calloc(maxcol, 1);
328 for (i = 0; i <= strlen(buf); i++)
330 printbuf[cnt] = buf[i];
334 start_display_buff(printbuf);
337 printbuf = calloc(maxcol, 1);
340 if (strlen(buf) % maxcol != 0)
342 start_display_buff(printbuf);
348 /****************************************************/
349 int start_display_buff(char *buff)
356 if (currow >= LINES - 2)
360 mvcur(0, 0, currow, STARTCOL);
362 if (Prompt("--RETURN for more, ctl-c to exit--", buffer, 1, 0) == 0)
364 erase_line(currow, STARTCOL);
365 show_text(currow, STARTCOL, "Flushing query...");
370 currow = DISPROW + 2;
371 show_text(currow, STARTCOL, "continued");
374 show_text(currow, STARTCOL, buff);
379 /****************************************************/
385 show_text(DISPROW, STARTCOL, "Add yourself to a list\n");
386 buf = calloc(LISTMAX, 1);
387 if (Prompt("Enter List Name: ", buf, LISTSIZE, 1) == 1)
390 argv[0] = strsave(buf);
391 argv[1] = strsave("user");
392 argv[2] = strsave(username);
393 if ((status = mr_query("add_member_to_list", 3, argv, scream, NULL)))
396 com_err(whoami, status, " found.\n");
400 sprintf(buf, "User %s added to list\n", username);
401 show_text(DISPROW + 3, STARTCOL, buf);
403 currow = DISPROW + 4;
404 show_text(DISPROW + 4, STARTCOL, "Press any Key to continue...");
410 /****************************************************/
411 int delete_member(void)
416 show_text(DISPROW, STARTCOL, "Remove yourself from a list\n");
417 buf = calloc(LISTMAX, 1);
418 if (Prompt("Enter List Name: ", buf, LISTSIZE, 1) == 1)
421 argv[0] = strsave(buf);
422 argv[1] = strsave("user");
423 argv[2] = strsave(username);
424 if ((status = mr_query("delete_member_from_list", 3, argv, scream, NULL)))
427 com_err(whoami, status, " found.\n");
431 sprintf(buf, "User %s deleted from list\n", username);
432 show_text(DISPROW + 3, STARTCOL, buf);
434 currow = DISPROW + 4;
435 show_text(DISPROW + 4, STARTCOL, "Press any Key to continue...");
441 /****************************************************/
442 int list_by_member(void)
447 nargv[1] = strsave("ruser");
448 nargv[2] = strsave(username);
449 buf = calloc(BUFSIZ, 1);
450 sprintf(buf, "%s is on the following lists:\n", username);
451 show_text(DISPROW, STARTCOL, buf);
452 mvcur(0, 0, currow, STARTCOL);
454 if ((status = mr_query("get_lists_of_member", 2, nargv + 1, print_1, NULL)))
457 com_err(whoami, status, " in get_lists_of_member");
460 show_text(currow, STARTCOL, "Press any Key to continue...");
466 /****************************************************/
471 show_text(DISPROW, STARTCOL, "This function may take a while... proceed? [n] ");
472 c = getchar() & 0x7f;
473 if (c == 'y' || c == 'Y')
475 move(DISPROW + 1, STARTCOL);
476 addstr("Processing query...please hold");
481 erase_line(DISPROW, STARTCOL);
485 /****************************************************/
486 static int print_1(int argc, char *argv[], char *callback)
490 /* no newline 'cause display_buff adds one */
491 sprintf(buf, "%s\n", argv[0]);
497 /****************************************************/
498 static int print_all(int argc, char *argv[], char *callback)
506 erase_line(DISPROW + 1, STARTCOL);
507 show_text(DISPROW + 1, STARTCOL, "All mailing lists:");
510 sprintf(buf, "%s\n", argv[0]);
516 /****************************************************/
517 int list_all_groups(void)
520 argv[0] = argv[1] = argv[3] = "true";
521 argv[4] = "dontcare";
524 if ((status = mr_query("qualified_get_lists", 5, argv, print_all, NULL)))
527 com_err(whoami, status, " in list_all_groups\n");
534 /****************************************************/
535 int list_members(void)
542 move(DISPROW, STARTCOL);
543 mvcur(0, 0, DISPROW, STARTCOL);
545 buf = calloc(LISTMAX, 1);
546 if (Prompt("Enter List Name: ", buf, LISTSIZE, 1) == 1)
548 sprintf(buffer, "The members of list '%s' are:", buf);
549 show_text(DISPROW + 1, STARTCOL, buffer);
551 if ((status = mr_query("get_members_of_list", 1, argv, print_2, NULL)))
554 com_err(whoami, status, " found.\n");
559 show_text(currow, STARTCOL, "List is empty (no members).");
561 show_text(currow, STARTCOL, "Press any key to continue...");
573 /****************************************************/
574 static int print_2(int argc, char *argv[], char *callback)
579 sprintf(buf, "%s %s", argv[0], argv[1]);
585 /****************************************************/
586 int start_display(char *buff)
589 int secondcol; /* where to start the second column of text */
591 secondcol = (COLS / 2); /* 1/2 was accross the screen */
595 buffer = calloc(50, 1);
596 if (currow >= LINES - 2)
599 mvcur(0, 0, currow, STARTCOL);
601 if (Prompt("--RETURN for more, ctl-c to exit--", buffer, 1, 0) == 0)
603 erase_line(currow, STARTCOL);
604 show_text(currow, STARTCOL, "Flushing query...");
609 currow = DISPROW + 2;
610 sprintf(buffer, "Continued (Page %d)", page);
611 show_text(currow, STARTCOL, buffer);
616 show_text(currow, STARTCOL, buff);
619 erase_line(currow, secondcol - 1); /* in case the 1st col is too long */
620 show_text(currow, secondcol, buff);
627 /****************************************************/
628 int end_display(void)
638 buffer = calloc(50, 1);
640 sprintf(buffer, "End of List. %d Total Members\n", num_members - 1);
641 show_text(currow, STARTCOL, buffer);
643 show_text(currow, STARTCOL, "Press any key to continue...");
648 /****************************************************/
649 int display_menu(MENU *menu)
655 mvcur(0, 0, STARTROW, STARTCOL);
657 for (i = 0; i <= menu->num_items - 1; i++)
659 move(STARTROW + i, STARTCOL);
661 addstr(menu->items[i]);
664 center_text(STARTROW + menu->num_items + 2,
665 "Enter a number, <up arrow>, or <down arrow>.");
668 center_text(STARTROW + menu->num_items + 3,
669 "Press 'q' to exit, <return> to confirm choice.");
673 center_text(STARTROW + menu->num_items + 3,
674 "Press 'q' to exit, 'r' for main menu, "
675 "<return> to confirm choice.");
679 highlight(main_menu);
682 /****************************************************/
683 int pack_main_menu(void)
687 main_menu = malloc(sizeof(MENU));
688 main_menu->num_items = 7;
689 main_menu->items = malloc(sizeof(char *) * main_menu->num_items);
692 sprintf(buf, "Mail List Program for %s", username);
693 main_menu->title = strsave(buf);
694 main_menu->items[0] = strsave("1. Show all public mailing lists.");
695 main_menu->items[1] = strsave("2. Get all members of a mailing list.");
696 main_menu->items[2] = strsave("3. Display lists of which you are a member.");
697 main_menu->items[3] = strsave("4. Show description of list.");
698 main_menu->items[4] = strsave("5. Add yourself to a mailing list.");
699 main_menu->items[5] = strsave("6. Delete yourself from a mailing list.");
700 main_menu->items[6] = strsave("q. Quit.");
703 /****************************************************/
704 int pack_help_menu(void)
706 help_menu = malloc(sizeof(MENU));
707 help_menu->num_items = 5;
708 help_menu->items = malloc(sizeof(char *) * help_menu->num_items);
710 help_menu->title = strsave("mailmaint is designed as a basic mail list administration program.");
711 help_menu->items[0] = strsave("if you need to perform more advanced list manipulation like");
712 help_menu->items[1] = strsave("adding lists, or changing list characteristics, refer to the");
713 help_menu->items[2] = strsave("program listmaint.");
714 help_menu->items[3] = strsave(" ");
715 help_menu->items[4] = strsave("Press any key to continue.");
718 /****************************************************/
719 int highlight(MENU *menu)
721 if (oldpos[level] != position[level])
723 move(STARTROW + oldpos[level] - 1, STARTCOL);
725 addstr(menu->items[oldpos[level] - 1]);
729 move(STARTROW + position[level] - 1, STARTCOL);
731 addstr(menu->items[position[level] - 1]);
737 /****************************************************/
738 int title(char *buff)
740 move(0, MAX(0, (COLS - strlen(buff)) >> 1));
747 /****************************************************/
748 int center_text(int row, char *buff)
750 move(row, MAX(0, (COLS - strlen(buff)) >> 1));
755 /****************************************************/
756 int show_text(int row, int col, char *buff)
758 mvcur(0, 0, row, col);
763 /****************************************************/
764 int erase_line(int row, int col)
769 buff = calloc(COLS, 1);
770 for (i = 0; i <= COLS - 2; i++)
772 buff[i] = 0; /* just to be sure ! */
774 mvcur(0, 0, row, col);
777 free(buff); /* close mem. leak */
780 /****************************************************/
787 /****************************************************/
788 int clrwin(int erase_row)
796 buff = calloc(maxcol + 1, 1);
797 for (i = 0; i <= maxcol - 1; i++)
799 buff[i] = 0; /* just to be sure ! */
800 mvcur(0, 0, erase_row, STARTCOL);
802 for (i = erase_row; i <= currow - 1; i++)
805 mvcur(erase_row, STARTCOL, STARTROW + oldpos[level] - 1, STARTCOL);
810 /****************************************************/
811 static int scream(void)
813 com_err(whoami, status,
814 "\nA Moira update returned a value -- programmer botch\n");
817 return 0; /* to keep compiler happy */
820 /****************************************************/
821 static int fetch_list_info(char *list, List_info *li)
826 return mr_query("get_list_info", 1, argv, get_list_info, NULL);
829 static int get_list_info(int argc, char **argv)
831 if (current_li->acl_type)
832 free(current_li->acl_type);
833 current_li->acl_type = strsave(argv[7]);
834 if (current_li->acl_name)
835 free(current_li->acl_name);
836 current_li->acl_name = strsave(argv[8]);
837 if (current_li->desc)
838 free(current_li->desc);
839 current_li->desc = strsave(argv[9]);
840 if (current_li->modtime)
841 free(current_li->modtime);
842 current_li->modtime = strsave(argv[10]);
843 if (current_li->modby)
844 free(current_li->modby);
845 current_li->modby = strsave(argv[11]);
846 if (current_li->modwith)
847 free(current_li->modwith);
848 current_li->modwith = strsave(argv[12]);
853 /****************************************************/
854 /* Prompt the user for input */
855 int Prompt(char *prompt, char *buf, int buflen, int crok)
862 for (p = buf; abs(strlen(p) - strlen(buf)) <= buflen;)
865 c = getchar() & 0x7f;
874 display_menu(main_menu);
881 if (strlen(buf) < 1) /* only \n or \r in buff */
901 if (abs(strlen(p) - strlen(buf)) >= buflen)
921 * Hook function to cause error messages to be printed through
922 * curses instead of around it.
925 void menu_err_hook(const char *who, long code, const char *fmt, va_list args)
927 char buf[BUFSIZ], *cp;
930 for (cp = buf; *cp; cp++)
936 strcpy(cp, error_message(code));
940 vsprintf(cp, fmt, args);