3 * Simple add-me-to/remove-me-from list client
5 * mailmaint.c - pjlevine - 20 August 1987
7 * Copyright (C) 1988-1998 by the Massachusetts Institute of Technology.
8 * For copying and distribution information, please see the file
12 #include <mit-copyright.h>
14 #include <moira_site.h>
35 #define CTL(ch) ((ch) & 037)
36 #define MAX(A, B) ((A) > (B) ? (A) : (B))
38 char *whoami; /* should not be static, for logging package */
41 typedef struct list_info {
55 static char *ascbuff = {"0123456789"};
56 static List_info *current_li = (List_info *) NULL;
58 typedef struct _menu {
64 MENU *main_menu, *help_menu;
66 int position[2], oldpos[2];
67 int level, found_some, currow, page, num_members;
68 int moreflg, toggle, first_time;
71 void get_main_input(void);
72 void show_list_info(void);
73 void display_buff(char *buf);
74 void start_display_buff(char *buff);
75 void add_member(void);
76 void delete_member(void);
77 void list_by_member(void);
79 static int print_1(int argc, char *argv[], void *callback);
80 static int print_all(int argc, char *argv[], void *callback);
81 void list_all_groups(void);
82 void list_members(void);
83 static int print_2(int argc, char *argv[], void *callback);
84 void start_display(char *buff);
85 void end_display(void);
86 void display_menu(MENU *menu);
87 void pack_main_menu(void);
88 void pack_help_menu(void);
89 void highlight(MENU *menu);
90 void title(char *buff);
91 void center_text(int row, char *buff);
92 void show_text(int row, int col, char *buff);
93 void erase_line(int row, int col);
95 void clrwin(int erase_row);
96 static int fetch_list_info(char *list, List_info *li);
97 static int get_list_info(int argc, char **argv, void *hint);
98 int Prompt(char *prompt, char *buf, int buflen, int crok);
99 void menu_err_hook(const char *who, long code, const char *fmt, va_list args);
101 /* This crock is because the original code was very broken and this makes
102 * it work. Someday, we should abandon the code or fix it right.
104 #define mvcur(oy, ox, ny, nx) move(ny, nx)
106 /****************************************************/
108 int main(int argc, char *argv[])
110 void (*old_hook)(const char *, long, const char *, va_list);
111 int use_menu = 1, k_errno;
112 char buf[BUFSIZ], pname[ANAME_SZ], *motd;
114 if ((whoami = strrchr(argv[0], '/')) == NULL)
118 if (!(current_li = malloc(sizeof(List_info))))
120 sprintf(buf, ": allocating list info");
125 current_li->acl_type = NULL;
126 current_li->acl_name = NULL;
127 current_li->desc = NULL;
128 current_li->modtime = NULL;
129 current_li->modby = NULL;
130 current_li->modwith = NULL;
133 if ((k_errno = tf_init(TKT_FILE, R_TKT_FIL)) ||
134 (k_errno = tf_get_pname(pname)))
136 com_err(whoami, k_errno, "reading Kerberos ticket file");
142 printf("Connecting to database for %s...please hold on.\n", username);
144 status = mr_connect(NULL);
147 sprintf(buf, "\nConnection to Moira server failed");
151 status = mr_motd(&motd);
154 com_err(whoami, status, " unable to check server status");
160 fprintf(stderr, "The Moira server is currently unavailable:\n%s\n",
165 status = mr_auth("mailmaint");
168 sprintf(buf, "\nAuthorization failed.\n");
173 if ((LINES < 24) || (COLS < 60))
175 display_buff("Display window too small.\n\n");
176 sprintf(buf, "Current window parameters are (%d lines, %d columns)\n",
179 display_buff("Please resize your window\n");
180 display_buff("to at least 24 lines and 60 columns.\n");
185 old_hook = set_com_err_hook(menu_err_hook);
186 position[0] = oldpos[0] = 1;
190 display_menu(main_menu);
194 set_com_err_hook(old_hook);
198 com_err(whoami, status, buf);
202 /****************************************************/
203 void get_main_input(void)
210 oldpos[level] = position[level];
212 currow = DISPROW + 2;
214 toggle = num_members = moreflg = 0;
215 c = getchar() & 0x7f; /* mask parity bit */
216 if (c == '\r' || c == '\n')
218 if (position[level] == 7)
221 c = ascbuff[position[level]];
226 case 'L' & 037: /* clear screen */
227 display_menu(main_menu);
232 highlight(main_menu);
239 case '1': /* show all lists */
244 case '2': /* get all members of a list */
249 case '3': /* display list which user is a recipient */
254 case '4': /* show description */
259 case '5': /* add to list */
264 case '6': /* delete */
269 case 27: /* escape */
270 c = getchar() & 0x7f;
273 c = getchar() & 0x7f;
274 if (c == 65) /* up arrow */
277 if (!position[level])
282 if (c == 66) /* down arrow */
285 if (position[level] > 7)
295 highlight(main_menu);
299 /****************************************************/
300 void show_list_info(void)
304 show_text(DISPROW, STARTCOL, "Show information about a list.\n");
305 buf = calloc(1024, 1);
306 if (Prompt("Enter List Name: ", buf, LISTSIZE, 1) == 1)
309 if (fetch_list_info(buf, current_li) == 0)
311 sprintf(buf, "Description: %s\n", current_li->desc);
312 if (strlen(buf) > 60)
315 show_text(currow, STARTCOL, buf);
317 sprintf(buf, "List Administrator: %s %s",
318 current_li->acl_type, current_li->acl_name);
319 show_text(currow, STARTCOL, buf);
321 sprintf(buf, "Modified on %s by user %s with %s",
322 current_li->modtime, current_li->modby,
323 current_li->modwith);
324 show_text(currow, STARTCOL, buf);
329 show_text(currow, STARTCOL, "mailmaint: No such list found.");
332 show_text(currow, STARTCOL, "Press any Key to continue...");
338 /****************************************************/
339 void display_buff(char *buf)
348 printbuf = calloc(maxcol, 1);
349 for (i = 0; i <= strlen(buf); i++)
351 printbuf[cnt] = buf[i];
355 start_display_buff(printbuf);
358 printbuf = calloc(maxcol, 1);
361 if (strlen(buf) % maxcol != 0)
363 start_display_buff(printbuf);
369 /****************************************************/
370 void start_display_buff(char *buff)
377 if (currow >= LINES - 2)
381 mvcur(0, 0, currow, STARTCOL);
383 if (Prompt("--RETURN for more, ctl-c to exit--", buffer, 1, 0) == 0)
385 erase_line(currow, STARTCOL);
386 show_text(currow, STARTCOL, "Flushing query...");
391 currow = DISPROW + 2;
392 show_text(currow, STARTCOL, "continued");
395 show_text(currow, STARTCOL, buff);
400 /****************************************************/
401 void add_member(void)
406 show_text(DISPROW, STARTCOL, "Add yourself to a list\n");
407 buf = calloc(LISTMAX, 1);
408 if (Prompt("Enter List Name: ", buf, LISTSIZE, 1) == 1)
411 argv[0] = strdup(buf);
412 argv[1] = strdup("user");
413 argv[2] = strdup(username);
414 if ((status = mr_query("add_member_to_list", 3, argv, NULL, NULL)))
417 com_err(whoami, status, " found.\n");
421 sprintf(buf, "User %s added to list\n", username);
422 show_text(DISPROW + 3, STARTCOL, buf);
424 currow = DISPROW + 4;
425 show_text(DISPROW + 4, STARTCOL, "Press any Key to continue...");
431 /****************************************************/
432 void delete_member(void)
437 show_text(DISPROW, STARTCOL, "Remove yourself from a list\n");
438 buf = calloc(LISTMAX, 1);
439 if (Prompt("Enter List Name: ", buf, LISTSIZE, 1) == 1)
442 argv[0] = strdup(buf);
443 argv[1] = strdup("user");
444 argv[2] = strdup(username);
445 if ((status = mr_query("delete_member_from_list", 3, argv, NULL, NULL)))
448 com_err(whoami, status, " found.\n");
452 sprintf(buf, "User %s deleted from list\n", username);
453 show_text(DISPROW + 3, STARTCOL, buf);
455 currow = DISPROW + 4;
456 show_text(DISPROW + 4, STARTCOL, "Press any Key to continue...");
462 /****************************************************/
463 void list_by_member(void)
468 nargv[1] = strdup("ruser");
469 nargv[2] = strdup(username);
470 buf = calloc(BUFSIZ, 1);
471 sprintf(buf, "%s is on the following lists:\n", username);
472 show_text(DISPROW, STARTCOL, buf);
473 mvcur(0, 0, currow, STARTCOL);
475 if ((status = mr_query("get_lists_of_member", 2, nargv + 1, print_1, NULL)))
478 com_err(whoami, status, " in get_lists_of_member");
481 show_text(currow, STARTCOL, "Press any Key to continue...");
486 /****************************************************/
491 show_text(DISPROW, STARTCOL, "This function may take a while... proceed? [n] ");
492 c = getchar() & 0x7f;
493 if (c == 'y' || c == 'Y')
495 move(DISPROW + 1, STARTCOL);
496 addstr("Processing query...please hold");
501 erase_line(DISPROW, STARTCOL);
504 /****************************************************/
505 static int print_1(int argc, char *argv[], void *callback)
509 /* no newline 'cause display_buff adds one */
510 sprintf(buf, "%s\n", argv[0]);
516 /****************************************************/
517 static int print_all(int argc, char *argv[], void *callback)
525 erase_line(DISPROW + 1, STARTCOL);
526 show_text(DISPROW + 1, STARTCOL, "All mailing lists:");
529 sprintf(buf, "%s\n", argv[0]);
535 /****************************************************/
536 void list_all_groups(void)
539 argv[0] = argv[1] = argv[3] = "true";
540 argv[4] = "dontcare";
543 if ((status = mr_query("qualified_get_lists", 5, argv, print_all, NULL)))
546 com_err(whoami, status, " in list_all_groups\n");
551 /****************************************************/
552 void list_members(void)
559 move(DISPROW, STARTCOL);
560 mvcur(0, 0, DISPROW, STARTCOL);
562 buf = calloc(LISTMAX, 1);
563 if (Prompt("Enter List Name: ", buf, LISTSIZE, 1) == 1)
565 sprintf(buffer, "The members of list '%s' are:", buf);
566 show_text(DISPROW + 1, STARTCOL, buffer);
568 if ((status = mr_query("get_members_of_list", 1, argv, print_2, NULL)))
571 com_err(whoami, status, " found.\n");
576 show_text(currow, STARTCOL, "List is empty (no members).");
578 show_text(currow, STARTCOL, "Press any key to continue...");
589 /****************************************************/
590 static int print_2(int argc, char *argv[], void *callback)
595 sprintf(buf, "%s %s", argv[0], argv[1]);
601 /****************************************************/
602 void start_display(char *buff)
605 int secondcol; /* where to start the second column of text */
607 secondcol = (COLS / 2); /* 1/2 was accross the screen */
611 buffer = calloc(50, 1);
612 if (currow >= LINES - 2)
615 mvcur(0, 0, currow, STARTCOL);
617 if (Prompt("--RETURN for more, ctl-c to exit--", buffer, 1, 0) == 0)
619 erase_line(currow, STARTCOL);
620 show_text(currow, STARTCOL, "Flushing query...");
625 currow = DISPROW + 2;
626 sprintf(buffer, "Continued (Page %d)", page);
627 show_text(currow, STARTCOL, buffer);
632 show_text(currow, STARTCOL, buff);
635 erase_line(currow, secondcol - 1); /* in case the 1st col is too long */
636 show_text(currow, secondcol, buff);
642 /****************************************************/
643 void end_display(void)
653 buffer = calloc(50, 1);
655 sprintf(buffer, "End of List. %d Total Members\n", num_members - 1);
656 show_text(currow, STARTCOL, buffer);
658 show_text(currow, STARTCOL, "Press any key to continue...");
663 /****************************************************/
664 void display_menu(MENU *menu)
670 mvcur(0, 0, STARTROW, STARTCOL);
672 for (i = 0; i <= menu->num_items - 1; i++)
674 move(STARTROW + i, STARTCOL);
676 addstr(menu->items[i]);
679 center_text(STARTROW + menu->num_items + 2,
680 "Enter a number, <up arrow>, or <down arrow>.");
683 center_text(STARTROW + menu->num_items + 3,
684 "Press 'q' to exit, <return> to confirm choice.");
688 center_text(STARTROW + menu->num_items + 3,
689 "Press 'q' to exit, 'r' for main menu, "
690 "<return> to confirm choice.");
694 highlight(main_menu);
697 /****************************************************/
698 void pack_main_menu(void)
702 main_menu = malloc(sizeof(MENU));
703 main_menu->num_items = 7;
704 main_menu->items = malloc(sizeof(char *) * main_menu->num_items);
707 sprintf(buf, "Mail List Program for %s", username);
708 main_menu->title = strdup(buf);
709 main_menu->items[0] = strdup("1. Show all public mailing lists.");
710 main_menu->items[1] = strdup("2. Get all members of a mailing list.");
711 main_menu->items[2] = strdup("3. Display lists of which you are a member.");
712 main_menu->items[3] = strdup("4. Show description of list.");
713 main_menu->items[4] = strdup("5. Add yourself to a mailing list.");
714 main_menu->items[5] = strdup("6. Delete yourself from a mailing list.");
715 main_menu->items[6] = strdup("q. Quit.");
718 /****************************************************/
719 void pack_help_menu(void)
721 help_menu = malloc(sizeof(MENU));
722 help_menu->num_items = 5;
723 help_menu->items = malloc(sizeof(char *) * help_menu->num_items);
725 help_menu->title = strdup("mailmaint is designed as a basic mail list administration program.");
726 help_menu->items[0] = strdup("if you need to perform more advanced list manipulation like");
727 help_menu->items[1] = strdup("adding lists, or changing list characteristics, refer to the");
728 help_menu->items[2] = strdup("program listmaint.");
729 help_menu->items[3] = strdup(" ");
730 help_menu->items[4] = strdup("Press any key to continue.");
733 /****************************************************/
734 void highlight(MENU *menu)
736 if (oldpos[level] != position[level])
738 move(STARTROW + oldpos[level] - 1, STARTCOL);
740 addstr(menu->items[oldpos[level] - 1]);
744 move(STARTROW + position[level] - 1, STARTCOL);
746 addstr(menu->items[position[level] - 1]);
752 /****************************************************/
753 void title(char *buff)
755 move(0, MAX(0, (COLS - strlen(buff)) >> 1));
762 /****************************************************/
763 void center_text(int row, char *buff)
765 move(row, MAX(0, (COLS - strlen(buff)) >> 1));
770 /****************************************************/
771 void show_text(int row, int col, char *buff)
773 mvcur(0, 0, row, col);
778 /****************************************************/
779 void erase_line(int row, int col)
784 buff = calloc(COLS, 1);
785 for (i = 0; i <= COLS - 2; i++)
787 buff[i] = 0; /* just to be sure ! */
789 mvcur(0, 0, row, col);
792 free(buff); /* close mem. leak */
795 /****************************************************/
802 /****************************************************/
803 void clrwin(int erase_row)
811 buff = calloc(maxcol + 1, 1);
812 for (i = 0; i <= maxcol - 1; i++)
814 buff[i] = 0; /* just to be sure ! */
815 mvcur(0, 0, erase_row, STARTCOL);
817 for (i = erase_row; i <= currow - 1; i++)
820 mvcur(erase_row, STARTCOL, STARTROW + oldpos[level] - 1, STARTCOL);
825 /****************************************************/
826 static int fetch_list_info(char *list, List_info *li)
831 return mr_query("get_list_info", 1, argv, get_list_info, NULL);
834 static int get_list_info(int argc, char **argv, void *hint)
836 if (current_li->acl_type)
837 free(current_li->acl_type);
838 current_li->acl_type = strdup(argv[7]);
839 if (current_li->acl_name)
840 free(current_li->acl_name);
841 current_li->acl_name = strdup(argv[8]);
842 if (current_li->desc)
843 free(current_li->desc);
844 current_li->desc = strdup(argv[9]);
845 if (current_li->modtime)
846 free(current_li->modtime);
847 current_li->modtime = strdup(argv[10]);
848 if (current_li->modby)
849 free(current_li->modby);
850 current_li->modby = strdup(argv[11]);
851 if (current_li->modwith)
852 free(current_li->modwith);
853 current_li->modwith = strdup(argv[12]);
858 /****************************************************/
859 /* Prompt the user for input */
860 int Prompt(char *prompt, char *buf, int buflen, int crok)
867 for (p = buf; abs(strlen(p) - strlen(buf)) <= buflen;)
870 c = getchar() & 0x7f;
879 display_menu(main_menu);
886 if (strlen(buf) < 1) /* only \n or \r in buff */
906 if (abs(strlen(p) - strlen(buf)) >= buflen)
926 * Hook function to cause error messages to be printed through
927 * curses instead of around it.
930 void menu_err_hook(const char *who, long code, const char *fmt, va_list args)
932 char buf[BUFSIZ], *cp;
935 for (cp = buf; *cp; cp++)
941 strcpy(cp, error_message(code));
945 vsprintf(cp, fmt, args);