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
18 /***********************************************************************/
24 #include <sys/types.h>
29 #include <moira_site.h>
30 #include <mit-copyright.h>
38 #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 extern char *strsave();
46 void menu_err_hook(const char *who, long code, const char *fmt, va_list args);
52 typedef struct list_info {
66 static char *ascbuff = {"0123456789"};
67 static int print_2(), print_1();
68 static List_info *current_li = (List_info *) NULL;
69 static int get_list_info();
70 static int fetch_list_info();
74 extern char *strsave();
80 typedef struct _menu {
86 MENU *main_menu, *help_menu;
88 int position[2], oldpos[2];
89 int level, found_some, currow, page, num_members;
90 int moreflg, toggle, first_time;
93 /* This crock is because the original code was very broken and this makes
94 * it work. Someday, we should abandon the code or fix it right.
96 #define mvcur(oy,ox,ny,nx) move(ny,nx)
98 /****************************************************/
106 void (*old_hook)(const char *, long, const char *, va_list);
111 char buf[BUFSIZ], *motd;
113 if ((whoami = strrchr(argv[0], '/')) == NULL)
117 username = calloc(20, 1);
118 if ((current_li = (List_info *) malloc(sizeof(List_info)))
119 == (List_info *) NULL) {
120 (void) sprintf(buf, ": allocating list info");
124 current_li->acl_type = (char *) NULL;
125 current_li->acl_name = (char *) NULL;
126 current_li->desc = (char *) NULL;
127 current_li->modtime = (char *) NULL;
128 current_li->modby = (char *) NULL;
129 current_li->modwith = (char *) NULL;
131 if ((username = getlogin()) == NULL) {
132 struct passwd *getpwuid();
134 username = getpwuid((int) getuid())->pw_name;
136 username = (username && strlen(username)) ? strsave(username) : "";
138 printf("Connecting to database for %s...please hold on.\n", username);
140 status = mr_connect(NULL);
142 (void) sprintf(buf, "\nConnection to Moira server failed");
146 status = mr_motd(&motd);
148 com_err(whoami, status, " unable to check server status");
153 fprintf(stderr, "The Moira server is currently unavailable:\n%s\n", motd);
157 status = mr_auth("mailmaint");
159 (void) sprintf(buf, "\nAuthorization failed.\n");
165 if ((LINES < 24) || (COLS < 60)) {
166 display_buff("Display window too small.\n\n");
167 (void) sprintf(buf, "Current window parameters are (%d \
168 lines, %d columns)\n", LINES, COLS);
170 display_buff("Please resize your window\n");
171 display_buff("to at least 24 lines and 60 columns.\n");
176 old_hook = set_com_err_hook(menu_err_hook);
177 position[0] = oldpos[0] = 1;
181 display_menu(main_menu);
185 set_com_err_hook(old_hook);
190 com_err(whoami, status, buf);
194 /****************************************************/
201 oldpos[level] = position[level];
203 currow = DISPROW + 2;
205 toggle = num_members = moreflg = 0;
206 c = getchar() & 0x7f; /* mask parity bit */
207 if (c == '\r' || c == '\n') {
208 if (position[level] == 7)
211 c = ascbuff[position[level]];
215 case 'L' & 037: /* clear screen */
216 display_menu(main_menu);
221 highlight(main_menu);
227 case '1': /* show all lists */
233 case '2': /* get all members of a list */
236 (void) list_members();
239 case '3': /* display list which user is a recipient */
245 case '4': /* show description */
251 case '5': /* add to list */
257 case '6': /* delete */
263 case 27: /* up arrow */
264 c = getchar() & 0x7f;
266 c = getchar() & 0x7f;
269 if (!position[level])
275 if (position[level] > 7)
285 highlight(main_menu);
289 /****************************************************/
294 show_text(DISPROW, STARTCOL, "Show information about a list.\n");
295 buf = calloc((unsigned)1024, 1);
296 if (Prompt("Enter List Name: ", buf, LISTSIZE, 1) == 1) {
298 if (fetch_list_info(buf, current_li) == 0) {
299 (void) sprintf(buf, "Description: %s\n", current_li->desc);
300 if (strlen(buf) > 60)
301 (void) display_buff(buf);
303 show_text(currow, STARTCOL, buf);
305 (void) sprintf(buf, "List Administrator: %s %s",
306 current_li->acl_type, current_li->acl_name);
307 show_text(currow, STARTCOL, buf);
309 (void) sprintf(buf, "Modified on %s by user %s with %s",
310 current_li->modtime, current_li->modby,
311 current_li->modwith);
312 show_text(currow, STARTCOL, buf);
316 show_text(currow, STARTCOL, "mailmaint: No such list found.");
319 show_text(currow, STARTCOL, "Press any Key to continue...");
325 /****************************************************/
335 /* I don't understand the point of this limitation. -jweiss 3/25/94
340 printbuf = calloc((unsigned)maxcol, 1);
341 for (i = 0; i <= strlen(buf); i++) {
342 printbuf[cnt] = buf[i];
345 (void) start_display_buff(printbuf);
348 printbuf = calloc((unsigned)maxcol, 1);
351 if (strlen(buf) % maxcol != 0) {
352 (void) start_display_buff(printbuf);
358 /****************************************************/
359 start_display_buff(buff)
367 if (currow >= LINES - 2) {
370 mvcur(0, 0, currow, STARTCOL);
372 if (Prompt("--RETURN for more, ctl-c to exit--", buffer, 1, 0) == 0) {
373 erase_line(currow, STARTCOL);
374 show_text(currow, STARTCOL, "Flushing query...");
379 currow = DISPROW + 2;
380 show_text(currow, STARTCOL, "continued");
383 show_text(currow, STARTCOL, buff);
388 /****************************************************/
394 show_text(DISPROW, STARTCOL, "Add yourself to a list\n");
395 buf = calloc(LISTMAX, 1);
396 if (Prompt("Enter List Name: ", buf, LISTSIZE, 1) == 1) {
398 argv[0] = strsave(buf);
399 argv[1] = strsave("user");
400 argv[2] = strsave(username);
401 if (status = mr_query("add_member_to_list", 3, argv,
402 scream, (char *) NULL)) {
404 com_err(whoami, status, " found.\n");
407 (void) sprintf(buf, "User %s added to list\n", username);
408 show_text(DISPROW + 3, STARTCOL, buf);
410 currow = DISPROW + 4;
411 show_text(DISPROW + 4, STARTCOL, "Press any Key to continue...");
417 /****************************************************/
423 show_text(DISPROW, STARTCOL, "Remove yourself from a list\n");
424 buf = calloc(LISTMAX, 1);
425 if (Prompt("Enter List Name: ", buf, LISTSIZE, 1) == 1) {
427 argv[0] = strsave(buf);
428 argv[1] = strsave("user");
429 argv[2] = strsave(username);
430 if (status = mr_query("delete_member_from_list", 3, argv,
431 scream, (char *) NULL)) {
433 com_err(whoami, status, " found.\n");
436 (void) sprintf(buf, "User %s deleted from list\n", username);
437 show_text(DISPROW + 3, STARTCOL, buf);
439 currow = DISPROW + 4;
440 show_text(DISPROW + 4, STARTCOL, "Press any Key to continue...");
446 /****************************************************/
452 nargv[1] = strsave("ruser");
453 nargv[2] = strsave(username);
454 buf = calloc(BUFSIZ, 1);
455 (void) sprintf(buf, "%s is on the following lists:\n", username);
456 show_text(DISPROW, STARTCOL, buf);
457 mvcur(0, 0, currow, STARTCOL);
459 if (status = mr_query("get_lists_of_member", 2, nargv + 1,
460 print_1, (char *) NULL)) {
462 com_err(whoami, status, " in get_lists_of_member");
465 show_text(currow, STARTCOL, "Press any Key to continue...");
471 /****************************************************/
476 show_text(DISPROW, STARTCOL, "This function may take a \
477 while... proceed? [y] ");
478 c = getchar() & 0x7f;
479 if (c == 'y' || c == 'Y' || c == '\n' || c == '\r') {
480 move(DISPROW + 1, STARTCOL);
481 addstr("Processing query...please hold");
483 (void) list_all_groups();
486 erase_line(DISPROW, STARTCOL);
491 /****************************************************/
494 print_1(argc, argv, callback)
496 char *argv[], *callback;
500 /* no newline 'cause display_buff adds one */
501 (void) sprintf(buf, "%s\n", argv[0]);
502 (void) start_display(buf);
507 /****************************************************/
510 print_all(argc, argv, callback)
512 char *argv[], *callback;
519 erase_line(DISPROW + 1, STARTCOL);
520 show_text(DISPROW + 1, STARTCOL, "All mailing lists:");
523 (void) sprintf(buf, "%s\n", argv[0]);
524 (void) start_display(buf);
529 /****************************************************/
533 argv[0] = argv[1] = argv[3] = "true";
534 argv[4] = "dontcare";
537 if (status = mr_query("qualified_get_lists", 5, argv,
538 print_all, (char *) NULL)) {
540 com_err(whoami, status, " in list_all_groups\n");
547 /****************************************************/
555 move(DISPROW, STARTCOL);
556 mvcur(0, 0, DISPROW, STARTCOL);
558 buf = calloc(LISTMAX, 1);
559 if (Prompt("Enter List Name: ", buf, LISTSIZE, 1) == 1) {
560 (void) sprintf(buffer, "The members of list '%s' are:", buf);
561 show_text(DISPROW + 1, STARTCOL, buffer);
563 if (status = mr_query("get_members_of_list", 1, argv,
564 print_2, (char *) NULL)) {
566 com_err(whoami, status, " found.\n");
570 show_text(currow, STARTCOL, "List is empty (no members).");
572 show_text(currow, STARTCOL, "Press any key to continue...");
584 /****************************************************/
587 print_2(argc, argv, callback)
589 char *argv[], *callback;
594 (void) sprintf(buf, "%s %s", argv[0], argv[1]);
595 (void) start_display(buf);
600 /****************************************************/
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) {
614 mvcur(0, 0, currow, STARTCOL);
616 if (Prompt("--RETURN for more, ctl-c to exit--", buffer, 1, 0) == 0) {
617 erase_line(currow, STARTCOL);
618 show_text(currow, STARTCOL, "Flushing query...");
623 currow = DISPROW + 2;
624 (void) sprintf(buffer, "Continued (Page %d)", page);
625 show_text(currow, STARTCOL, buffer);
630 show_text(currow, STARTCOL, buff);
632 erase_line(currow, secondcol-1); /* in case the 1st col is too long */
633 show_text(currow, secondcol, buff);
640 /****************************************************/
650 buffer = calloc(50, 1);
652 (void) sprintf(buffer, "End of List. %d Total Members\n", num_members - 1);
653 show_text(currow, STARTCOL, buffer);
655 show_text(currow, STARTCOL, "Press any key to continue...");
661 /****************************************************/
669 mvcur(0, 0, STARTROW, STARTCOL);
671 for (i = 0; i <= menu->num_items - 1; i++) {
672 move(STARTROW + i, STARTCOL);
674 addstr(menu->items[i]);
677 center_text(STARTROW + menu->num_items + 2,
678 "Enter a number, <up arrow>, or <down arrow>.");
680 center_text(STARTROW + menu->num_items + 3,
681 "Press 'q' to exit, <return> to confirm choice.");
683 center_text(STARTROW + menu->num_items + 3,
684 "Press 'q' to exit, 'r' for main menu, <return> to confirm choice.");
687 highlight(main_menu);
690 /****************************************************/
695 main_menu = (MENU *) malloc((unsigned) sizeof(MENU));
696 main_menu->num_items = 7;
697 main_menu->items = (char **) malloc((unsigned) sizeof(char *) * main_menu->num_items);
700 (void) sprintf(buf, "Mail List Program for %s", username);
701 main_menu->title = strsave(buf);
702 main_menu->items[0] = strsave("1. Show all public mailing lists.");
703 main_menu->items[1] = strsave("2. Get all members of a mailing list.");
704 main_menu->items[2] = strsave("3. Display lists of which you are a member.");
705 main_menu->items[3] = strsave("4. Show description of list.");
706 main_menu->items[4] = strsave("5. Add yourself to a mailing list.");
707 main_menu->items[5] = strsave("6. Delete yourself from a mailing list.");
708 main_menu->items[6] = strsave("q. Quit.");
711 /****************************************************/
714 help_menu = (MENU *) malloc((unsigned) sizeof(MENU));
715 help_menu->num_items = 5;
716 help_menu->items = (char **) malloc((unsigned) sizeof(char *) * help_menu->num_items);
718 help_menu->title = strsave("mailmaint is designed as a basic mail list administration program.");
719 help_menu->items[0] = strsave("if you need to perform more advanced list manipulation like");
720 help_menu->items[1] = strsave("adding lists, or changing list characteristics, refer to the");
721 help_menu->items[2] = strsave("program listmaint.");
722 help_menu->items[3] = strsave(" ");
723 help_menu->items[4] = strsave("Press any key to continue.");
726 /****************************************************/
732 if (oldpos[level] != position[level]) {
733 move(STARTROW + oldpos[level] - 1, STARTCOL);
735 addstr(menu->items[oldpos[level] - 1]);
739 move(STARTROW + position[level] - 1, STARTCOL);
741 addstr(menu->items[position[level] - 1]);
747 /****************************************************/
751 move(0, MAX(0, (COLS - strlen(buff)) >> 1));
758 /****************************************************/
759 center_text(row, buff)
763 move(row, MAX(0, (COLS - strlen(buff)) >> 1));
768 /****************************************************/
769 show_text(row, col, buff)
773 mvcur(0, 0, row, col);
778 /****************************************************/
785 buff = calloc((unsigned)COLS, 1);
786 for (i = 0; i <= COLS - 2; i++)
788 buff[i] = 0; /* just to be sure ! */
790 mvcur(0, 0, row, col);
793 free(buff); /* close mem. leak */
796 /****************************************************/
803 /****************************************************/
812 /* I don't understand the point of this limitation. -jweiss 3/25/94
813 and I believe it was preventing the window from being cleared properly.
815 maxcol = 80; */ /* limit width */
817 buff = calloc((unsigned)maxcol + 1, 1);
818 for (i = 0; i <= maxcol - 1; i++)
820 buff[i] = 0; /* just to be sure ! */
821 mvcur(0, 0, erase_row, STARTCOL);
823 for (i = erase_row; i <= currow - 1; i++) {
827 mvcur(erase_row, STARTCOL, STARTROW + oldpos[level] - 1, STARTCOL);
829 free (buff); /* fix mem. leak */
832 /****************************************************/
837 com_err(whoami, status, "\nA Moira update returned a value -- programmer \
841 return(0); /* to keep compiler happy */
844 /****************************************************/
847 fetch_list_info(list, li)
854 return mr_query("get_list_info", 1, argv, get_list_info, (char *) NULL);
859 get_list_info(argc, argv)
864 if (current_li->acl_type)
865 free(current_li->acl_type);
866 current_li->acl_type = strsave(argv[7]);
867 if (current_li->acl_name)
868 free(current_li->acl_name);
869 current_li->acl_name = strsave(argv[8]);
870 if (current_li->desc)
871 free(current_li->desc);
872 current_li->desc = strsave(argv[9]);
873 if (current_li->modtime)
874 free(current_li->modtime);
875 current_li->modtime = strsave(argv[10]);
876 if (current_li->modby)
877 free(current_li->modby);
878 current_li->modby = strsave(argv[11]);
879 if (current_li->modwith)
880 free(current_li->modwith);
881 current_li->modwith = strsave(argv[12]);
888 /****************************************************/
889 /* Prompt the user for input */
891 Prompt(prompt, buf, buflen, crok)
902 for (p = buf; abs(strlen(p) - strlen(buf)) <= buflen;) {
904 c = getchar() & 0x7f;
912 display_menu(main_menu);
919 if (strlen(buf) < 1)/* only \n or \r in buff */
938 if (abs(strlen(p) - strlen(buf)) >= buflen) {
947 (void) putchar(CTL('G'));
956 * Hook function to cause error messages to be printed through
957 * curses instead of around it.
961 menu_err_hook(who, code, fmt, args)
967 char buf[BUFSIZ], *cp;
969 (void) strcpy(buf, who);
970 for (cp = buf; *cp; cp++);
974 (void) strcpy(cp, error_message(code));
978 #if defined(AIX386) || defined(sun)
979 vsprintf(cp, fmt, args);
981 /* can do this because we never pass more than 1 arg here anyway... */
982 sprintf(cp, fmt, args);