]>
Commit | Line | Data |
---|---|---|
1 | /* $Id$ | |
2 | * | |
3 | * Simple add-me-to/remove-me-from list client | |
4 | * | |
5 | * mailmaint.c - pjlevine - 20 August 1987 | |
6 | * | |
7 | * Copyright (C) 1988-1998 by the Massachusetts Institute of Technology. | |
8 | * For copying and distribution information, please see the file | |
9 | * <mit-copyright.h>. | |
10 | */ | |
11 | ||
12 | #include <mit-copyright.h> | |
13 | #include <moira.h> | |
14 | #include <moira_site.h> | |
15 | #include <mrclient.h> | |
16 | ||
17 | #include <ctype.h> | |
18 | #ifdef HAVE_CURSES | |
19 | #ifdef _WIN32 | |
20 | #include <conio.h> | |
21 | #ifdef MOUSE_MOVED | |
22 | #undef MOUSE_MOVED | |
23 | #endif | |
24 | #endif /*_WIN32*/ | |
25 | #include <curses.h> | |
26 | #endif | |
27 | #include <stdio.h> | |
28 | #include <stdlib.h> | |
29 | #include <string.h> | |
30 | #ifdef HAVE_UNISTD_H | |
31 | #include <unistd.h> | |
32 | #endif | |
33 | ||
34 | #ifdef _WIN32 | |
35 | #define INPUT_MASK 0xff | |
36 | #ifdef getchar | |
37 | #undef getchar | |
38 | #endif | |
39 | #define getchar() _getch() | |
40 | #ifdef title | |
41 | #undef title | |
42 | #endif | |
43 | static void DELETE_A_CHAR(void) | |
44 | { | |
45 | int x, y; | |
46 | getsyx(&y, &x); | |
47 | x -= 1; | |
48 | mvdelch(y,x); | |
49 | } | |
50 | #else /* !_WIN32 */ | |
51 | #define INPUT_MASK 0x7f | |
52 | #define DELETE_A_CHAR() printf("\b \b"); | |
53 | #endif /* !_WIN32 */ | |
54 | ||
55 | RCSID("$Header$"); | |
56 | ||
57 | #define STARTCOL 0 | |
58 | #define STARTROW 3 | |
59 | #define DISPROW 15 | |
60 | #define LISTMAX 50 | |
61 | #define LISTSIZE 32 | |
62 | #define CTL(ch) ((ch) & 037) | |
63 | #ifdef MAX | |
64 | #undef MAX | |
65 | #endif | |
66 | #define MAX(A, B) ((A) > (B) ? (A) : (B)) | |
67 | ||
68 | char *whoami; /* should not be static, for logging package */ | |
69 | static int status; | |
70 | ||
71 | typedef struct list_info { | |
72 | int active; | |
73 | int public; | |
74 | int hidden; | |
75 | int maillist; | |
76 | int group; | |
77 | char *acl_type; | |
78 | char *acl_name; | |
79 | char *desc; | |
80 | char *modtime; | |
81 | char *modby; | |
82 | char *modwith; | |
83 | } List_info; | |
84 | ||
85 | static char *ascbuff = {"0123456789"}; | |
86 | static List_info *current_li = (List_info *) NULL; | |
87 | ||
88 | typedef struct _menu { | |
89 | int num_items; | |
90 | char *title; | |
91 | char **items; | |
92 | } MENU; | |
93 | ||
94 | MENU *main_menu, *help_menu; | |
95 | ||
96 | int position[2], oldpos[2]; | |
97 | int level, found_some, currow, page, num_members; | |
98 | int moreflg, toggle, first_time; | |
99 | char *username; | |
100 | ||
101 | void get_main_input(void); | |
102 | void show_list_info(void); | |
103 | void display_buff(char *buf); | |
104 | void start_display_buff(char *buff); | |
105 | void add_member(void); | |
106 | void delete_member(void); | |
107 | void list_by_member(void); | |
108 | void show_all(void); | |
109 | static int print_1(int argc, char *argv[], void *callback); | |
110 | static int print_all(int argc, char *argv[], void *callback); | |
111 | void list_all_groups(void); | |
112 | void list_members(void); | |
113 | static int print_2(int argc, char *argv[], void *callback); | |
114 | void start_display(char *buff); | |
115 | void end_display(void); | |
116 | void display_menu(MENU *menu); | |
117 | void pack_main_menu(void); | |
118 | void pack_help_menu(void); | |
119 | void free_menu(MENU* menu); | |
120 | void highlight(MENU *menu); | |
121 | void title(char *buff); | |
122 | void center_text(int row, char *buff); | |
123 | void show_text(int row, int col, char *buff); | |
124 | void erase_line(int row, int col); | |
125 | void cls(void); | |
126 | void clrwin(int erase_row); | |
127 | static int fetch_list_info(char *list, List_info *li); | |
128 | static int get_list_info(int argc, char **argv, void *hint); | |
129 | int Prompt(char *prompt, char *buf, int buflen, int crok); | |
130 | void menu_err_hook(const char *who, long code, const char *fmt, va_list args); | |
131 | ||
132 | /* This crock is because the original code was very broken and this makes | |
133 | * it work. Someday, we should abandon the code or fix it right. | |
134 | */ | |
135 | #define mvcur(oy, ox, ny, nx) move(ny, nx) | |
136 | ||
137 | /****************************************************/ | |
138 | ||
139 | int main(int argc, char *argv[]) | |
140 | { | |
141 | void (*old_hook)(const char *, long, const char *, va_list); | |
142 | int use_menu = 1, k_errno; | |
143 | char buf[BUFSIZ]; | |
144 | ||
145 | if ((whoami = strrchr(argv[0], '/')) == NULL) | |
146 | whoami = argv[0]; | |
147 | else | |
148 | whoami++; | |
149 | if (!(current_li = malloc(sizeof(List_info)))) | |
150 | { | |
151 | sprintf(buf, ": allocating list info"); | |
152 | goto punt; | |
153 | } | |
154 | else | |
155 | { | |
156 | current_li->acl_type = NULL; | |
157 | current_li->acl_name = NULL; | |
158 | current_li->desc = NULL; | |
159 | current_li->modtime = NULL; | |
160 | current_li->modby = NULL; | |
161 | current_li->modwith = NULL; | |
162 | } | |
163 | ||
164 | username = mrcl_krb_user(); | |
165 | if (!username) | |
166 | exit(1); | |
167 | ||
168 | if (mrcl_connect(NULL, "mailmaint", 2, 1)) | |
169 | exit(2); | |
170 | ||
171 | initscr(); | |
172 | if ((LINES < 24) || (COLS < 60)) | |
173 | { | |
174 | display_buff("Display window too small.\n\n"); | |
175 | sprintf(buf, "Current window parameters are (%d lines, %d columns)\n", | |
176 | LINES, COLS); | |
177 | display_buff(buf); | |
178 | display_buff("Please resize your window\n"); | |
179 | display_buff("to at least 24 lines and 60 columns.\n"); | |
180 | exit(0); | |
181 | } | |
182 | ||
183 | raw(); | |
184 | noecho(); | |
185 | old_hook = set_com_err_hook(menu_err_hook); | |
186 | position[0] = oldpos[0] = 1; | |
187 | level = 0; | |
188 | ||
189 | pack_main_menu(); | |
190 | pack_help_menu(); | |
191 | display_menu(main_menu); | |
192 | get_main_input(); | |
193 | cls(); | |
194 | endwin(); | |
195 | set_com_err_hook(old_hook); | |
196 | ||
197 | free_menu(main_menu); | |
198 | free_menu(help_menu); | |
199 | ||
200 | if (current_li->acl_type) | |
201 | free(current_li->acl_type); | |
202 | if (current_li->acl_name) | |
203 | free(current_li->acl_name); | |
204 | if (current_li->desc) | |
205 | free(current_li->desc); | |
206 | if (current_li->modtime) | |
207 | free(current_li->modtime); | |
208 | if (current_li->modby) | |
209 | free(current_li->modby); | |
210 | if (current_li->modwith) | |
211 | free(current_li->modwith); | |
212 | free(current_li); | |
213 | ||
214 | mr_disconnect(); | |
215 | ||
216 | exit(0); | |
217 | ||
218 | punt: | |
219 | com_err(whoami, status, buf); | |
220 | exit(1); | |
221 | } | |
222 | ||
223 | /****************************************************/ | |
224 | void get_main_input(void) | |
225 | { | |
226 | int c; | |
227 | int retflg; | |
228 | ||
229 | while (1) | |
230 | { | |
231 | oldpos[level] = position[level]; | |
232 | retflg = 0; | |
233 | currow = DISPROW + 2; | |
234 | page = 1; | |
235 | toggle = num_members = moreflg = 0; | |
236 | c = getchar() & INPUT_MASK; /* mask parity bit */ | |
237 | if (c == '\r' || c == '\n') | |
238 | { | |
239 | if (position[level] == 7) | |
240 | c = 'q'; | |
241 | else | |
242 | c = ascbuff[position[level]]; | |
243 | retflg = 1; | |
244 | } | |
245 | switch (c) | |
246 | { | |
247 | case 'L' & 037: /* clear screen */ | |
248 | display_menu(main_menu); | |
249 | break; | |
250 | case 'q': | |
251 | case 'Q': /* quit */ | |
252 | position[level] = 7; | |
253 | highlight(main_menu); | |
254 | if (retflg) | |
255 | { | |
256 | cls(); | |
257 | return; | |
258 | } | |
259 | break; | |
260 | case '1': /* show all lists */ | |
261 | position[level] = 1; | |
262 | if (retflg) | |
263 | show_all(); | |
264 | break; | |
265 | case '2': /* get all members of a list */ | |
266 | position[level] = 2; | |
267 | if (retflg) | |
268 | list_members(); | |
269 | break; | |
270 | case '3': /* display list which user is a recipient */ | |
271 | position[level] = 3; | |
272 | if (retflg) | |
273 | list_by_member(); | |
274 | break; | |
275 | case '4': /* show description */ | |
276 | position[level] = 4; | |
277 | if (retflg) | |
278 | show_list_info(); | |
279 | break; | |
280 | case '5': /* add to list */ | |
281 | position[level] = 5; | |
282 | if (retflg) | |
283 | add_member(); | |
284 | break; | |
285 | case '6': /* delete */ | |
286 | position[level] = 6; | |
287 | if (retflg) | |
288 | delete_member(); | |
289 | break; | |
290 | #ifndef _WIN32 | |
291 | case 27: /* escape */ | |
292 | c = getchar() & INPUT_MASK; | |
293 | if (c == 91) | |
294 | { | |
295 | c = getchar() & INPUT_MASK; | |
296 | if (c == 65) /* up arrow */ | |
297 | { | |
298 | position[level]--; | |
299 | if (!position[level]) | |
300 | position[level] = 7; | |
301 | } | |
302 | else | |
303 | { | |
304 | if (c == 66) /* down arrow */ | |
305 | { | |
306 | position[level]++; | |
307 | if (position[level] > 7) | |
308 | position[level] = 1; | |
309 | } | |
310 | } | |
311 | } | |
312 | #else /* _WIN32 */ | |
313 | case 0xe0: | |
314 | c = getchar() & INPUT_MASK; | |
315 | if (c == 0x48) /* up arrow */ | |
316 | { | |
317 | position[level]--; | |
318 | if (!position[level]) | |
319 | position[level] = 7; | |
320 | } | |
321 | else | |
322 | { | |
323 | if (c == 0x50) /* down arrow */ | |
324 | { | |
325 | position[level]++; | |
326 | if (position[level] > 7) | |
327 | position[level] = 1; | |
328 | } | |
329 | } | |
330 | #endif /* _WIN32 */ | |
331 | break; | |
332 | default: | |
333 | printf("%c", 7); | |
334 | break; | |
335 | } | |
336 | highlight(main_menu); | |
337 | } | |
338 | } | |
339 | ||
340 | /****************************************************/ | |
341 | void show_list_info(void) | |
342 | { | |
343 | char *buf; | |
344 | ||
345 | show_text(DISPROW, STARTCOL, "Show information about a list.\n"); | |
346 | buf = calloc(1024, 1); | |
347 | if (Prompt("Enter List Name: ", buf, LISTSIZE, 1) == 1) | |
348 | { | |
349 | display_buff("\n"); | |
350 | if (fetch_list_info(buf, current_li) == 0) | |
351 | { | |
352 | sprintf(buf, "Description: %s\n", current_li->desc); | |
353 | if (strlen(buf) > 60) | |
354 | display_buff(buf); | |
355 | else | |
356 | show_text(currow, STARTCOL, buf); | |
357 | currow++; | |
358 | sprintf(buf, "List Administrator: %s %s", | |
359 | current_li->acl_type, current_li->acl_name); | |
360 | show_text(currow, STARTCOL, buf); | |
361 | currow++; | |
362 | sprintf(buf, "Modified on %s by user %s with %s", | |
363 | current_li->modtime, current_li->modby, | |
364 | current_li->modwith); | |
365 | show_text(currow, STARTCOL, buf); | |
366 | currow++; | |
367 | } | |
368 | else | |
369 | { | |
370 | show_text(currow, STARTCOL, "mailmaint: No such list found."); | |
371 | currow++; | |
372 | } | |
373 | show_text(currow, STARTCOL, "Press any Key to continue..."); | |
374 | getchar(); | |
375 | } | |
376 | free(buf); | |
377 | clrwin(DISPROW); | |
378 | } | |
379 | ||
380 | /****************************************************/ | |
381 | void display_buff(char *buf) | |
382 | { | |
383 | int i, cnt; | |
384 | char *printbuf = NULL; | |
385 | int maxcol; | |
386 | int len; | |
387 | ||
388 | maxcol = COLS; | |
389 | ||
390 | cnt = 0; | |
391 | printbuf = calloc(maxcol, 1); | |
392 | len = strlen(buf); | |
393 | for (i = 0; i <= len; i++) | |
394 | { | |
395 | printbuf[cnt] = buf[i]; | |
396 | cnt++; | |
397 | if (cnt >= maxcol) | |
398 | { | |
399 | start_display_buff(printbuf); | |
400 | cnt = 0; | |
401 | free(printbuf); | |
402 | printbuf = calloc(maxcol, 1); | |
403 | } | |
404 | } | |
405 | if (len % maxcol != 0) | |
406 | { | |
407 | start_display_buff(printbuf); | |
408 | } | |
409 | if (printbuf) | |
410 | free(printbuf); | |
411 | return; | |
412 | } | |
413 | ||
414 | /****************************************************/ | |
415 | void start_display_buff(char *buff) | |
416 | { | |
417 | char buffer[5]; | |
418 | ||
419 | num_members++; | |
420 | if (moreflg) | |
421 | return; | |
422 | if (currow >= LINES - 2) | |
423 | { | |
424 | page++; | |
425 | currow++; | |
426 | mvcur(0, 0, currow, STARTCOL); | |
427 | refresh(); | |
428 | if (Prompt("--RETURN for more, ctl-c to exit--", buffer, 1, 0) == 0) | |
429 | { | |
430 | erase_line(currow, STARTCOL); | |
431 | show_text(currow, STARTCOL, "Flushing query..."); | |
432 | moreflg = 1; | |
433 | return; | |
434 | } | |
435 | clrwin(DISPROW + 2); | |
436 | currow = DISPROW + 2; | |
437 | show_text(currow, STARTCOL, "continued"); | |
438 | currow++; | |
439 | } | |
440 | show_text(currow, STARTCOL, buff); | |
441 | currow++; | |
442 | return; | |
443 | } | |
444 | ||
445 | /****************************************************/ | |
446 | void add_member(void) | |
447 | { | |
448 | char *argv[3]; | |
449 | char *buf; | |
450 | ||
451 | show_text(DISPROW, STARTCOL, "Add yourself to a list\n"); | |
452 | buf = calloc(LISTMAX, 1); | |
453 | if (Prompt("Enter List Name: ", buf, LISTSIZE, 1) == 1) | |
454 | { | |
455 | display_buff("\n"); | |
456 | argv[0] = strdup(buf); | |
457 | argv[1] = strdup("user"); | |
458 | argv[2] = strdup(username); | |
459 | if ((status = mr_query("add_member_to_list", 3, argv, NULL, NULL))) | |
460 | { | |
461 | display_buff("\n"); | |
462 | com_err(whoami, status, " found.\n"); | |
463 | } | |
464 | else | |
465 | { | |
466 | sprintf(buf, "User %s added to list\n", username); | |
467 | show_text(DISPROW + 3, STARTCOL, buf); | |
468 | } | |
469 | currow = DISPROW + 4; | |
470 | show_text(DISPROW + 4, STARTCOL, "Press any Key to continue..."); | |
471 | getchar(); | |
472 | } | |
473 | free(buf); | |
474 | clrwin(DISPROW); | |
475 | } | |
476 | ||
477 | /****************************************************/ | |
478 | void delete_member(void) | |
479 | { | |
480 | char *argv[3]; | |
481 | char *buf; | |
482 | ||
483 | show_text(DISPROW, STARTCOL, "Remove yourself from a list\n"); | |
484 | buf = calloc(LISTMAX, 1); | |
485 | if (Prompt("Enter List Name: ", buf, LISTSIZE, 1) == 1) | |
486 | { | |
487 | display_buff("\n"); | |
488 | argv[0] = strdup(buf); | |
489 | argv[1] = strdup("user"); | |
490 | argv[2] = strdup(username); | |
491 | if ((status = mr_query("delete_member_from_list", 3, argv, NULL, NULL))) | |
492 | { | |
493 | display_buff("\n"); | |
494 | com_err(whoami, status, " found.\n"); | |
495 | } | |
496 | else | |
497 | { | |
498 | sprintf(buf, "User %s deleted from list\n", username); | |
499 | show_text(DISPROW + 3, STARTCOL, buf); | |
500 | } | |
501 | currow = DISPROW + 4; | |
502 | show_text(DISPROW + 4, STARTCOL, "Press any Key to continue..."); | |
503 | getchar(); | |
504 | free(argv[0]); | |
505 | free(argv[1]); | |
506 | free(argv[2]); | |
507 | } | |
508 | free(buf); | |
509 | clrwin(DISPROW); | |
510 | } | |
511 | ||
512 | /****************************************************/ | |
513 | void list_by_member(void) | |
514 | { | |
515 | char *nargv[3]; | |
516 | char *buf; | |
517 | ||
518 | nargv[1] = strdup("ruser"); | |
519 | nargv[2] = strdup(username); | |
520 | buf = calloc(BUFSIZ, 1); | |
521 | sprintf(buf, "%s is on the following lists:\n", username); | |
522 | show_text(DISPROW, STARTCOL, buf); | |
523 | mvcur(0, 0, currow, STARTCOL); | |
524 | refresh(); | |
525 | if ((status = mr_query("get_lists_of_member", 2, nargv + 1, print_1, NULL))) | |
526 | { | |
527 | display_buff("\n"); | |
528 | com_err(whoami, status, " in get_lists_of_member"); | |
529 | } | |
530 | currow++; | |
531 | show_text(currow, STARTCOL, "Press any Key to continue..."); | |
532 | getchar(); | |
533 | clrwin(DISPROW); | |
534 | free(buf); | |
535 | } | |
536 | ||
537 | /****************************************************/ | |
538 | void show_all(void) | |
539 | { | |
540 | char c; | |
541 | ||
542 | show_text(DISPROW, STARTCOL, "This function may take a while... proceed? [n] "); | |
543 | c = getchar() & INPUT_MASK; | |
544 | if (c == 'y' || c == 'Y') | |
545 | { | |
546 | move(DISPROW + 1, STARTCOL); | |
547 | addstr("Processing query...please hold"); | |
548 | refresh(); | |
549 | list_all_groups(); | |
550 | } | |
551 | else | |
552 | erase_line(DISPROW, STARTCOL); | |
553 | } | |
554 | ||
555 | /****************************************************/ | |
556 | static int print_1(int argc, char *argv[], void *callback) | |
557 | { | |
558 | char buf[BUFSIZ]; | |
559 | ||
560 | /* no newline 'cause display_buff adds one */ | |
561 | sprintf(buf, "%s\n", argv[0]); | |
562 | start_display(buf); | |
563 | ||
564 | return MR_CONT; | |
565 | } | |
566 | ||
567 | /****************************************************/ | |
568 | static int print_all(int argc, char *argv[], void *callback) | |
569 | { | |
570 | char buf[BUFSIZ]; | |
571 | ||
572 | if (moreflg) | |
573 | return 0; | |
574 | if (first_time) | |
575 | { | |
576 | erase_line(DISPROW + 1, STARTCOL); | |
577 | show_text(DISPROW + 1, STARTCOL, "All mailing lists:"); | |
578 | first_time = 0; | |
579 | } | |
580 | sprintf(buf, "%s\n", argv[0]); | |
581 | start_display(buf); | |
582 | ||
583 | return MR_CONT; | |
584 | } | |
585 | ||
586 | /****************************************************/ | |
587 | void list_all_groups(void) | |
588 | { | |
589 | char *argv[5]; | |
590 | argv[0] = argv[1] = argv[3] = "true"; | |
591 | argv[4] = "dontcare"; | |
592 | argv[2] = "false"; | |
593 | first_time = 1; | |
594 | if ((status = mr_query("qualified_get_lists", 5, argv, print_all, NULL))) | |
595 | { | |
596 | display_buff("\n"); | |
597 | com_err(whoami, status, " in list_all_groups\n"); | |
598 | } | |
599 | end_display(); | |
600 | } | |
601 | ||
602 | /****************************************************/ | |
603 | void list_members(void) | |
604 | { | |
605 | char *argv[1]; | |
606 | char *buf; | |
607 | char buffer[80]; | |
608 | ||
609 | found_some = 0; | |
610 | move(DISPROW, STARTCOL); | |
611 | mvcur(0, 0, DISPROW, STARTCOL); | |
612 | refresh(); | |
613 | buf = calloc(LISTMAX, 1); | |
614 | if (Prompt("Enter List Name: ", buf, LISTSIZE, 1) == 1) | |
615 | { | |
616 | sprintf(buffer, "The members of list '%s' are:", buf); | |
617 | show_text(DISPROW + 1, STARTCOL, buffer); | |
618 | argv[0] = buf; | |
619 | if ((status = mr_query("get_members_of_list", 1, argv, print_2, NULL))) | |
620 | { | |
621 | display_buff("\n"); | |
622 | com_err(whoami, status, " found.\n"); | |
623 | currow++; | |
624 | } | |
625 | if (!found_some) | |
626 | { | |
627 | show_text(currow, STARTCOL, "List is empty (no members)."); | |
628 | currow++; | |
629 | show_text(currow, STARTCOL, "Press any key to continue..."); | |
630 | getchar(); | |
631 | clrwin(DISPROW); | |
632 | goto cleanup; | |
633 | } | |
634 | end_display(); | |
635 | goto cleanup; | |
636 | } | |
637 | clrwin(DISPROW); | |
638 | cleanup: | |
639 | free(buf); | |
640 | } | |
641 | ||
642 | /****************************************************/ | |
643 | static int print_2(int argc, char *argv[], void *callback) | |
644 | { | |
645 | char buf[BUFSIZ]; | |
646 | ||
647 | found_some = 1; | |
648 | sprintf(buf, "%s %s", argv[0], argv[1]); | |
649 | start_display(buf); | |
650 | ||
651 | return MR_CONT; | |
652 | } | |
653 | ||
654 | /****************************************************/ | |
655 | void start_display(char *buff) | |
656 | { | |
657 | char *buffer; | |
658 | int secondcol; /* where to start the second column of text */ | |
659 | ||
660 | secondcol = (COLS / 2); /* 1/2 was accross the screen */ | |
661 | num_members++; | |
662 | if (moreflg) | |
663 | return; | |
664 | buffer = calloc(50, 1); | |
665 | if (currow >= LINES - 2) | |
666 | { | |
667 | page++; | |
668 | mvcur(0, 0, currow, STARTCOL); | |
669 | refresh(); | |
670 | if (Prompt("--RETURN for more, ctl-c to exit--", buffer, 1, 0) == 0) | |
671 | { | |
672 | erase_line(currow, STARTCOL); | |
673 | show_text(currow, STARTCOL, "Flushing query..."); | |
674 | moreflg = 1; | |
675 | goto cleanup; | |
676 | } | |
677 | clrwin(DISPROW + 2); | |
678 | currow = DISPROW + 2; | |
679 | sprintf(buffer, "Continued (Page %d)", page); | |
680 | show_text(currow, STARTCOL, buffer); | |
681 | currow++; | |
682 | toggle = 0; | |
683 | } | |
684 | if (!toggle) | |
685 | show_text(currow, STARTCOL, buff); | |
686 | else | |
687 | { | |
688 | erase_line(currow, secondcol - 1); /* in case the 1st col is too long */ | |
689 | show_text(currow, secondcol, buff); | |
690 | currow++; | |
691 | } | |
692 | toggle = !toggle; | |
693 | cleanup: | |
694 | free(buffer); | |
695 | } | |
696 | ||
697 | /****************************************************/ | |
698 | void end_display(void) | |
699 | { | |
700 | char *buffer; | |
701 | ||
702 | if (moreflg) | |
703 | { | |
704 | clrwin(DISPROW); | |
705 | return; | |
706 | } | |
707 | ||
708 | buffer = calloc(50, 1); | |
709 | currow++; | |
710 | sprintf(buffer, "End of List. %d Total Members\n", num_members - 1); | |
711 | show_text(currow, STARTCOL, buffer); | |
712 | currow++; | |
713 | show_text(currow, STARTCOL, "Press any key to continue..."); | |
714 | getchar(); | |
715 | clrwin(DISPROW); | |
716 | free(buffer); | |
717 | } | |
718 | ||
719 | /****************************************************/ | |
720 | void display_menu(MENU *menu) | |
721 | { | |
722 | int i; | |
723 | ||
724 | cls(); | |
725 | title(menu->title); | |
726 | mvcur(0, 0, STARTROW, STARTCOL); | |
727 | refresh(); | |
728 | for (i = 0; i <= menu->num_items - 1; i++) | |
729 | { | |
730 | move(STARTROW + i, STARTCOL); | |
731 | standend(); | |
732 | addstr(menu->items[i]); | |
733 | refresh(); | |
734 | } | |
735 | center_text(STARTROW + menu->num_items + 2, | |
736 | "Enter a number, <up arrow>, or <down arrow>."); | |
737 | if (!level) | |
738 | { | |
739 | center_text(STARTROW + menu->num_items + 3, | |
740 | "Press 'q' to exit, <return> to confirm choice."); | |
741 | } | |
742 | else | |
743 | { | |
744 | center_text(STARTROW + menu->num_items + 3, | |
745 | "Press 'q' to exit, 'r' for main menu, " | |
746 | "<return> to confirm choice."); | |
747 | } | |
748 | ||
749 | if (!level) | |
750 | highlight(main_menu); | |
751 | } | |
752 | ||
753 | /****************************************************/ | |
754 | void pack_main_menu(void) | |
755 | { | |
756 | char *buf; | |
757 | ||
758 | main_menu = malloc(sizeof(MENU)); | |
759 | main_menu->num_items = 7; | |
760 | main_menu->items = malloc(sizeof(char *) * main_menu->num_items); | |
761 | ||
762 | buf = calloc(50, 1); | |
763 | sprintf(buf, "Mail List Program for %s", username); | |
764 | main_menu->title = strdup(buf); | |
765 | main_menu->items[0] = strdup("1. Show all public mailing lists."); | |
766 | main_menu->items[1] = strdup("2. Get all members of a mailing list."); | |
767 | main_menu->items[2] = strdup("3. Display lists of which you are a member."); | |
768 | main_menu->items[3] = strdup("4. Show description of list."); | |
769 | main_menu->items[4] = strdup("5. Add yourself to a mailing list."); | |
770 | main_menu->items[5] = strdup("6. Delete yourself from a mailing list."); | |
771 | main_menu->items[6] = strdup("q. Quit."); | |
772 | free(buf); | |
773 | } | |
774 | ||
775 | /****************************************************/ | |
776 | void pack_help_menu(void) | |
777 | { | |
778 | help_menu = malloc(sizeof(MENU)); | |
779 | help_menu->num_items = 5; | |
780 | help_menu->items = malloc(sizeof(char *) * help_menu->num_items); | |
781 | ||
782 | help_menu->title = strdup("mailmaint is designed as a basic mail list administration program."); | |
783 | help_menu->items[0] = strdup("if you need to perform more advanced list manipulation like"); | |
784 | help_menu->items[1] = strdup("adding lists, or changing list characteristics, refer to the"); | |
785 | help_menu->items[2] = strdup("program listmaint."); | |
786 | help_menu->items[3] = strdup(" "); | |
787 | help_menu->items[4] = strdup("Press any key to continue."); | |
788 | } | |
789 | ||
790 | /****************************************************/ | |
791 | void free_menu(MENU* menu) | |
792 | { | |
793 | int i; | |
794 | for (i = 0; i < menu->num_items; i++) | |
795 | free(menu->items[i]); | |
796 | free(menu->items); | |
797 | free(menu->title); | |
798 | free(menu); | |
799 | } | |
800 | ||
801 | /****************************************************/ | |
802 | void highlight(MENU *menu) | |
803 | { | |
804 | if (oldpos[level] != position[level]) | |
805 | { | |
806 | move(STARTROW + oldpos[level] - 1, STARTCOL); | |
807 | standend(); | |
808 | addstr(menu->items[oldpos[level] - 1]); | |
809 | refresh(); | |
810 | } | |
811 | ||
812 | move(STARTROW + position[level] - 1, STARTCOL); | |
813 | standout(); | |
814 | addstr(menu->items[position[level] - 1]); | |
815 | refresh(); | |
816 | standend(); | |
817 | refresh(); | |
818 | } | |
819 | ||
820 | /****************************************************/ | |
821 | void title(char *buff) | |
822 | { | |
823 | move(0, MAX(0, (COLS - (int)strlen(buff)) >> 1)); | |
824 | standout(); | |
825 | addstr(buff); | |
826 | refresh(); | |
827 | standend(); | |
828 | } | |
829 | ||
830 | /****************************************************/ | |
831 | void center_text(int row, char *buff) | |
832 | { | |
833 | move(row, MAX(0, (COLS - (int)strlen(buff)) >> 1)); | |
834 | addstr(buff); | |
835 | refresh(); | |
836 | } | |
837 | ||
838 | /****************************************************/ | |
839 | void show_text(int row, int col, char *buff) | |
840 | { | |
841 | mvcur(0, 0, row, col); | |
842 | addstr(buff); | |
843 | refresh(); | |
844 | } | |
845 | ||
846 | /****************************************************/ | |
847 | void erase_line(int row, int col) | |
848 | { | |
849 | char *buff; | |
850 | int i; | |
851 | ||
852 | buff = calloc(COLS, 1); | |
853 | for (i = 0; i <= COLS - 2; i++) | |
854 | buff[i] = ' '; | |
855 | buff[i] = 0; /* just to be sure ! */ | |
856 | move(row, col); | |
857 | mvcur(0, 0, row, col); | |
858 | addstr(buff); | |
859 | refresh(); | |
860 | free(buff); /* close mem. leak */ | |
861 | } | |
862 | ||
863 | /****************************************************/ | |
864 | void cls(void) | |
865 | { | |
866 | clear(); | |
867 | refresh(); | |
868 | } | |
869 | ||
870 | /****************************************************/ | |
871 | void clrwin(int erase_row) | |
872 | { | |
873 | int i; | |
874 | char *buff; | |
875 | int maxcol; | |
876 | ||
877 | maxcol = COLS; | |
878 | ||
879 | buff = calloc(maxcol + 1, 1); | |
880 | for (i = 0; i <= maxcol - 1; i++) | |
881 | buff[i] = ' '; | |
882 | buff[i] = 0; /* just to be sure ! */ | |
883 | mvcur(0, 0, erase_row, STARTCOL); | |
884 | refresh(); | |
885 | for (i = erase_row; i <= currow - 1; i++) | |
886 | addstr(buff); | |
887 | addstr(buff); | |
888 | mvcur(erase_row, STARTCOL, STARTROW + oldpos[level] - 1, STARTCOL); | |
889 | refresh(); | |
890 | free(buff); | |
891 | } | |
892 | ||
893 | /****************************************************/ | |
894 | static int fetch_list_info(char *list, List_info *li) | |
895 | { | |
896 | char *argv[1]; | |
897 | ||
898 | argv[0] = list; | |
899 | return mr_query("get_list_info", 1, argv, get_list_info, NULL); | |
900 | } | |
901 | ||
902 | static int get_list_info(int argc, char **argv, void *hint) | |
903 | { | |
904 | if (current_li->acl_type) | |
905 | free(current_li->acl_type); | |
906 | current_li->acl_type = strdup(argv[7]); | |
907 | if (current_li->acl_name) | |
908 | free(current_li->acl_name); | |
909 | current_li->acl_name = strdup(argv[8]); | |
910 | if (current_li->desc) | |
911 | free(current_li->desc); | |
912 | current_li->desc = strdup(argv[9]); | |
913 | if (current_li->modtime) | |
914 | free(current_li->modtime); | |
915 | current_li->modtime = strdup(argv[10]); | |
916 | if (current_li->modby) | |
917 | free(current_li->modby); | |
918 | current_li->modby = strdup(argv[11]); | |
919 | if (current_li->modwith) | |
920 | free(current_li->modwith); | |
921 | current_li->modwith = strdup(argv[12]); | |
922 | return MR_CONT; | |
923 | } | |
924 | ||
925 | ||
926 | /****************************************************/ | |
927 | /* Prompt the user for input */ | |
928 | int Prompt(char *prompt, char *buf, int buflen, int crok) | |
929 | { | |
930 | int c; | |
931 | char *p; | |
932 | ||
933 | addstr(prompt); | |
934 | refresh(); | |
935 | ||
936 | for (p = buf; abs(strlen(p) - strlen(buf)) <= buflen;) | |
937 | { | |
938 | refresh(); | |
939 | c = getchar() & INPUT_MASK; | |
940 | switch (c) | |
941 | { | |
942 | case CTL('C'): | |
943 | return 0; | |
944 | case CTL('Z'): | |
945 | return 0; | |
946 | case CTL('L'): | |
947 | cls(); | |
948 | display_menu(main_menu); | |
949 | return 0; | |
950 | case '\n': | |
951 | case '\r': | |
952 | if (crok) | |
953 | display_buff("\n"); | |
954 | *p = '\0'; | |
955 | if (strlen(buf) < 1) /* only \n or \r in buff */ | |
956 | return -1; | |
957 | else | |
958 | return 1; | |
959 | case '\b': | |
960 | case '\177': | |
961 | if (p > buf) | |
962 | { | |
963 | p--; | |
964 | DELETE_A_CHAR(); | |
965 | } | |
966 | break; | |
967 | case CTL('U'): | |
968 | case CTL('G'): | |
969 | case CTL('['): | |
970 | while (p-- > buf) | |
971 | DELETE_A_CHAR(); | |
972 | p = buf; | |
973 | break; | |
974 | #ifdef _WIN32 | |
975 | case 0xe0: | |
976 | c = getchar() & INPUT_MASK; | |
977 | putchar(CTL('G')); | |
978 | break; | |
979 | #endif /*_WIN32*/ | |
980 | default: | |
981 | if (abs(strlen(p) - strlen(buf)) >= buflen) | |
982 | { | |
983 | printf("%c", 7); | |
984 | break; | |
985 | } | |
986 | if (isprint(c)) | |
987 | { | |
988 | addch(c); | |
989 | *p++ = c; | |
990 | } | |
991 | else | |
992 | putchar(CTL('G')); | |
993 | break; | |
994 | } | |
995 | } | |
996 | return 0; | |
997 | } | |
998 | ||
999 | ||
1000 | /* | |
1001 | * Hook function to cause error messages to be printed through | |
1002 | * curses instead of around it. | |
1003 | */ | |
1004 | ||
1005 | void menu_err_hook(const char *who, long code, const char *fmt, va_list args) | |
1006 | { | |
1007 | char buf[BUFSIZ], *cp; | |
1008 | ||
1009 | strcpy(buf, who); | |
1010 | for (cp = buf; *cp; cp++) | |
1011 | ; | |
1012 | *cp++ = ':'; | |
1013 | *cp++ = ' '; | |
1014 | if (code) | |
1015 | { | |
1016 | strcpy(cp, error_message(code)); | |
1017 | while (*cp) | |
1018 | cp++; | |
1019 | } | |
1020 | vsprintf(cp, fmt, args); | |
1021 | display_buff(buf); | |
1022 | } |