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>
36 #define CTL(ch) ((ch) & 037)
40 #define MAX(A, B) ((A) > (B) ? (A) : (B))
42 char *whoami; /* should not be static, for logging package */
45 typedef struct list_info {
59 static char *ascbuff = {"0123456789"};
60 static List_info *current_li = (List_info *) NULL;
62 typedef struct _menu {
68 MENU *main_menu, *help_menu;
70 int position[2], oldpos[2];
71 int level, found_some, currow, page, num_members;
72 int moreflg, toggle, first_time;
75 void get_main_input(void);
76 void show_list_info(void);
77 void display_buff(char *buf);
78 void start_display_buff(char *buff);
79 void add_member(void);
80 void delete_member(void);
81 void list_by_member(void);
83 static int print_1(int argc, char *argv[], void *callback);
84 static int print_all(int argc, char *argv[], void *callback);
85 void list_all_groups(void);
86 void list_members(void);
87 static int print_2(int argc, char *argv[], void *callback);
88 void start_display(char *buff);
89 void end_display(void);
90 void display_menu(MENU *menu);
91 void pack_main_menu(void);
92 void pack_help_menu(void);
93 void highlight(MENU *menu);
94 void title(char *buff);
95 void center_text(int row, char *buff);
96 void show_text(int row, int col, char *buff);
97 void erase_line(int row, int col);
99 void clrwin(int erase_row);
100 static int fetch_list_info(char *list, List_info *li);
101 static int get_list_info(int argc, char **argv, void *hint);
102 int Prompt(char *prompt, char *buf, int buflen, int crok);
103 void menu_err_hook(const char *who, long code, const char *fmt, va_list args);
105 /* This crock is because the original code was very broken and this makes
106 * it work. Someday, we should abandon the code or fix it right.
108 #define mvcur(oy, ox, ny, nx) move(ny, nx)
110 /****************************************************/
112 int main(int argc, char *argv[])
114 void (*old_hook)(const char *, long, const char *, va_list);
115 int use_menu = 1, k_errno;
116 char buf[BUFSIZ], pname[ANAME_SZ];
118 if ((whoami = strrchr(argv[0], '/')) == NULL)
122 if (!(current_li = malloc(sizeof(List_info))))
124 sprintf(buf, ": allocating list info");
129 current_li->acl_type = NULL;
130 current_li->acl_name = NULL;
131 current_li->desc = NULL;
132 current_li->modtime = NULL;
133 current_li->modby = NULL;
134 current_li->modwith = NULL;
137 if ((k_errno = tf_init(TKT_FILE, R_TKT_FIL)) ||
138 (k_errno = tf_get_pname(pname)))
140 com_err(whoami, k_errno, "reading Kerberos ticket file");
146 printf("Connecting to database for %s...please hold on.\n", username);
148 if (mrcl_connect(NULL, "mailmaint", 2, 1))
152 if ((LINES < 24) || (COLS < 60))
154 display_buff("Display window too small.\n\n");
155 sprintf(buf, "Current window parameters are (%d lines, %d columns)\n",
158 display_buff("Please resize your window\n");
159 display_buff("to at least 24 lines and 60 columns.\n");
164 old_hook = set_com_err_hook(menu_err_hook);
165 position[0] = oldpos[0] = 1;
169 display_menu(main_menu);
173 set_com_err_hook(old_hook);
177 com_err(whoami, status, buf);
181 /****************************************************/
182 void 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 void 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 void 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 void 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 /****************************************************/
380 void add_member(void)
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] = strdup(buf);
391 argv[1] = strdup("user");
392 argv[2] = strdup(username);
393 if ((status = mr_query("add_member_to_list", 3, argv, NULL, 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 void 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] = strdup(buf);
422 argv[1] = strdup("user");
423 argv[2] = strdup(username);
424 if ((status = mr_query("delete_member_from_list", 3, argv, NULL, 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 void list_by_member(void)
447 nargv[1] = strdup("ruser");
448 nargv[2] = strdup(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...");
465 /****************************************************/
470 show_text(DISPROW, STARTCOL, "This function may take a while... proceed? [n] ");
471 c = getchar() & 0x7f;
472 if (c == 'y' || c == 'Y')
474 move(DISPROW + 1, STARTCOL);
475 addstr("Processing query...please hold");
480 erase_line(DISPROW, STARTCOL);
483 /****************************************************/
484 static int print_1(int argc, char *argv[], void *callback)
488 /* no newline 'cause display_buff adds one */
489 sprintf(buf, "%s\n", argv[0]);
495 /****************************************************/
496 static int print_all(int argc, char *argv[], void *callback)
504 erase_line(DISPROW + 1, STARTCOL);
505 show_text(DISPROW + 1, STARTCOL, "All mailing lists:");
508 sprintf(buf, "%s\n", argv[0]);
514 /****************************************************/
515 void list_all_groups(void)
518 argv[0] = argv[1] = argv[3] = "true";
519 argv[4] = "dontcare";
522 if ((status = mr_query("qualified_get_lists", 5, argv, print_all, NULL)))
525 com_err(whoami, status, " in list_all_groups\n");
530 /****************************************************/
531 void list_members(void)
538 move(DISPROW, STARTCOL);
539 mvcur(0, 0, DISPROW, STARTCOL);
541 buf = calloc(LISTMAX, 1);
542 if (Prompt("Enter List Name: ", buf, LISTSIZE, 1) == 1)
544 sprintf(buffer, "The members of list '%s' are:", buf);
545 show_text(DISPROW + 1, STARTCOL, buffer);
547 if ((status = mr_query("get_members_of_list", 1, argv, print_2, NULL)))
550 com_err(whoami, status, " found.\n");
555 show_text(currow, STARTCOL, "List is empty (no members).");
557 show_text(currow, STARTCOL, "Press any key to continue...");
568 /****************************************************/
569 static int print_2(int argc, char *argv[], void *callback)
574 sprintf(buf, "%s %s", argv[0], argv[1]);
580 /****************************************************/
581 void start_display(char *buff)
584 int secondcol; /* where to start the second column of text */
586 secondcol = (COLS / 2); /* 1/2 was accross the screen */
590 buffer = calloc(50, 1);
591 if (currow >= LINES - 2)
594 mvcur(0, 0, currow, STARTCOL);
596 if (Prompt("--RETURN for more, ctl-c to exit--", buffer, 1, 0) == 0)
598 erase_line(currow, STARTCOL);
599 show_text(currow, STARTCOL, "Flushing query...");
604 currow = DISPROW + 2;
605 sprintf(buffer, "Continued (Page %d)", page);
606 show_text(currow, STARTCOL, buffer);
611 show_text(currow, STARTCOL, buff);
614 erase_line(currow, secondcol - 1); /* in case the 1st col is too long */
615 show_text(currow, secondcol, buff);
621 /****************************************************/
622 void end_display(void)
632 buffer = calloc(50, 1);
634 sprintf(buffer, "End of List. %d Total Members\n", num_members - 1);
635 show_text(currow, STARTCOL, buffer);
637 show_text(currow, STARTCOL, "Press any key to continue...");
642 /****************************************************/
643 void display_menu(MENU *menu)
649 mvcur(0, 0, STARTROW, STARTCOL);
651 for (i = 0; i <= menu->num_items - 1; i++)
653 move(STARTROW + i, STARTCOL);
655 addstr(menu->items[i]);
658 center_text(STARTROW + menu->num_items + 2,
659 "Enter a number, <up arrow>, or <down arrow>.");
662 center_text(STARTROW + menu->num_items + 3,
663 "Press 'q' to exit, <return> to confirm choice.");
667 center_text(STARTROW + menu->num_items + 3,
668 "Press 'q' to exit, 'r' for main menu, "
669 "<return> to confirm choice.");
673 highlight(main_menu);
676 /****************************************************/
677 void pack_main_menu(void)
681 main_menu = malloc(sizeof(MENU));
682 main_menu->num_items = 7;
683 main_menu->items = malloc(sizeof(char *) * main_menu->num_items);
686 sprintf(buf, "Mail List Program for %s", username);
687 main_menu->title = strdup(buf);
688 main_menu->items[0] = strdup("1. Show all public mailing lists.");
689 main_menu->items[1] = strdup("2. Get all members of a mailing list.");
690 main_menu->items[2] = strdup("3. Display lists of which you are a member.");
691 main_menu->items[3] = strdup("4. Show description of list.");
692 main_menu->items[4] = strdup("5. Add yourself to a mailing list.");
693 main_menu->items[5] = strdup("6. Delete yourself from a mailing list.");
694 main_menu->items[6] = strdup("q. Quit.");
697 /****************************************************/
698 void pack_help_menu(void)
700 help_menu = malloc(sizeof(MENU));
701 help_menu->num_items = 5;
702 help_menu->items = malloc(sizeof(char *) * help_menu->num_items);
704 help_menu->title = strdup("mailmaint is designed as a basic mail list administration program.");
705 help_menu->items[0] = strdup("if you need to perform more advanced list manipulation like");
706 help_menu->items[1] = strdup("adding lists, or changing list characteristics, refer to the");
707 help_menu->items[2] = strdup("program listmaint.");
708 help_menu->items[3] = strdup(" ");
709 help_menu->items[4] = strdup("Press any key to continue.");
712 /****************************************************/
713 void highlight(MENU *menu)
715 if (oldpos[level] != position[level])
717 move(STARTROW + oldpos[level] - 1, STARTCOL);
719 addstr(menu->items[oldpos[level] - 1]);
723 move(STARTROW + position[level] - 1, STARTCOL);
725 addstr(menu->items[position[level] - 1]);
731 /****************************************************/
732 void title(char *buff)
734 move(0, MAX(0, (COLS - (int)strlen(buff)) >> 1));
741 /****************************************************/
742 void center_text(int row, char *buff)
744 move(row, MAX(0, (COLS - (int)strlen(buff)) >> 1));
749 /****************************************************/
750 void show_text(int row, int col, char *buff)
752 mvcur(0, 0, row, col);
757 /****************************************************/
758 void erase_line(int row, int col)
763 buff = calloc(COLS, 1);
764 for (i = 0; i <= COLS - 2; i++)
766 buff[i] = 0; /* just to be sure ! */
768 mvcur(0, 0, row, col);
771 free(buff); /* close mem. leak */
774 /****************************************************/
781 /****************************************************/
782 void clrwin(int erase_row)
790 buff = calloc(maxcol + 1, 1);
791 for (i = 0; i <= maxcol - 1; i++)
793 buff[i] = 0; /* just to be sure ! */
794 mvcur(0, 0, erase_row, STARTCOL);
796 for (i = erase_row; i <= currow - 1; i++)
799 mvcur(erase_row, STARTCOL, STARTROW + oldpos[level] - 1, STARTCOL);
804 /****************************************************/
805 static int fetch_list_info(char *list, List_info *li)
810 return mr_query("get_list_info", 1, argv, get_list_info, NULL);
813 static int get_list_info(int argc, char **argv, void *hint)
815 if (current_li->acl_type)
816 free(current_li->acl_type);
817 current_li->acl_type = strdup(argv[7]);
818 if (current_li->acl_name)
819 free(current_li->acl_name);
820 current_li->acl_name = strdup(argv[8]);
821 if (current_li->desc)
822 free(current_li->desc);
823 current_li->desc = strdup(argv[9]);
824 if (current_li->modtime)
825 free(current_li->modtime);
826 current_li->modtime = strdup(argv[10]);
827 if (current_li->modby)
828 free(current_li->modby);
829 current_li->modby = strdup(argv[11]);
830 if (current_li->modwith)
831 free(current_li->modwith);
832 current_li->modwith = strdup(argv[12]);
837 /****************************************************/
838 /* Prompt the user for input */
839 int Prompt(char *prompt, char *buf, int buflen, int crok)
846 for (p = buf; abs(strlen(p) - strlen(buf)) <= buflen;)
849 c = getchar() & 0x7f;
858 display_menu(main_menu);
865 if (strlen(buf) < 1) /* only \n or \r in buff */
885 if (abs(strlen(p) - strlen(buf)) >= buflen)
905 * Hook function to cause error messages to be printed through
906 * curses instead of around it.
909 void menu_err_hook(const char *who, long code, const char *fmt, va_list args)
911 char buf[BUFSIZ], *cp;
914 for (cp = buf; *cp; cp++)
920 strcpy(cp, error_message(code));
924 vsprintf(cp, fmt, args);