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)
39 #define MAX(A, B) ((A) > (B) ? (A) : (B))
41 char *whoami; /* should not be static, for logging package */
44 typedef struct list_info {
58 static char *ascbuff = {"0123456789"};
59 static List_info *current_li = (List_info *) NULL;
61 typedef struct _menu {
67 MENU *main_menu, *help_menu;
69 int position[2], oldpos[2];
70 int level, found_some, currow, page, num_members;
71 int moreflg, toggle, first_time;
74 void get_main_input(void);
75 void show_list_info(void);
76 void display_buff(char *buf);
77 void start_display_buff(char *buff);
78 void add_member(void);
79 void delete_member(void);
80 void list_by_member(void);
82 static int print_1(int argc, char *argv[], void *callback);
83 static int print_all(int argc, char *argv[], void *callback);
84 void list_all_groups(void);
85 void list_members(void);
86 static int print_2(int argc, char *argv[], void *callback);
87 void start_display(char *buff);
88 void end_display(void);
89 void display_menu(MENU *menu);
90 void pack_main_menu(void);
91 void pack_help_menu(void);
92 void highlight(MENU *menu);
93 void title(char *buff);
94 void center_text(int row, char *buff);
95 void show_text(int row, int col, char *buff);
96 void erase_line(int row, int col);
98 void clrwin(int erase_row);
99 static int fetch_list_info(char *list, List_info *li);
100 static int get_list_info(int argc, char **argv, void *hint);
101 int Prompt(char *prompt, char *buf, int buflen, int crok);
102 void menu_err_hook(const char *who, long code, const char *fmt, va_list args);
104 /* This crock is because the original code was very broken and this makes
105 * it work. Someday, we should abandon the code or fix it right.
107 #define mvcur(oy, ox, ny, nx) move(ny, nx)
109 /****************************************************/
111 int main(int argc, char *argv[])
113 void (*old_hook)(const char *, long, const char *, va_list);
114 int use_menu = 1, k_errno;
115 char buf[BUFSIZ], pname[ANAME_SZ], *motd;
117 if ((whoami = strrchr(argv[0], '/')) == NULL)
121 if (!(current_li = malloc(sizeof(List_info))))
123 sprintf(buf, ": allocating list info");
128 current_li->acl_type = NULL;
129 current_li->acl_name = NULL;
130 current_li->desc = NULL;
131 current_li->modtime = NULL;
132 current_li->modby = NULL;
133 current_li->modwith = NULL;
136 if ((k_errno = tf_init(TKT_FILE, R_TKT_FIL)) ||
137 (k_errno = tf_get_pname(pname)))
139 com_err(whoami, k_errno, "reading Kerberos ticket file");
145 printf("Connecting to database for %s...please hold on.\n", username);
147 status = mr_connect(NULL);
150 sprintf(buf, "\nConnection to Moira server failed");
154 status = mr_motd(&motd);
157 com_err(whoami, status, " unable to check server status");
163 fprintf(stderr, "The Moira server is currently unavailable:\n%s\n",
168 status = mr_auth("mailmaint");
171 sprintf(buf, "\nAuthorization failed.\n");
176 if ((LINES < 24) || (COLS < 60))
178 display_buff("Display window too small.\n\n");
179 sprintf(buf, "Current window parameters are (%d lines, %d columns)\n",
182 display_buff("Please resize your window\n");
183 display_buff("to at least 24 lines and 60 columns.\n");
188 old_hook = set_com_err_hook(menu_err_hook);
189 position[0] = oldpos[0] = 1;
193 display_menu(main_menu);
197 set_com_err_hook(old_hook);
201 com_err(whoami, status, buf);
205 /****************************************************/
206 void get_main_input(void)
213 oldpos[level] = position[level];
215 currow = DISPROW + 2;
217 toggle = num_members = moreflg = 0;
218 c = getchar() & 0x7f; /* mask parity bit */
219 if (c == '\r' || c == '\n')
221 if (position[level] == 7)
224 c = ascbuff[position[level]];
229 case 'L' & 037: /* clear screen */
230 display_menu(main_menu);
235 highlight(main_menu);
242 case '1': /* show all lists */
247 case '2': /* get all members of a list */
252 case '3': /* display list which user is a recipient */
257 case '4': /* show description */
262 case '5': /* add to list */
267 case '6': /* delete */
272 case 27: /* escape */
273 c = getchar() & 0x7f;
276 c = getchar() & 0x7f;
277 if (c == 65) /* up arrow */
280 if (!position[level])
285 if (c == 66) /* down arrow */
288 if (position[level] > 7)
298 highlight(main_menu);
302 /****************************************************/
303 void show_list_info(void)
307 show_text(DISPROW, STARTCOL, "Show information about a list.\n");
308 buf = calloc(1024, 1);
309 if (Prompt("Enter List Name: ", buf, LISTSIZE, 1) == 1)
312 if (fetch_list_info(buf, current_li) == 0)
314 sprintf(buf, "Description: %s\n", current_li->desc);
315 if (strlen(buf) > 60)
318 show_text(currow, STARTCOL, buf);
320 sprintf(buf, "List Administrator: %s %s",
321 current_li->acl_type, current_li->acl_name);
322 show_text(currow, STARTCOL, buf);
324 sprintf(buf, "Modified on %s by user %s with %s",
325 current_li->modtime, current_li->modby,
326 current_li->modwith);
327 show_text(currow, STARTCOL, buf);
332 show_text(currow, STARTCOL, "mailmaint: No such list found.");
335 show_text(currow, STARTCOL, "Press any Key to continue...");
341 /****************************************************/
342 void display_buff(char *buf)
351 printbuf = calloc(maxcol, 1);
352 for (i = 0; i <= strlen(buf); i++)
354 printbuf[cnt] = buf[i];
358 start_display_buff(printbuf);
361 printbuf = calloc(maxcol, 1);
364 if (strlen(buf) % maxcol != 0)
366 start_display_buff(printbuf);
372 /****************************************************/
373 void start_display_buff(char *buff)
380 if (currow >= LINES - 2)
384 mvcur(0, 0, currow, STARTCOL);
386 if (Prompt("--RETURN for more, ctl-c to exit--", buffer, 1, 0) == 0)
388 erase_line(currow, STARTCOL);
389 show_text(currow, STARTCOL, "Flushing query...");
394 currow = DISPROW + 2;
395 show_text(currow, STARTCOL, "continued");
398 show_text(currow, STARTCOL, buff);
403 /****************************************************/
404 void add_member(void)
409 show_text(DISPROW, STARTCOL, "Add yourself to a list\n");
410 buf = calloc(LISTMAX, 1);
411 if (Prompt("Enter List Name: ", buf, LISTSIZE, 1) == 1)
414 argv[0] = strdup(buf);
415 argv[1] = strdup("user");
416 argv[2] = strdup(username);
417 if ((status = mr_query("add_member_to_list", 3, argv, NULL, NULL)))
420 com_err(whoami, status, " found.\n");
424 sprintf(buf, "User %s added to list\n", username);
425 show_text(DISPROW + 3, STARTCOL, buf);
427 currow = DISPROW + 4;
428 show_text(DISPROW + 4, STARTCOL, "Press any Key to continue...");
434 /****************************************************/
435 void delete_member(void)
440 show_text(DISPROW, STARTCOL, "Remove yourself from a list\n");
441 buf = calloc(LISTMAX, 1);
442 if (Prompt("Enter List Name: ", buf, LISTSIZE, 1) == 1)
445 argv[0] = strdup(buf);
446 argv[1] = strdup("user");
447 argv[2] = strdup(username);
448 if ((status = mr_query("delete_member_from_list", 3, argv, NULL, NULL)))
451 com_err(whoami, status, " found.\n");
455 sprintf(buf, "User %s deleted from list\n", username);
456 show_text(DISPROW + 3, STARTCOL, buf);
458 currow = DISPROW + 4;
459 show_text(DISPROW + 4, STARTCOL, "Press any Key to continue...");
465 /****************************************************/
466 void list_by_member(void)
471 nargv[1] = strdup("ruser");
472 nargv[2] = strdup(username);
473 buf = calloc(BUFSIZ, 1);
474 sprintf(buf, "%s is on the following lists:\n", username);
475 show_text(DISPROW, STARTCOL, buf);
476 mvcur(0, 0, currow, STARTCOL);
478 if ((status = mr_query("get_lists_of_member", 2, nargv + 1, print_1, NULL)))
481 com_err(whoami, status, " in get_lists_of_member");
484 show_text(currow, STARTCOL, "Press any Key to continue...");
489 /****************************************************/
494 show_text(DISPROW, STARTCOL, "This function may take a while... proceed? [n] ");
495 c = getchar() & 0x7f;
496 if (c == 'y' || c == 'Y')
498 move(DISPROW + 1, STARTCOL);
499 addstr("Processing query...please hold");
504 erase_line(DISPROW, STARTCOL);
507 /****************************************************/
508 static int print_1(int argc, char *argv[], void *callback)
512 /* no newline 'cause display_buff adds one */
513 sprintf(buf, "%s\n", argv[0]);
519 /****************************************************/
520 static int print_all(int argc, char *argv[], void *callback)
528 erase_line(DISPROW + 1, STARTCOL);
529 show_text(DISPROW + 1, STARTCOL, "All mailing lists:");
532 sprintf(buf, "%s\n", argv[0]);
538 /****************************************************/
539 void list_all_groups(void)
542 argv[0] = argv[1] = argv[3] = "true";
543 argv[4] = "dontcare";
546 if ((status = mr_query("qualified_get_lists", 5, argv, print_all, NULL)))
549 com_err(whoami, status, " in list_all_groups\n");
554 /****************************************************/
555 void list_members(void)
562 move(DISPROW, STARTCOL);
563 mvcur(0, 0, DISPROW, STARTCOL);
565 buf = calloc(LISTMAX, 1);
566 if (Prompt("Enter List Name: ", buf, LISTSIZE, 1) == 1)
568 sprintf(buffer, "The members of list '%s' are:", buf);
569 show_text(DISPROW + 1, STARTCOL, buffer);
571 if ((status = mr_query("get_members_of_list", 1, argv, print_2, NULL)))
574 com_err(whoami, status, " found.\n");
579 show_text(currow, STARTCOL, "List is empty (no members).");
581 show_text(currow, STARTCOL, "Press any key to continue...");
592 /****************************************************/
593 static int print_2(int argc, char *argv[], void *callback)
598 sprintf(buf, "%s %s", argv[0], argv[1]);
604 /****************************************************/
605 void start_display(char *buff)
608 int secondcol; /* where to start the second column of text */
610 secondcol = (COLS / 2); /* 1/2 was accross the screen */
614 buffer = calloc(50, 1);
615 if (currow >= LINES - 2)
618 mvcur(0, 0, currow, STARTCOL);
620 if (Prompt("--RETURN for more, ctl-c to exit--", buffer, 1, 0) == 0)
622 erase_line(currow, STARTCOL);
623 show_text(currow, STARTCOL, "Flushing query...");
628 currow = DISPROW + 2;
629 sprintf(buffer, "Continued (Page %d)", page);
630 show_text(currow, STARTCOL, buffer);
635 show_text(currow, STARTCOL, buff);
638 erase_line(currow, secondcol - 1); /* in case the 1st col is too long */
639 show_text(currow, secondcol, buff);
645 /****************************************************/
646 void end_display(void)
656 buffer = calloc(50, 1);
658 sprintf(buffer, "End of List. %d Total Members\n", num_members - 1);
659 show_text(currow, STARTCOL, buffer);
661 show_text(currow, STARTCOL, "Press any key to continue...");
666 /****************************************************/
667 void display_menu(MENU *menu)
673 mvcur(0, 0, STARTROW, STARTCOL);
675 for (i = 0; i <= menu->num_items - 1; i++)
677 move(STARTROW + i, STARTCOL);
679 addstr(menu->items[i]);
682 center_text(STARTROW + menu->num_items + 2,
683 "Enter a number, <up arrow>, or <down arrow>.");
686 center_text(STARTROW + menu->num_items + 3,
687 "Press 'q' to exit, <return> to confirm choice.");
691 center_text(STARTROW + menu->num_items + 3,
692 "Press 'q' to exit, 'r' for main menu, "
693 "<return> to confirm choice.");
697 highlight(main_menu);
700 /****************************************************/
701 void pack_main_menu(void)
705 main_menu = malloc(sizeof(MENU));
706 main_menu->num_items = 7;
707 main_menu->items = malloc(sizeof(char *) * main_menu->num_items);
710 sprintf(buf, "Mail List Program for %s", username);
711 main_menu->title = strdup(buf);
712 main_menu->items[0] = strdup("1. Show all public mailing lists.");
713 main_menu->items[1] = strdup("2. Get all members of a mailing list.");
714 main_menu->items[2] = strdup("3. Display lists of which you are a member.");
715 main_menu->items[3] = strdup("4. Show description of list.");
716 main_menu->items[4] = strdup("5. Add yourself to a mailing list.");
717 main_menu->items[5] = strdup("6. Delete yourself from a mailing list.");
718 main_menu->items[6] = strdup("q. Quit.");
721 /****************************************************/
722 void pack_help_menu(void)
724 help_menu = malloc(sizeof(MENU));
725 help_menu->num_items = 5;
726 help_menu->items = malloc(sizeof(char *) * help_menu->num_items);
728 help_menu->title = strdup("mailmaint is designed as a basic mail list administration program.");
729 help_menu->items[0] = strdup("if you need to perform more advanced list manipulation like");
730 help_menu->items[1] = strdup("adding lists, or changing list characteristics, refer to the");
731 help_menu->items[2] = strdup("program listmaint.");
732 help_menu->items[3] = strdup(" ");
733 help_menu->items[4] = strdup("Press any key to continue.");
736 /****************************************************/
737 void highlight(MENU *menu)
739 if (oldpos[level] != position[level])
741 move(STARTROW + oldpos[level] - 1, STARTCOL);
743 addstr(menu->items[oldpos[level] - 1]);
747 move(STARTROW + position[level] - 1, STARTCOL);
749 addstr(menu->items[position[level] - 1]);
755 /****************************************************/
756 void title(char *buff)
758 move(0, MAX(0, (COLS - (int)strlen(buff)) >> 1));
765 /****************************************************/
766 void center_text(int row, char *buff)
768 move(row, MAX(0, (COLS - (int)strlen(buff)) >> 1));
773 /****************************************************/
774 void show_text(int row, int col, char *buff)
776 mvcur(0, 0, row, col);
781 /****************************************************/
782 void erase_line(int row, int col)
787 buff = calloc(COLS, 1);
788 for (i = 0; i <= COLS - 2; i++)
790 buff[i] = 0; /* just to be sure ! */
792 mvcur(0, 0, row, col);
795 free(buff); /* close mem. leak */
798 /****************************************************/
805 /****************************************************/
806 void clrwin(int erase_row)
814 buff = calloc(maxcol + 1, 1);
815 for (i = 0; i <= maxcol - 1; i++)
817 buff[i] = 0; /* just to be sure ! */
818 mvcur(0, 0, erase_row, STARTCOL);
820 for (i = erase_row; i <= currow - 1; i++)
823 mvcur(erase_row, STARTCOL, STARTROW + oldpos[level] - 1, STARTCOL);
828 /****************************************************/
829 static int fetch_list_info(char *list, List_info *li)
834 return mr_query("get_list_info", 1, argv, get_list_info, NULL);
837 static int get_list_info(int argc, char **argv, void *hint)
839 if (current_li->acl_type)
840 free(current_li->acl_type);
841 current_li->acl_type = strdup(argv[7]);
842 if (current_li->acl_name)
843 free(current_li->acl_name);
844 current_li->acl_name = strdup(argv[8]);
845 if (current_li->desc)
846 free(current_li->desc);
847 current_li->desc = strdup(argv[9]);
848 if (current_li->modtime)
849 free(current_li->modtime);
850 current_li->modtime = strdup(argv[10]);
851 if (current_li->modby)
852 free(current_li->modby);
853 current_li->modby = strdup(argv[11]);
854 if (current_li->modwith)
855 free(current_li->modwith);
856 current_li->modwith = strdup(argv[12]);
861 /****************************************************/
862 /* Prompt the user for input */
863 int Prompt(char *prompt, char *buf, int buflen, int crok)
870 for (p = buf; abs(strlen(p) - strlen(buf)) <= buflen;)
873 c = getchar() & 0x7f;
882 display_menu(main_menu);
889 if (strlen(buf) < 1) /* only \n or \r in buff */
909 if (abs(strlen(p) - strlen(buf)) >= buflen)
929 * Hook function to cause error messages to be printed through
930 * curses instead of around it.
933 void menu_err_hook(const char *who, long code, const char *fmt, va_list args)
935 char buf[BUFSIZ], *cp;
938 for (cp = buf; *cp; cp++)
944 strcpy(cp, error_message(code));
948 vsprintf(cp, fmt, args);