1
2 static char rcsid[] = "@(#)$Id: alias.c,v 1.6 1996/08/08 19:49:22 wfp5p Exp $";
3
4 /*******************************************************************************
5 * The Elm Mail System - $Revision: 1.6 $ $State: Exp $
6 *
7 * Copyright (c) 1988-1995 USENET Community Trust
8 * Copyright (c) 1986,1987 Dave Taylor
9 *******************************************************************************
10 * Bug reports, patches, comments, suggestions should be sent to:
11 *
12 * Bill Pemberton, Elm Coordinator
13 * flash@virginia.edu
14 *
15 *******************************************************************************
16 * $Log: alias.c,v $
17 * Revision 1.6 1996/08/08 19:49:22 wfp5p
18 * Alpha 11
19 *
20 * Revision 1.5 1996/05/09 15:51:14 wfp5p
21 * Alpha 10
22 *
23 * Revision 1.4 1996/03/14 17:27:50 wfp5p
24 * Alpha 9
25 *
26 * Revision 1.3 1995/09/29 17:41:57 wfp5p
27 * Alpha 8 (Chip's big changes)
28 *
29 * Revision 1.2 1995/05/24 15:34:37 wfp5p
30 * Change to deal with parenthesized comments in when eliminating members from
31 * an alias. (from Keith Neufeld <neufeld@pvi.org>)
32 *
33 * Allow a shell escape from the alias screen (just like from
34 * the index screen). It does not put the shell escape onto the alias
35 * screen menu. (from Keith Neufeld <neufeld@pvi.org>)
36 *
37 * Allow the use of "T" from the builtin pager. (from Keith Neufeld
38 * <neufeld@pvi.org>)
39 *
40 * Revision 1.1.1.1 1995/04/19 20:38:34 wfp5p
41 * Initial import of elm 2.4 PL0 as base for elm 2.5.
42 *
43 ******************************************************************************/
44
45 /** This file contains alias stuff
46
47 **/
48
49 #include "elm_defs.h"
50 #include "elm_globals.h"
51 #include "port_stat.h"
52 #include "s_elm.h"
53 #include "s_aliases.h"
54 #include "ndbz.h"
55
56 #define ECHOIT 1 /* echo on for prompting */
57
58 /*
59 * A simple macro to make it easier to remember how to do a simple
60 * resync and not screw up whether or not to prompt on deletions.
61 */
62
63 #define resync_aliases(newaliases) delete_aliases(newaliases,TRUE)
64
65 extern char *alias_type();
66 void get_realnames();
67 void install_aliases();
68
69 int is_system=0; /* system file updating? */
70
71 int num_duplicates;
72 DBZ *system_hash = NULL, *user_hash = NULL;
73
74
open_alias_files(are_in_aliases)75 open_alias_files(are_in_aliases)
76 int are_in_aliases;
77 {
78 if(open_system_aliases() | open_user_aliases()) {
79 dprint(5, (debugfile,
80 "Reading alias data files...\n"));
81 get_aliases(are_in_aliases);
82 }
83 }
84
85 int
open_system_aliases()86 open_system_aliases()
87 {
88 /*
89 * Open the system alias file, if present,
90 * and if it has changed since last we read it.
91 *
92 * Return 0 if hash file wasn't opened, otherwise 1
93 */
94
95 struct stat hst;
96 static time_t system_ctime = 0, system_mtime = 0;
97
98 /* If file hasn't changed, don't bother re-opening. */
99
100 if (stat(system_data_file, &hst) == 0) { /* File exists */
101 if (hst.st_ctime == system_ctime &&
102 hst.st_mtime == system_mtime) { /* No changes */
103 return(0);
104 }
105
106 /*
107 * Re-open system hash table. If we can't, just return.
108 */
109
110 if (system_hash != NULL)
111 dbz_close(system_hash);
112
113 if ((system_hash = dbz_open(system_data_file, O_RDONLY, 0)) == NULL)
114 return(0);
115
116 /* Remember hash file times. */
117
118 system_ctime = hst.st_ctime;
119 system_mtime = hst.st_mtime;
120
121 return(1);
122 }
123 else { /* File does not exist */
124 if (system_ctime == 0 && system_mtime == 0) {
125 return(0); /* File never existed */
126 }
127 else { /* Once existed, better re-read */
128
129 /*
130 * Since we no longer exist, we pretend we never existed.
131 */
132
133 system_ctime = 0;
134 system_mtime = 0;
135
136 return(1);
137 }
138 }
139
140 }
141
142 int
open_user_aliases()143 open_user_aliases()
144 {
145 /*
146 * Open the user alias file, if present,
147 * and if it has changed since last we read it.
148 *
149 * Return 0 if hash file wasn't opened, otherwise 1
150 */
151
152 struct stat hst;
153 char fname[SLEN];
154 static time_t user_ctime = 0, user_mtime = 0;
155
156 /* If hash file hasn't changed, don't bother re-reading. */
157
158 sprintf(fname, "%s/%s", user_home, ALIAS_DATA);
159
160 if (stat(fname, &hst) == 0) { /* File exists */
161 if (hst.st_ctime == user_ctime &&
162 hst.st_mtime == user_mtime) { /* No changes */
163 return(0);
164 }
165
166 /*
167 * Open user hash table. If we can't, just return.
168 */
169
170 if (user_hash != NULL)
171 dbz_close(user_hash);
172
173 if ((user_hash = dbz_open(fname, O_RDONLY, 0)) == NULL)
174 return(0);
175
176 /* Remember hash file times. */
177
178 user_ctime = hst.st_ctime;
179 user_mtime = hst.st_mtime;
180
181 return(1);
182 }
183 else { /* File does not exist */
184 if (user_ctime == 0 && user_mtime == 0) {
185 return(0); /* File never existed */
186 }
187 else { /* Once existed, better re-read */
188
189 /*
190 * Since we no longer exist, we pretend we never existed.
191 */
192
193 user_ctime = 0;
194 user_mtime = 0;
195
196 return(1);
197 }
198 }
199
200 }
201
202 int
add_alias(replace,to_replace)203 add_alias(replace, to_replace)
204 int replace, to_replace;
205 {
206 /*
207 * Add an alias to the user alias text file. If there
208 * are aliases tagged, the user is asked if he wants to
209 * create a group alias from the tagged files.
210 *
211 * Return zero if alias not added in actuality.
212 *
213 * If replace == FALSE, then we will ask for the new
214 * aliasname.
215 *
216 * If replace == TRUE, then we are replacing the alias
217 * denoted by to_replace.
218 *
219 * Note that even if replace == FALSE, if the user types
220 * in the name of a current alias then we can still do
221 * a replacement.
222 */
223
224 int i, leftoff, ans, tagged = 0;
225
226 char aliasname[SLEN], firstname[SLEN], lastname[SLEN];
227 char address1[LONG_STRING], buffer[SLEN];
228 char comment[LONG_STRING];
229 char *ch_ptr;
230
231 /*
232 * See if there are any tagged aliases.
233 */
234 for (i=0; i < num_aliases; i++) {
235 if (ison(aliases[i]->status, TAGGED)) {
236 if (tagged == 0) leftoff = i;
237 tagged++;
238 }
239 }
240
241 if (tagged == 1) {
242 /*
243 * There is only on alias tagged. Ask the question
244 * but the default response is NO.
245 */
246 PutLine0(LINES-2,0, catgets(elm_msg_cat,
247 AliasesSet, AliasesOneTagged,
248 "There is 1 alias tagged..."));
249 CleartoEOLN();
250 ans = enter_yn(catgets(elm_msg_cat, AliasesSet, AliasesCreateGroup,
251 "Create group alias?"), FALSE, LINES-3, FALSE);
252 }
253 else if (tagged > 1) {
254 /*
255 * If multiple tagged aliases then we assume the user
256 * wants to create a group alias. The default response
257 * is YES.
258 */
259 PutLine1(LINES-2,0, catgets(elm_msg_cat,
260 AliasesSet, AliasesManyTagged,
261 "There are %d aliases tagged..."), tagged);
262 CleartoEOLN();
263 ans = enter_yn(catgets(elm_msg_cat, AliasesSet, AliasesCreateGroup,
264 "Create group alias?"), TRUE, LINES-3, FALSE);
265 } else {
266 /*
267 * Nothing tagged ... thus nothing to make a group of.
268 */
269 ans = FALSE;
270 }
271
272 /*
273 * If requested above, create the group alias address.
274 */
275 if (ans) {
276 strcpy(address1, aliases[leftoff]->alias);
277 for (i=leftoff+1; i < num_aliases; i++) {
278 if (ison(aliases[i]->status, TAGGED)) {
279 strcat(address1, ",");
280 strcat(address1, aliases[i]->alias);
281 }
282 }
283 }
284 else {
285 tagged = 0;
286 }
287
288 /*
289 * Only ask for an aliasname if we are NOT replacing the
290 * current alias.
291 */
292 if (replace) {
293 strcpy(aliasname, aliases[to_replace]->alias);
294 /*
295 * First, see if what we are replacing is a SYSTEM
296 * alias. If so, we need to ask a question.
297 */
298 if(aliases[to_replace]->type & SYSTEM) {
299 dprint(3, (debugfile,
300 "Aliasname [%s] is SYSTEM in add_alias\n", aliasname));
301 /*
302 * If they don't want to superceed the SYSTEM alias then
303 * just return.
304 */
305 if( ! superceed_system(to_replace, buffer)) {
306 ClearLine(LINES-2);
307 return(0);
308 }
309 }
310 }
311 else {
312 strcpy(buffer, catgets(elm_msg_cat,
313 AliasesSet, AliasesEnterAliasName, "Enter alias name: "));
314 PutLine0(LINES-2,0, buffer);
315 CleartoEOLN();
316 *aliasname = '\0';
317 if ((replace = get_aliasname(aliasname, buffer, &to_replace)) < 0) {
318 dprint(3, (debugfile,
319 "Aliasname [%s] was rejected in add_alias\n", aliasname));
320 ClearLine(LINES-2);
321 return(0);
322 }
323 }
324
325 /*
326 * If we are replacing an existing alias, we will assume that
327 * they might want to be just editing most of what is already
328 * there. So we copy some defaults from the existing alias.
329 */
330 if (replace) {
331 strcpy(lastname, aliases[to_replace]->last_name);
332 strcpy(firstname, aliases[to_replace]->name);
333 ch_ptr = strstr(firstname, lastname);
334 *(ch_ptr-1) = '\0';
335 strcpy(comment, aliases[to_replace]->comment);
336 }
337 else {
338 *lastname = '\0';
339 *firstname = '\0';
340 *comment = '\0';
341 }
342 get_realnames(aliasname, firstname, lastname, comment, buffer);
343
344 /*
345 * Since there are no tagged aliases, we must ask for an
346 * address. If we are replacing, a default address is
347 * presented.
348 */
349 if (tagged == 0) {
350 sprintf(buffer, catgets(elm_msg_cat,
351 AliasesSet, AliasesEnterAddress,
352 "Enter address for %s: "), aliasname);
353 PutLine0(LINES-2, 0, buffer);
354 if (replace)
355 strcpy(address1, aliases[to_replace]->address);
356 else
357 *address1 = '\0';
358
359 if (enter_string(address1, sizeof(address1), -1, -1,
360 ESTR_REPLACE) < 0 || address1[0] == '\0') {
361 Raw(ON);
362 error(catgets(elm_msg_cat, AliasesSet, AliasesNoAddressSpec,
363 "No address specified!"));
364 return(0);
365 }
366 Raw(ON);
367
368 despace_address(address1);
369
370 clear_error(); /* Just in case */
371 }
372
373 if(ask_accept(aliasname, firstname, lastname, comment, address1,
374 buffer, replace, to_replace)) {
375 /*
376 * We can only clear the tags after we know that the
377 * alias was added. This allows the user to back out
378 * and rethink without losing the tags.
379 */
380 if (tagged > 0) {
381 for (i=leftoff; i < num_aliases; i++) {
382 if (ison(aliases[i]->status, TAGGED)) {
383 clearit(aliases[i]->status, TAGGED);
384 show_msg_tag(i);
385 }
386 }
387 }
388 return(1);
389 }
390 else {
391 return(0);
392 }
393
394 }
395
396 int
add_current_alias()397 add_current_alias()
398 {
399 /*
400 * Alias the current message to the specified name and
401 * add it to the alias text file, for processing as
402 * the user leaves the program.
403 *
404 * Returns non-zero iff alias actually added to file.
405 */
406
407 char aliasname[SLEN], firstname[SLEN], lastname[SLEN];
408 char comment[SLEN], address1[LONG_STRING], buffer[SLEN];
409 char comment_buff[LONG_STRING];
410 char *chspace, *bufptr;
411 struct header_rec *current_header;
412
413 static char bad_punc[] = ",.:;";
414 char *punc_ptr;
415 int i, match;
416 int replace, to_replace;
417
418 if (curr_folder.curr_mssg == 0) {
419 dprint(4, (debugfile,
420 "Add current alias called without any current message!\n"));
421 error(catgets(elm_msg_cat, AliasesSet, AliasesNoMessage,
422 "No message to alias to!"));
423 return(0);
424 }
425 current_header = curr_folder.headers[curr_folder.curr_mssg-1];
426
427 strcpy(buffer, catgets(elm_msg_cat, AliasesSet, AliasesCurrentMessage,
428 "Current message address aliased to: "));
429 PutLine0(LINES-2,0, buffer);
430 CleartoEOLN();
431 *aliasname = '\0';
432 if ((replace = get_aliasname(aliasname, buffer, &to_replace)) < 0) {
433 dprint(3, (debugfile,
434 "Aliasname [%s] was rejected in add_current_alias\n",
435 aliasname));
436 ClearLine(LINES-2);
437 return(0);
438 }
439
440 /* use full name in current message for default comment */
441 tail_of(current_header->from, comment_buff, current_header->to);
442 if(index(comment_buff, (int)'!') || index(comment_buff, (int)'@'))
443 /* never mind - it's an address not a full name */
444 *comment_buff = '\0';
445
446 /*
447 * Try to break up the From: comment into firstname, lastname, and
448 * any other text. This is based on the fact that many address
449 * comments are pretty straightforward. This will break on many
450 * situations. Should handle:
451 * (Robert Howard)
452 * (Robert L. Howard)
453 * (Robert Howard, Georgia Tech)
454 * pretty well. Will break on:
455 * (The Voice of Reason)
456 * and others....
457 */
458
459 *firstname = '\0';
460 *lastname = '\0';
461 *comment = '\0';
462 if (strlen(comment_buff) != 0) { /* There is something. */
463 bufptr = comment_buff;
464 while (*bufptr == ' ') bufptr++; /* Always strip leading WS */
465 if ((chspace = index(bufptr, ' ')) != NULL) {
466 /*
467 * A space means that there is at least (firstname lastname)
468 * Get firstname and move bufptr.
469 */
470 *chspace = '\0';
471 strcpy(firstname, bufptr);
472 bufptr = chspace + 1; /* Move the pointer */
473 while (*bufptr == ' ') bufptr++;
474 }
475
476 above: if ((chspace = index(bufptr, ' ')) != NULL) {
477 /*
478 * Another space means a third+ word. We either have:
479 * 1. Word 3+ is a comment, or
480 * 2. Word 2 is a middle initial (word 3 is lastname).
481 * Check and see.
482 */
483 *chspace = '\0';
484 if ((strlen(bufptr) == 1) ||
485 (strlen(bufptr) == 2 && *(bufptr+1) == '.')) {
486 /*
487 * If the second word is either a single
488 * character or a character followed by '.' it was
489 * probably a middle initial. Add it to firstname
490 * and shift.
491 */
492 strcat(firstname, " ");
493 strcat(firstname, bufptr);
494 bufptr = chspace + 1; /* Move the pointer */
495 while (*bufptr == ' ') bufptr++;
496 goto above;
497 }
498 strcpy(lastname, bufptr);
499 bufptr = chspace + 1; /* Move the pointer */
500 while (*bufptr == ' ') bufptr++;
501 strcpy(comment, bufptr);
502 }
503 else {
504 /*
505 * Only a lastname left.
506 */
507 strcpy(lastname, bufptr);
508 }
509
510 /*
511 * Finally, get any puctuation characters off the end of
512 * lastname.
513 */
514 match = TRUE;
515 for (i = strlen(lastname) - 1; match && i>0; i--) {
516 match = FALSE;
517 for (punc_ptr = bad_punc; *punc_ptr != '\0'; punc_ptr++) {
518 if (lastname[i] == *punc_ptr) {
519 lastname[i] = '\0';
520 match = TRUE;
521 break;
522 }
523 }
524 }
525 }
526
527 get_realnames(aliasname, firstname, lastname, comment, buffer);
528
529 /* grab the return address of this message */
530 get_return(address1, curr_folder.curr_mssg-1);
531 strcpy(address1, strip_parens(address1)); /* remove parens! */
532
533 return(ask_accept(aliasname, firstname, lastname, comment, address1,
534 buffer, replace, to_replace));
535
536 }
537
add_to_alias_text(aliasname,firstname,lastname,comment,address)538 add_to_alias_text(aliasname, firstname, lastname, comment, address)
539 char *aliasname, *firstname, *lastname, *comment, *address;
540 {
541 /*
542 * Add the data to the user alias text file.
543 *
544 * Return zero if we succeeded, 1 if not.
545 */
546
547 FILE *file;
548 char fname[SLEN];
549 char buffer[SLEN];
550 int err;
551
552 sprintf(fname,"%s/%s", user_home, ALIAS_TEXT);
553
554 save_file_stats(fname);
555 if ((file = fopen(fname, "a")) == NULL) {
556 err = errno;
557 dprint(2, (debugfile,
558 "Failure attempting to add alias to file %s within %s",
559 fname, "add_to_alias_text"));
560 dprint(2, (debugfile, "** %s **\n", strerror(err)));
561 error1(catgets(elm_msg_cat, AliasesSet, AliasesCouldntOpenAdd,
562 "Couldn't open %s to add new alias!"), fname);
563 return(1);
564 }
565
566 if (strlen(firstname) == 0) {
567 strcpy(buffer, lastname);
568 }
569 else {
570 sprintf(buffer, "%s; %s", lastname, firstname);
571 }
572 if (strlen(comment) != 0) {
573 strcat(buffer, ", ");
574 strcat(buffer, comment);
575 }
576 if (fprintf(file,"%s = %s = %s\n", aliasname, buffer, address) == EOF) {
577 err = errno;
578 dprint(2, (debugfile,
579 "Failure attempting to write alias to file within %s",
580 fname, "add_to_alias_text"));
581 dprint(2, (debugfile, "** %s **\n", strerror(err)));
582 error1(catgets(elm_msg_cat, AliasesSet, AliasesCouldntWrite,
583 "Couldn't write alias to file %s!"), fname);
584 fclose(file);
585 return(1);
586 }
587
588 fclose(file);
589
590 restore_file_stats(fname);
591
592 return(0);
593 }
594
delete_from_alias_text(name,num_to_delete)595 delete_from_alias_text(name, num_to_delete)
596 char **name;
597 int num_to_delete;
598 {
599 /*
600 * Delete the data from the user alias text file.
601 *
602 * Return zero if we succeeded, 1 if not.
603 */
604
605 FILE *file, *tmp_file;
606
607 char fname[SLEN], tmpfname[SLEN];
608 char line_in_file[LONG_STRING];
609 char rest_of_line[LONG_STRING];
610 char *s, *rest;
611
612 register int i;
613 int num_aliases;
614 int delete_continues;
615 int err;
616
617 delete_continues = FALSE;
618
619 for (i=0; i < num_to_delete; i++)
620 strcat(name[i], ",");
621
622 sprintf(fname,"%s/%s", user_home, ALIAS_TEXT);
623 sprintf(tmpfname,"%s/%s.t", user_home, ALIAS_TEXT);
624
625 save_file_stats(fname);
626
627 if ((file = fopen(fname, "r")) == NULL) {
628 err = errno;
629 dprint(2, (debugfile,
630 "Failure attempting to delete alias from file %s within %s",
631 fname, "delete_from_alias_text"));
632 dprint(2, (debugfile, "** %s **\n", strerror(err)));
633 error1(catgets(elm_msg_cat, AliasesSet, AliasesCouldntOpenDelete,
634 "Couldn't open %s to delete alias!"), fname);
635 return(1);
636 }
637
638 if ((tmp_file = file_open(tmpfname, "w")) == NULL) {
639 err = errno;
640 dprint(2, (debugfile,
641 "Failure attempting to open temp file %s within %s",
642 tmpfname, "delete_from_alias_text"));
643 dprint(2, (debugfile, "** %s **\n", strerror(err)));
644 error1(catgets(elm_msg_cat, AliasesSet, AliasesCouldntOpenTemp,
645 "Couldn't open temp file %s to delete alias!"), tmpfname);
646 return(1);
647 }
648
649 while (mail_gets(line_in_file, sizeof(line_in_file), file) != 0)
650 {
651 if (! whitespace(line_in_file[0])) {
652 delete_continues = FALSE;
653 if (line_in_file[0] != '#') {
654 if (num_aliases = parse_aliases(line_in_file, rest_of_line)) {
655 for (i=0; i < num_to_delete && num_aliases; i++) {
656 if ( ((s = strstr(line_in_file, name[i])) == line_in_file) ||
657 ((s != NULL) && (*(s-1) == ',')) ) {
658 /*
659 * Collapse the to be deleted alias out of line_in_file
660 */
661 rest = index(s, (int)',');
662 for (++rest; *rest; rest++)
663 *s++ = *rest;
664 *s = '\0';
665 num_aliases--;
666 }
667 }
668 if (num_aliases) {
669 *(line_in_file + strlen(line_in_file) - 1) = ' ';
670 strcat(line_in_file, rest_of_line);
671 }
672 else {
673 delete_continues = TRUE;
674 }
675 }
676 }
677 }
678 if (! delete_continues) {
679 if (fprintf(tmp_file,"%s", line_in_file) == EOF) {
680 err = errno;
681 dprint(2, (debugfile,
682 "Failure attempting to write to temp file %s within %s",
683 tmpfname, "delete_from_alias_text"));
684 dprint(2, (debugfile, "** %s **\n", strerror(err)));
685 error1(catgets(elm_msg_cat, AliasesSet, AliasesCouldntWriteTemp,
686 "Couldn't write to temp file %s!"), tmpfname);
687 fclose(file);
688 fclose(tmp_file);
689 unlink(tmpfname);
690 return(1);
691 }
692 }
693 }
694 fclose(file);
695 fclose(tmp_file);
696 if (rename(tmpfname, fname) != 0)
697 {
698 error1(catgets(elm_msg_cat, AliasesSet, AliasesCouldntRenameTemp,
699 "Couldn't rename temp file %s after deleting alias!"), tmpfname);
700 return(1);
701 }
702
703 restore_file_stats(fname);
704
705 return(0);
706 }
707
708 void
alias()709 alias()
710 {
711 /*
712 * Work with alias commands...
713 */
714
715 char name[NLEN], *address, buffer[SLEN];
716 char *commap;
717 int key_offset; /** Position offset within keyboard string **/
718 static int newaliases = 0;
719 int ch, i, j;
720 int nutitle = 0;
721 int too_long;
722
723 /*
724 * We're going to try to match the way elm does it at
725 * he main menu. I probably won't be able to use any
726 * main menu routines, but I will "borrow" from them. RLH
727 */
728
729 main_state(); /* Save globals for return to main menu */
730
731 open_alias_files(FALSE); /* First, read the alias files. RLH */
732
733 alias_screen(newaliases);
734
735 while (1) {
736
737 redraw = 0;
738 nucurr = 0;
739 nufoot = 0;
740
741 prompt(nls_Prompt);
742 CleartoEOLN();
743 ch = GetKey(0);
744
745 MoveCursor(LINES-3,strlen(nls_Prompt)); CleartoEOS();
746
747 dprint(3, (debugfile, "\n-- Alias command: %c\n\n", ch));
748
749 switch (ch) {
750 case '?': redraw += alias_help(); break;
751
752 #ifdef ALLOW_SUBSHELL
753 case '!' : WriteChar('!');
754 main_state(); /** reload index screen vars **/
755 redraw += subshell();
756 main_state(); /** reload alias screen vars **/
757 break;
758 #endif /* ALLOW_SUBSHELL */
759
760 case '$': PutLine0(-1, -1, catgets(elm_msg_cat,
761 AliasesSet, AliasesResync,
762 "Resynchronize aliases..."));
763 /*
764 * Process deletions and then see if we need to
765 * re-run the "newalias" routine.
766 */
767 if (resync_aliases(newaliases)) {
768 install_aliases();
769 newaliases = 0;
770 redraw++;
771 }
772 break;
773
774 case 'a': PutLine0(-1, -1, catgets(elm_msg_cat,
775 AliasesSet, AliasesAddCurrent,
776 "Add address from current message..."));
777 clear_error();
778 if (add_current_alias()) {
779 newaliases++;
780 nutitle++;
781 }
782 break;
783
784 case 'c':
785 if (curr_alias > 0) {
786 PutLine0(-1, -1, catgets(elm_msg_cat,
787 AliasesSet, AliasesReplaceCurrent,
788 "Replace current alias in database..."));
789 clear_error();
790 if (add_alias(TRUE, curr_alias-1)) {
791 newaliases++;
792 nutitle++;
793 }
794 }
795 else {
796 error(catgets(elm_msg_cat,
797 AliasesSet, AliasesNoneToReplace,
798 "Warning: no aliases to replace!"));
799 }
800 break;
801
802 case 'e': PutLine1(LINES-3, strlen(nls_Prompt),
803 catgets(elm_msg_cat, AliasesSet, AliasesEdit,
804 "Edit %s..."), ALIAS_TEXT);
805 /*
806 * Process aliases.text for deletions, etc. You
807 * have to do this *before* checking current because
808 * all aliases could be marked for deletion.
809 */
810 (void) resync_aliases(newaliases);
811 if (edit_aliases_text()) {
812 newaliases = 0;
813 }
814 redraw++;
815 break;
816
817 case 'm':
818 if (curr_alias > 0) {
819 PutLine0(-1, -1, catgets(elm_msg_cat,
820 AliasesSet, AliasesMail, "Mail..."));
821 redraw += a_sendmsg();
822 }
823 else {
824 error(catgets(elm_msg_cat,
825 AliasesSet, AliasesNoneToMail,
826 "Warning: no aliases to send mail to!"));
827 }
828 break;
829
830 case 'n': PutLine0(-1, -1, catgets(elm_msg_cat,
831 AliasesSet, AliasesAddNew,
832 "Add a new alias to database..."));
833 clear_error();
834 if (add_alias(FALSE, -1)) {
835 newaliases++;
836 nutitle++;
837 }
838 break;
839
840 case 'q':
841 case 'Q':
842 case 'i':
843 case 'I':
844 case 'r':
845 case 'R': PutLine0(-1, -1, catgets(elm_msg_cat,
846 AliasesSet, AliasesAddReturn,
847 "Return to main menu..."));
848 /*
849 * leaving the alias system. Must check for
850 * pending deletes, etc. prompt is set to FALSE
851 * on uppercase letters so that deletions are
852 * NOT queried.
853 */
854 if (delete_aliases(newaliases, islower(ch))) {
855 install_aliases();
856 newaliases = 0;
857 }
858 clear_error();
859 main_state(); /* Done with aliases. */
860 return;
861
862 case RETURN:
863 case LINE_FEED:
864 case ' ':
865 case 'v':
866 if (newaliases) { /* Need this ?? */
867 error(catgets(elm_msg_cat,
868 AliasesSet, AliasesNotInstalled,
869 "Warning: new aliases not installed yet!"));
870 }
871
872 if (curr_alias > 0) {
873 if (aliases[curr_alias-1]->type & GROUP) {
874 PutLine1(LINES-1, 0, catgets(elm_msg_cat,
875 AliasesSet, AliasesGroupAlias,
876 "Group alias: %-60.60s"),
877 aliases[curr_alias-1]->address);
878 }
879 else {
880 PutLine1(LINES-1, 0, catgets(elm_msg_cat,
881 AliasesSet, AliasesAliasedAddress,
882 "Aliased address: %-60.60s"),
883 aliases[curr_alias-1]->address);
884 }
885 }
886 else {
887 error(catgets(elm_msg_cat,
888 AliasesSet, AliasesNoneToView,
889 "Warning: no aliases to view!"));
890 }
891 break;
892
893 case 'x':
894 case 'X': PutLine0(-1, -1, catgets(elm_msg_cat,
895 AliasesSet, AliasesAddReturn,
896 "Return to main menu..."));
897 exit_alias();
898 clear_error();
899 main_state(); /* Done with aliases. */
900 return;
901
902 case 'f':
903 case 'F':
904 if (curr_alias > 0) {
905 clear_error();
906 strcpy(name, aliases[curr_alias-1]->alias);
907 if (ch == 'F') {
908 strcpy(buffer, catgets(elm_msg_cat,
909 AliasesSet, AliasesFullyExpanded,
910 "Fully expand alias: "));
911 PutLine0(LINES-2, 0, buffer);
912 if (enter_string(name, sizeof(name), -1, -1,
913 ESTR_REPLACE) < 0 || name[0] == '\0')
914 break;
915 }
916 too_long = FALSE;
917 address = get_alias_address(name, TRUE, &too_long);
918 if (address != NULL) {
919 while (TRUE) {
920 ClearScreen();
921 PutLine1(2,0, catgets(elm_msg_cat,
922 AliasesSet, AliasesAliasedFull,
923 "Aliased address for:\t%s\n\r"),
924 name);
925 i = 4;
926 while (i < LINES-2) {
927 if ((commap = index(address, (int)','))
928 == NULL) {
929 PutLine0(i, 4, address);
930 break;
931 }
932 *commap = '\0';
933 PutLine0(i++, 4, address);
934 address = commap+2;
935 }
936 PutLine0(LINES-1, 0, catgets(elm_msg_cat,
937 AliasesSet, AliasesPressReturn,
938 "Press <return> to continue."));
939 (void) ReadCh();
940 if (commap == NULL) {
941 redraw++;
942 break;
943 }
944 }
945 }
946 else if (! too_long) {
947 error(catgets(elm_msg_cat,
948 AliasesSet, AliasesNotFound,
949 "Not found."));
950 }
951 }
952 else {
953 error(catgets(elm_msg_cat,
954 AliasesSet, AliasesNoneToView,
955 "Warning: no aliases to view!"));
956 }
957 break;
958
959 case KEY_REDRAW:
960 redraw = 1;
961 break;
962
963 /*
964 * None of the menu specific commands were chosen, therefore
965 * it must be a "motion" command (or an error).
966 */
967 default : motion(ch);
968
969 }
970
971 if (redraw) { /* Redraw screen if necessary */
972 alias_screen(newaliases);
973 nutitle = 0;
974 }
975
976 if (nutitle) { /* Redraw title if necessary */
977 alias_title(newaliases);
978 nutitle = 0;
979 }
980
981 check_range();
982
983 if (nucurr == NEW_PAGE)
984 show_headers();
985 else if (nucurr == SAME_PAGE)
986 show_current();
987 else if (nufoot) {
988 if (mini_menu) {
989 MoveCursor(LINES-7, 0);
990 CleartoEOS();
991 show_alias_menu();
992 }
993 else {
994 MoveCursor(LINES-4, 0);
995 CleartoEOS();
996 }
997 show_last_error(); /* for those operations that have to
998 * clear the footer except for a message.
999 */
1000 }
1001 } /* BIG while loop... */
1002 }
1003
1004 void
install_aliases()1005 install_aliases()
1006 {
1007 /*
1008 * Run the 'newalias' program and update the
1009 * aliases before going back to the main program!
1010 *
1011 * No return value.....
1012 */
1013
1014 int na;
1015 char itextfile[SLEN], odatafile[SLEN];
1016 char buffer[SLEN];
1017
1018
1019 error(catgets(elm_msg_cat, AliasesSet, AliasesUpdating,
1020 "Updating aliases..."));
1021 if (sleepmsg > 0)
1022 sleep(sleepmsg);
1023
1024 sprintf(itextfile, "%s/%s", user_home, ALIAS_TEXT);
1025 sprintf(odatafile, "%s/%s", user_home, ALIAS_DATA);
1026
1027 /*
1028 * We need to unlimit everything since aliases are
1029 * eing read in from scratch.
1030 */
1031 selected = 0;
1032
1033 na = do_newalias(itextfile, odatafile, TRUE, FALSE);
1034 if (na >= 0) {
1035 error1(catgets(elm_msg_cat, AliasesSet, AliasesReReading,
1036 "Processed %d aliases. Re-reading the database..."), na);
1037 if (sleepmsg > 0)
1038 sleep(sleepmsg);
1039 open_alias_files(TRUE);
1040 set_error(catgets(elm_msg_cat, AliasesSet, AliasesUpdatedOK,
1041 "Aliases updated successfully."));
1042 }
1043 }
1044
alias_help()1045 alias_help()
1046 {
1047 /*
1048 * Help section for the alias menu...
1049 *
1050 * Return non-0 if main part of screen overwritten, else 0
1051 */
1052
1053 int ch;
1054 int redraw=0;
1055 char *alias_prompt;
1056
1057
1058 if (mini_menu)
1059 alias_prompt = catgets(elm_msg_cat, AliasesSet, AliasesShortKey,
1060 "Key: ");
1061 else
1062 alias_prompt = catgets(elm_msg_cat, AliasesSet, AliasesLongKey,
1063 "Key you want help for: ");
1064
1065 MoveCursor(LINES-3, 0);
1066 CleartoEOS();
1067 if (mini_menu) {
1068 CenterLine(LINES-3, catgets(elm_msg_cat, AliasesSet, AliasesKeyMenu,
1069 "Press the key you want help for, '?' for a key list, or '.' to exit help"));
1070 }
1071
1072 lower_prompt(alias_prompt);
1073
1074 while ((ch = ReadCh()) != '.') {
1075 switch(ch) {
1076 case '?' : display_helpfile("alias");
1077 redraw++;
1078 return(redraw);
1079
1080 case '$': error(catgets(elm_msg_cat, AliasesSet, AliasesHelpDollar,
1081 "$ = Force resynchronization of aliases, processing additions and deletions."));
1082 break;
1083
1084 case '/': error(catgets(elm_msg_cat, AliasesSet, AliasesHelpSlash,
1085 "/ = Search for specified name or alias in list."));
1086 break;
1087
1088 case RETURN:
1089 case LINE_FEED:
1090 case ' ':
1091 case 'v': error(catgets(elm_msg_cat, AliasesSet, AliasesHelpv,
1092 "v = View the address for the currently selected alias."));
1093 break;
1094
1095 case 'a': error(catgets(elm_msg_cat, AliasesSet, AliasesHelpa,
1096 "a = Add (return) address of current message to alias database."));
1097 break;
1098
1099 case 'c': error(catgets(elm_msg_cat, AliasesSet, AliasesHelpc,
1100 "c = Change current user alias, modifying alias database at next resync."));
1101 break;
1102
1103 case 'd': error(catgets(elm_msg_cat, AliasesSet, AliasesHelpd,
1104 "d = Mark the current alias for deletion from alias database."));
1105 break;
1106
1107 case ctrl('D'): error(catgets(elm_msg_cat, AliasesSet, AliasesHelpCtrlD,
1108 "^D = Mark for deletion user aliases matching specified pattern."));
1109 break;
1110
1111 case 'e': error(catgets(elm_msg_cat, AliasesSet, AliasesHelpe,
1112 "e = Edit the alias text file directly (will run newalias)."));
1113 break;
1114
1115 case 'f': error(catgets(elm_msg_cat, AliasesSet, AliasesHelpf,
1116 "f = Display fully expanded address of current alias."));
1117 break;
1118
1119 case 'l': error(catgets(elm_msg_cat, AliasesSet, AliasesHelpl,
1120 "l = Limit displayed aliases on the specified criteria."));
1121 break;
1122
1123 case ctrl('L'): error(catgets(elm_msg_cat, AliasesSet, AliasesHelpCtrlL,
1124 "^L = Rewrite the screen."));
1125 break;
1126
1127 case 'm': error(catgets(elm_msg_cat, AliasesSet, AliasesHelpm,
1128 "m = Send mail to the current or tagged aliases."));
1129 break;
1130
1131 case 'n': error(catgets(elm_msg_cat, AliasesSet, AliasesHelpn,
1132 "n = Add a new user alias, adding to alias database at next resync."));
1133 break;
1134
1135 case 'r':
1136 case 'q':
1137 case 'i': error(catgets(elm_msg_cat, AliasesSet, AliasesHelpi,
1138 "r,q,i = Return from alias menu (with prompting)."));
1139 break;
1140
1141 case 'R':
1142 case 'Q':
1143 case 'I': error(catgets(elm_msg_cat, AliasesSet, AliasesHelpQ,
1144 "R,Q,I = Return from alias menu (no prompting)."));
1145 break;
1146
1147 case 't': error(catgets(elm_msg_cat, AliasesSet, AliasesHelpt,
1148 "t = Tag current alias for further operations."));
1149 break;
1150
1151 case 'T': error(catgets(elm_msg_cat, AliasesSet, AliasesHelpT,
1152 "T = Tag current alias and go to next alias."));
1153 break;
1154
1155 case ctrl('T'): error(catgets(elm_msg_cat, AliasesSet, AliasesHelpCtrlT,
1156 "^T = Tag aliases matching specified pattern."));
1157 break;
1158
1159 case 'u': error(catgets(elm_msg_cat, AliasesSet, AliasesHelpu,
1160 "u = Unmark the current alias for deletion from alias database."));
1161 break;
1162
1163 case ctrl('U'): error(catgets(elm_msg_cat, AliasesSet, AliasesHelpCtrlU,
1164 "^U = Mark for undeletion user aliases matching specified pattern."));
1165 break;
1166
1167 case 'x':
1168 case 'X': error(catgets(elm_msg_cat, AliasesSet, AliasesHelpX,
1169 "x = Exit from alias menu, abandoning any pending deletions."));
1170 break;
1171
1172 default : error(catgets(elm_msg_cat, AliasesSet, AliasesHelpNoHelp,
1173 "That key isn't used in this section."));
1174 break;
1175 }
1176 lower_prompt(alias_prompt);
1177 }
1178
1179 /* Remove help lines */
1180 MoveCursor(LINES-3, 0); CleartoEOS();
1181 return(redraw);
1182 }
1183
get_aliases(are_in_aliases)1184 get_aliases(are_in_aliases)
1185 int are_in_aliases;
1186 {
1187 /*
1188 * Get all the system and user alias info
1189 *
1190 * If we get this far, we must be needing to re-read from
1191 * at least one data file. Unfortunately that means we
1192 * really need to read both since the aliases may be sorted
1193 * and all mixed up... :-(
1194 */
1195
1196 char fname[SLEN];
1197 register int i = -1;
1198 int dups = 0;
1199
1200 curr_alias = 0;
1201 num_duplicates = 0;
1202 /*
1203 * Read from user data file if it is open.
1204 */
1205 if (user_hash != NULL) {
1206 dprint(6, (debugfile,
1207 "About to read user data file = %d.\n",
1208 user_hash->dbz_basef));
1209 fseek(user_hash->dbz_basef, 0L, 0);
1210 while (get_one_alias(user_hash, curr_alias)) {
1211 dprint(8, (debugfile, "%d\t%s\t%s\n", curr_alias+1,
1212 aliases[curr_alias]->alias,
1213 aliases[curr_alias]->address));
1214
1215 curr_alias++;
1216 }
1217 }
1218 num_aliases = curr_alias; /* Needed for find_alias() */
1219
1220 /*
1221 * Read from system data file if it is open.
1222 */
1223 if (system_hash != NULL) {
1224 dprint(6, (debugfile,
1225 "About to read system data file = %d.\n",
1226 system_hash->dbz_basef));
1227 fseek(system_hash->dbz_basef, 0L, 0);
1228 while (get_one_alias(system_hash, curr_alias)) {
1229 /*
1230 * If an identical user alias is found, we may
1231 * not want to display it, so we had better mark it.
1232 */
1233 if (find_alias(aliases[curr_alias]->alias, USER) >= 0) {
1234 setit(aliases[curr_alias]->type, DUPLICATE);
1235 dups++;
1236 setit(aliases[curr_alias]->status, URGENT);
1237 /* Not really, I want the U for User */
1238 dprint(6, (debugfile,
1239 "System alias %s is same as user alias.\n",
1240 aliases[curr_alias]->alias));
1241 }
1242 dprint(8, (debugfile, "%d\t%s\t%s\n", curr_alias+1,
1243 aliases[curr_alias]->alias,
1244 aliases[curr_alias]->address));
1245
1246 curr_alias++;
1247 }
1248 num_duplicates = dups;
1249 }
1250 num_aliases = curr_alias - num_duplicates;
1251
1252 if (OPMODE_IS_READMODE(opmode) && num_aliases > 0) {
1253 curr_alias = 0;
1254 sort_aliases((num_aliases+num_duplicates), FALSE, are_in_aliases);
1255 curr_alias = 1;
1256 if (are_in_aliases) {
1257 (void) get_page(curr_alias);
1258 }
1259 }
1260
1261 }
1262
get_one_alias(db,current)1263 get_one_alias(db, current)
1264 DBZ *db;
1265 int current;
1266 {
1267 /*
1268 * Get an alias (name, address, etc.) from the data file
1269 */
1270
1271 int new_max;
1272 register struct alias_rec *a;
1273
1274 if ((a = fetch_alias(db, (char *)NULL)) == NULL)
1275 return 0;
1276
1277 if (current >= max_aliases) {
1278 new_max = max_aliases + KLICK;
1279 if (max_aliases == 0) {
1280 aliases = (struct alias_rec **)
1281 safe_malloc(new_max * sizeof(struct alias_rec *));
1282 } else {
1283 aliases = (struct alias_rec **) safe_realloc((malloc_t)aliases,
1284 new_max * sizeof(struct alias_rec *));
1285 }
1286 while (max_aliases < new_max)
1287 aliases[max_aliases++] = NULL;
1288 }
1289
1290 if (aliases[current] != NULL)
1291 free((malloc_t)aliases[current]);
1292 aliases[current] = a;
1293 return 1;
1294 }
1295
1296
main_state()1297 main_state()
1298 {
1299 /* Save the globals that are shared for both menus
1300 * so that we can return to the main menu without
1301 * "tragedy".
1302 */
1303
1304 static int alias_last = -1, alias_selected = 0, alias_page = 0;
1305 static int main_last = -1, main_selected = 0, main_page = 0;
1306
1307 if (inalias) { /* Restore the settings */
1308 alias_last = last_current;
1309 alias_selected = selected;
1310 alias_page = header_page;
1311
1312 last_current = main_last;
1313 selected = main_selected;
1314 header_page = main_page;
1315
1316 nls_item = catgets(elm_msg_cat, ElmSet, Elmitem, "message");
1317 nls_items = catgets(elm_msg_cat, ElmSet, Elmitems, "messages");
1318 nls_Item = catgets(elm_msg_cat, ElmSet, ElmItem, "Message");
1319 nls_Items = catgets(elm_msg_cat, ElmSet, ElmItems, "Messages");
1320 nls_Prompt = catgets(elm_msg_cat, ElmSet, ElmPrompt, "Command: ");
1321
1322 (void) define_softkeys(SOFTKEYS_MAIN);
1323
1324 dprint(3, (debugfile, "Leaving alias mode\n"));
1325 inalias = FALSE;
1326 }
1327 else {
1328 main_last = last_current;
1329 main_selected = selected;
1330 main_page = header_page;
1331
1332 last_current = alias_last;
1333 selected = alias_selected;
1334 header_page = alias_page;
1335
1336 nls_item = catgets(elm_msg_cat, AliasesSet, Aliasesitem, "alias");
1337 nls_items = catgets(elm_msg_cat, AliasesSet, Aliasesitems, "aliases");
1338 nls_Item = catgets(elm_msg_cat, AliasesSet, AliasesItem, "Alias");
1339 nls_Items = catgets(elm_msg_cat, AliasesSet, AliasesItems, "Aliases");
1340 nls_Prompt = catgets(elm_msg_cat, AliasesSet, AliasesPrompt, "Alias: ");
1341
1342 (void) define_softkeys(SOFTKEYS_ALIAS);
1343
1344 dprint(3, (debugfile, "Entered alias mode\n"));
1345 inalias = TRUE;
1346 }
1347 }
1348
1349 int
parse_aliases(buffer,remainder)1350 parse_aliases(buffer, remainder)
1351 char *buffer, *remainder;
1352 {
1353 /*
1354 * This routine will parse out the individual aliases present
1355 * on the line passed in buffer. This involves:
1356 *
1357 * 1. Testing for an '=' to make sure this is an alias entry.
1358 *
1359 * 2. Setting remainder to point to the rest of the line starting
1360 * at the '=' (for later rewriting if needed).
1361 *
1362 * 3. Parsing the aliases into an string padded with ',' at
1363 * the end.
1364 *
1365 * 4. Returning the number of aliases found (0 if test #1 fails).
1366 */
1367
1368 char *s;
1369 int number;
1370
1371 /* Check to see if an alias */
1372
1373 if ((s = index(buffer, (int)'=')) == NULL)
1374 return (0);
1375
1376 strcpy(remainder, s); /* Save the remainder of the line */
1377
1378 /* Terminate the list of aliases with a ',' */
1379
1380 while (--s >= buffer && whitespace(*s)) ;
1381 *++s = ',';
1382 *++s = '\0';
1383
1384 /* Lowercase everything */
1385
1386 s = shift_lower(buffer);
1387 strcpy(buffer, s);
1388
1389 /* Now, count the aliases */
1390
1391 number = 0;
1392 for (s = buffer; *s; s++)
1393 if (*s == ',')
1394 number++;
1395
1396 return (number);
1397 }
1398
1399 int
get_aliasname(aliasname,buffer,duplicate)1400 get_aliasname(aliasname, buffer, duplicate)
1401 char *aliasname, *buffer;
1402 int *duplicate;
1403 {
1404
1405 /*
1406 * Have the user enter an aliasname, check to see if it
1407 * is legal, then check for duplicates. If a duplicate
1408 * is found offer to replace existing alias.
1409 *
1410 * Return values:
1411 *
1412 * -1 Either the aliasname was zero length, had bad
1413 * characters and was a duplicate which the user
1414 * chose not to replace.
1415 *
1416 * 0 A new alias was entered successfully.
1417 *
1418 * 1 The entered alias was an existing USER alias
1419 * that the user has chosen to replace. In this
1420 * case the alias to replace is passed back in
1421 * in the variable 'duplicate'.
1422 */
1423
1424 int loc;
1425
1426 do {
1427 if (enter_string(aliasname, SLEN,
1428 LINES-2, strlen(buffer), ESTR_REPLACE) < 0
1429 || aliasname[0] == '\0')
1430 return(-1);
1431 } while (check_alias(aliasname) == -1);
1432
1433 clear_error(); /* Just in case */
1434 /*
1435 * Check to see if there is already a USER alias by this name.
1436 */
1437 if ((loc = find_alias(aliasname, USER)) >= 0) {
1438 dprint(3, (debugfile,
1439 "Attempt to add a duplicate alias [%s] in get_aliasname\n",
1440 aliases[loc]->alias));
1441 if (aliases[loc]->type & GROUP )
1442 PutLine1(LINES-2,0, catgets(elm_msg_cat,
1443 AliasesSet, AliasesAlreadyGroup,
1444 "Already a group with name %s."), aliases[loc]->alias);
1445 else
1446 PutLine1(LINES-2,0, catgets(elm_msg_cat,
1447 AliasesSet, AliasesAlreadyAlias,
1448 "Already an alias for %s."), aliases[loc]->alias);
1449 CleartoEOLN();
1450 /*
1451 * If they don't want to replace the alias by that name
1452 * then just return.
1453 */
1454 if (!enter_yn(catgets(elm_msg_cat, AliasesSet,
1455 AliasesReplaceExisting,
1456 "Replace existing alias?"), FALSE, LINES-3, FALSE))
1457 return(-1);
1458 *duplicate = loc;
1459 return(1);
1460 }
1461 /*
1462 * If they have elected to replace an existing alias then
1463 * we assume that they would also elect to superceed a
1464 * system alias by that name (since they have already
1465 * done so). So we don't even bother to check or ask.
1466 *
1467 * Of course we do check if there was no USER alias match.
1468 */
1469 if ((loc = find_alias(aliasname, SYSTEM)) >= 0) {
1470 dprint(3, (debugfile,
1471 "Attempt to add a duplicate system alias [%s] in get_aliasname\n",
1472 aliases[loc]->address));
1473
1474 if( ! superceed_system(loc, buffer))
1475 return(-1);
1476 }
1477 return(0);
1478
1479 }
1480
1481 int
superceed_system(this_alias,buffer)1482 superceed_system(this_alias, buffer)
1483 int this_alias;
1484 char *buffer;
1485 {
1486
1487 PutLine2(LINES-2, 0, catgets(elm_msg_cat,
1488 AliasesSet, AliasesSystemAlias, "System (%6s) alias for %s."),
1489 alias_type(aliases[this_alias]->type), aliases[this_alias]->alias);
1490 /*
1491 * If they don't want to superceed the SYSTEM alias then
1492 * return a FALSE.
1493 */
1494 return enter_yn(catgets(elm_msg_cat, AliasesSet, AliasesSuperceed,
1495 "Superceed?"), FALSE, LINES-3, FALSE);
1496 }
1497
1498 void
get_realnames(aliasname,firstname,lastname,comment,buffer)1499 get_realnames(aliasname, firstname, lastname, comment, buffer)
1500 char *aliasname, *firstname, *lastname, *comment, *buffer;
1501 {
1502 /* FOO - this is not handling enter_string() aborts properly */
1503
1504 sprintf(buffer, catgets(elm_msg_cat, AliasesSet, AliasesEnterLastName,
1505 "Enter last name for %s: "), aliasname);
1506 PutLine0(LINES-2, 0, buffer);
1507 enter_string(lastname, SLEN, -1, -1, ESTR_REPLACE);
1508
1509 sprintf(buffer, catgets(elm_msg_cat, AliasesSet, AliasesEnterFirstName,
1510 "Enter first name for %s: "), aliasname);
1511 PutLine0(LINES-2, 0, buffer);
1512 enter_string(firstname, SLEN, -1, -1, ESTR_REPLACE);
1513
1514 if (strlen(lastname) == 0) {
1515 if (strlen(firstname) == 0) {
1516 strcpy(lastname, aliasname);
1517 }
1518 else {
1519 strcpy(lastname, firstname);
1520 *firstname = '\0';
1521 }
1522 }
1523
1524 sprintf(buffer, catgets(elm_msg_cat, AliasesSet, AliasesEnterComment,
1525 "Enter optional comment for %s: "), aliasname);
1526 PutLine0(LINES-2, 0, buffer);
1527 enter_string(comment, SLEN, -1, -1, ESTR_REPLACE);
1528
1529 }
1530
1531 int
ask_accept(aliasname,firstname,lastname,comment,address,buffer,replace,replacement)1532 ask_accept(aliasname, firstname, lastname, comment, address, buffer,
1533 replace, replacement)
1534 char *aliasname, *firstname, *lastname, *comment, *address, *buffer;
1535 int replace, replacement;
1536 {
1537
1538 int ans;
1539 char *(old_alias[1]);
1540 /*
1541 * If firstname == lastname, they probably just took all
1542 * the deafaults. We *assume* they don't want lastname
1543 * entered twice, so we will truncate it.
1544 */
1545 if (strcmp(firstname, lastname) == 0) {
1546 *firstname = '\0';
1547 }
1548
1549 if (strlen(firstname) == 0) {
1550 strcpy(buffer, lastname);
1551 }
1552 else {
1553 sprintf(buffer, "%s %s", firstname, lastname);
1554 }
1555 PutLine2(LINES-1,0, catgets(elm_msg_cat, AliasesSet, AliasesAddressAs,
1556 "Messages addressed as: %s (%s)"), address, buffer);
1557 if (strlen(comment) != 0) {
1558 strcat(buffer, ", ");
1559 strcat(buffer, comment);
1560 }
1561
1562 PutLine2(LINES-2,0, catgets(elm_msg_cat, AliasesSet, AliasesAddressTo,
1563 "New alias: %s is '%s'."), aliasname, buffer);
1564 CleartoEOLN();
1565 /*
1566 * Kludge Alert: Spaces are padded to the front of the prompt
1567 * to write over the previous question. Should probably record
1568 * the end of the line, move to it, and CleartoEOLN() it.
1569 */
1570 ans = enter_yn(catgets(elm_msg_cat, AliasesSet, AliasesAcceptNew,
1571 " Accept new alias?"), TRUE, LINES-3, FALSE);
1572 if(ans) {
1573 if (replace) {
1574 old_alias[0] = aliases[replacement]->alias;
1575 /*
1576 * First, clear flag if this is marked to be deleted.
1577 * This prevents the problem where they marked it for
1578 * deletion and then figured out that it could be
1579 * c)hanged but didn't explicitly U)ndelete it. Without
1580 * this test, the resync action would then delete
1581 * the new alias we just so carefully added to the
1582 * text file.
1583 */
1584 if (ison(aliases[replacement]->status, DELETED)) {
1585 clearit(aliases[replacement]->status, DELETED);
1586 }
1587 /*
1588 * Changed aliases are given the NEW flag.
1589 */
1590 setit(aliases[replacement]->status, NEW);
1591 show_msg_status(replacement);
1592 /*
1593 * Now we can delete it...
1594 */
1595 delete_from_alias_text(old_alias, 1);
1596 /*
1597 * Kludge Alert: We need to get the trailing comma
1598 * (added in delete_from_alias_text()) off of the
1599 * alias since the display won't be re-sync'd right
1600 * away.
1601 */
1602 *((old_alias[0])+strlen(old_alias[0])-1) = '\0';
1603 }
1604 add_to_alias_text(aliasname, firstname, lastname, comment, address);
1605 }
1606 ClearLine(LINES-2);
1607 ClearLine(LINES-1);
1608 return ans;
1609 }
1610
1611 /* Check whether an address is aliased; if so return the alias, otherwise
1612 * return NULL. */
address_to_alias(address)1613 char *address_to_alias(address)
1614 char *address;
1615 {
1616 int i;
1617 char return_address[SLEN];
1618
1619 (void) open_alias_files(FALSE);
1620
1621 get_return_address(address, return_address);
1622
1623 for (i = 0; i < num_aliases; i++) {
1624 if (istrcmp(return_address, aliases[i]->address) == 0)
1625 return aliases[i]->alias;
1626 }
1627 return NULL;
1628 }
1629