1 /*
2    ATP QWK MAIL READER FOR READING AND REPLYING TO QWK MAIL PACKETS.
3    Copyright (C) 1992, 1993, 1997  Thomas McWilliams
4    Copyright (C) 1990  Rene Cougnenc
5 
6    This program is free software; you can redistribute it and/or modify
7    it under the terms of the GNU General Public License as published by
8    the Free Software Foundation; either version 2, or (at your option)
9    any later version.
10 
11    This program is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14    GNU General Public License for more details.
15 
16    You should have received a copy of the GNU General Public License
17    along with this program; if not, write to the Free Software
18    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19  */
20 
21 /*
22 chosetag.c
23 */
24 
25 #define TLMX 60			/* maximum length for tagline */
26 
27 #include <stdio.h>
28 #include <stdlib.h>
29 #include <string.h>
30 
31 #include "reader.h"
32 #include "readlib.h"
33 #include "qlib.h"
34 #include "ansi.h"
35 #include "makemail.h"
36 #ifdef __LCLINT__
37 #include "chosetag.lh"
38 #endif
39 
40 /*
41  * LineCount, count the lines in tagline file.
42  */
43 static unsigned int
LineCount(FILE * FpFrom)44 LineCount(FILE * FpFrom)
45 {
46     int Ch, NLn = 0;
47 
48     while ((Ch = getc(FpFrom)) != EOF) {
49 	if (Ch == (int)'\n')
50 	    NLn++;
51     }
52     return NLn;
53 }
54 
55 /*
56  * InitRandom, seed and initialize random sequence.
57  */
58 static void
InitRandom(void)59 InitRandom(void)
60 {
61     srand((unsigned int) time(NULL));
62 /*  srand ((unsigned int) getpid()   ); <- use this as a last resort */
63     return;
64 }
65 
66 #ifdef __EMX__
67 static const char *TagLine = NTAG;  /* PCBoard style tagline  */
68 static const char *FidoTag = FTAG;  /* Fidonet style tagline  */
69 /*
70  * atp_emx_tag_init, for EMX only: set tagline for DOS or OS/2 at runtime.
71  */
72 static void
atp_emx_tag_init(void)73 atp_emx_tag_init(void)
74 {
75     if (_osmode == DOS_MODE){
76         TagLine = NTAX;
77         FidoTag = FTAX;
78     }
79 }
80 
81 #else
82 static const char CONSPTR TagLine = NTAG;  /* PCBoard style tagline  */
83 static const char CONSPTR FidoTag = FTAG;  /* Fidonet style tagline  */
84 #endif
85 
86 /* current tagline */
87 static char  CurTag[256] = { '\n', NUL_CHAR };
88 
89 /* default tag from atprc config file */
90 static char OrigTag[256] = { '\n', NUL_CHAR };
91 
92 /* run time defined */
93 static char UserTag[256] = { '\n', NUL_CHAR };
94 
95 
96 /*
97  * get_CurTag - provides a copy of the current tagline.
98  */
99 #define TAG_END 84
100 byte *
get_CurTag(void)101 get_CurTag(void)
102 {
103     byte *tmpr;
104     /* truncate tagline to 80 chars */
105     if ( /*@i1 */ CurTag[TAG_END] != NUL_CHAR) {
106 	CurTag[TAG_END] = '\n';
107 	CurTag[TAG_END + 1] = NUL_CHAR;
108     }
109     tmpr = (byte *) strdup(CurTag);
110     test_fatal_malloc(tmpr, __FILE__, __LINE__);
111     return tmpr;
112 }
113 
114 
115 /*
116  * tag_set_by_main - called from main() to setup initial tagline.
117  */
118 void
tag_set_by_main(void)119 tag_set_by_main(void)
120 {
121 #ifdef __EMX__
122     atp_emx_tag_init();
123 #endif
124     /* setup the default TagLines */
125     if (fido)
126 	strcpy(CurTag, FidoTag);
127     else
128 	strcpy(CurTag, TagLine);
129     strcat(CurTag, OrigTag);
130     if (autotag)
131 	ChooseTag();
132     printf("%s\n", CurTag);
133 }
134 
135 
136 /*
137  * init_tagstyle - set tagline style to FIDO or PCBoard per atprc.
138  */
139 void
init_tagstyle(const char * value)140 init_tagstyle(const char *value)
141 {
142     if (stricmp(value, "FIDO") == SUCCESS) {
143 	toglfido();
144 	strcpy(CurTag, FidoTag);
145     } else {
146 	strcpy(CurTag, TagLine);
147     }
148 }
149 
150 /*
151  * BuildNewTag, used by TagSeek() to copy tagline from taglines.atp file.
152  */
153 static void
BuildNewTag(FILE * Fp)154 BuildNewTag(FILE * Fp)
155 {
156     unsigned int charct = 0;
157     char tmptagbuf[TLMX + 50];	/* temporary work buffer */
158     char *crtag = tmptagbuf;
159     int Ch = 0;
160 
161     /* build new tag line */
162     do {
163 	Ch = getc(Fp);
164 	if (Ch != (int)'\r') {
165 	    *crtag = (char) Ch;
166 	    crtag++;
167 	    charct++;
168 	}
169     } while (Ch != EOF && Ch != (int)'\n' && charct < TLMX);
170     if (Ch == EOF) {
171 	printf("unexpected end of file\n");
172     } else {
173 	crtag--;
174 	if (/*@i1*/ *crtag != '\n')
175 	    *crtag = '\n';
176 	crtag++;
177 	*crtag = NUL_CHAR;
178 	if (fido)
179 	    strcpy(CurTag, FidoTag);	/* setup the default TagLines */
180 	else
181 	    strcpy(CurTag, TagLine);
182 	/*@-usedef */
183 	strcat(CurTag, tmptagbuf);
184 	/*@=usedef */
185     }
186 }
187 
188 
189 /*
190  * TagSeek, locate and retrieve a tagline by number.
191  */
192 static void
TagSeek(const unsigned int tagchoice)193 TagSeek(const unsigned int tagchoice)
194 {
195     char ttagpath[MAXPATHS];
196     /*@+voidabstract */
197     FILE *Fp = NULL;
198     /*@=voidabstract */
199 
200     sprintf(ttagpath, "%s%s", HomePath, TAGFILE);
201     if ((Fp = fopen(ttagpath, "rb")) == NULL) {		/* open tagline file */
202 	fprintf(stderr, "Can't open file %s mode %s\n", ttagpath, "read only");
203     } else {
204 	unsigned int NLn = 0;
205 	int Ch = 0;
206 	while (NLn != tagchoice && Ch != EOF) {		/* seek to chosen tagline */
207 	    Ch = getc(Fp);
208 	    if (Ch == (int)'\n')
209 		NLn++;
210 	}
211 	if (Ch == EOF) {
212 	    printf("unexpected end of file\n");
213 	} else {
214 	    BuildNewTag(Fp);
215 	}
216 	fclose(Fp);
217     }
218 }
219 
220 
221 /*
222  * ChooseTag - select a tagline at random from taglines.atp.
223  */
224 void
ChooseTag(void)225 ChooseTag(void)
226 {
227     FILE *Fp;
228     char ttagpath[MAXPATHS];
229 
230     sprintf(ttagpath, "%s%s", HomePath, TAGFILE);
231     if ((Fp = fopen(ttagpath, "rb")) == NULL) {		/* open tagline file */
232 	fprintf(stderr, "Can't open file %s mode %s\n", ttagpath, "read only");
233     } else {
234 	const unsigned int NToChoose = 1;
235 	const unsigned int NSample = LineCount(Fp);
236 	fclose(Fp);
237 	/* the following error can occur if the tagline file is empty */
238 	if (NSample < NToChoose) {
239 	    fprintf(stderr, "\n%s: file appears empty, line count = %u. ( %s:%d )\n",
240 		    ttagpath, NSample, __FILE__, __LINE__);
241 	} else {
242 	    static atp_BOOL_T flag1st = TRUE;
243 	    unsigned int toffset;
244 	    if (flag1st) {
245 		InitRandom();
246 		flag1st = FALSE;
247 	    }
248 	    toffset = (unsigned int) ((rand()) % NSample);
249 	    TagSeek(toffset);
250 	}
251     }
252 }
253 
254 
255 /*
256  * togltag - toggle tagline styles between FIDO and PCBoard.
257  */
258 void
togltag(void)259 togltag(void)
260 {
261     Tag("tag fido");
262 }
263 
264 /*
265  * init_tagpers - get persistent tagline from atprc.
266  */
267 void
init_tagpers(const char * value,const char * sign,const char * aLine)268 init_tagpers(const char *value, const char *sign, const char *aLine)
269 {
270     /* Get persistent tagline */
271     if ( /*@i2 */ *value != NUL_CHAR && *sign == '=') {
272 	const char CONSPTR tptr = strchr(aLine, '=') + 2;
273 	strcpy(OrigTag, tptr);	/* Copy the Original tagline from config */
274 	strcat(OrigTag, "\n");
275     } else {
276 	strcpy(OrigTag, " \n");	/* blank tagline */
277     }
278 }
279 
280 
281 /*
282  * in_edit_reply_mode, when true pause display at end of tagline listing.
283  */
284 static atp_BOOL_T in_edit_reply_mode = FALSE ;
285 
286 /*
287  * tag_set_edit_reply_mode - tells tagview() how to format tagline listing.
288  */
289 void
tag_set_edit_reply_mode(const atp_BOOL_T er_mode)290 tag_set_edit_reply_mode(const atp_BOOL_T er_mode)
291 {
292 	in_edit_reply_mode = er_mode ;
293 }
294 
295 /* -5 is the initial offset needed for a nice display */
296 #define LINE_BIAS -5
297 
298 /*
299  * tagview, view tagline list.
300  */
301 static void
tagview(const char * Path,const char * File)302 tagview(const char *Path, const char *File)
303 {
304     FILE *fp;
305     char tmp[MAXPATHS];
306 
307     sprintf(tmp, "%s%c%s", Path, SEP, File);
308     if ((fp = fopen(tmp, "rb")) == NULL) {
309 	/* "No file" */
310 	red();
311 	printf("%s %s\n", txt[67], tmp);
312     } else {
313 	/* "line" is the index used by the screen output routine */
314 	int line = LINE_BIAS;
315 	/* lines_total provides a reference number for each tagline */
316 	int lines_total = 0;
317 	char buf[301];
318 	CLSCRN();
319 	clear();
320 	cyan();
321 	fflush(stdout);
322 	/*@-usedef */
323 	while (fget(buf, 250, fp)) {
324 	    /*@=usedef */
325 	    line++;
326 	    if (line > (get_ScrnRows() - 7)) {
327 		line = 0;
328 		if (!more(TRUE)) {
329 		    break;
330 		}
331 		cyan();
332 	    }
333 	    printf("%4d: %s\n", lines_total, buf);
334 	    lines_total++;
335 	}
336 	fclose(fp);
337 	printf("\nDefault Tag : %s", OrigTag);
338 	printf("User defined: %s", UserTag);
339 	printf("\n");
340 	/* if in_edit_reply_mode, pause screen display tgm*/
341 	if (in_edit_reply_mode)
342 	    (void)more(TRUE);
343     }
344 }
345 
346 
347 /*
348  *  StealTag, tom glaab's tagline stealer for atp.
349  *  tjg october 1993 (tom glaab)
350  *  tglaab@nooster.navy.mil
351  * StealAsk, prompt user on disposition of stolen tagline.
352  */
353 static void
StealAsk(char * tagtemp)354 StealAsk(char *tagtemp)
355 {
356     char tprompt[80];
357     /* begin common code */
358     clear();
359     yellow();
360     printf("\nyou've selected: ");
361     high();
362     cyan();
363     puts(tagtemp);
364     clear();
365     printf("\n");
366     yellow();
367     sprintf(tprompt, "%s", "do you want to save it to disk? ");
368     high();
369     if (YesNo(YES, tprompt)) {
370 	char ttagpath[MAXPATHS];
371 	FILE *tagfile;
372 	clear();
373 	sprintf(ttagpath, "%s%s", HomePath, TAGFILE);
374 	if ((tagfile = fopen(ttagpath, "a")) != NULL) {
375 	    fputs(tagtemp, tagfile);
376 	    fputc('\n', tagfile);
377 	} else {
378 	    red();
379 	    high();
380 	    fprintf(stderr, "Can't open file %s mode %s\n", ttagpath, "append");
381 	}
382 	clear();
383 	fclose(tagfile);
384     }
385 }
386 
387 
388 /*
389  * StealTag, capture a tagline from the current message.
390  */
391 static void
StealTag(void)392 StealTag(void)
393 {
394     const byte *ptr = (byte *) rbuf + header_SIZE;
395     const byte pcboard_tag_mark = (byte) 254;
396     const byte CONSPTR plimit = ptr + (size_t) get_MsgSize();
397 
398     /* seek to first "square" mark */
399     while (ptr < plimit && /*@i1 */ *ptr != pcboard_tag_mark)
400 	ptr++;
401     /* seek to next "square" mark */
402     while (++ptr < plimit && /*@i2 */ *ptr != (byte) '\n' && *ptr != pcboard_tag_mark)	/* empty loop */
403 	;			/* empty loop */
404     /* found a tagline */
405     if (ptr < plimit && /*@i1 */ *ptr != (byte) '\n') {
406 	char tagtemp[TLMX + 2];
407 	int i = 0;
408 	ptr += 2;
409 	/* copy it to our buffer */
410 	while (ptr < plimit && /*@i1 */ *ptr != (byte) '\n' && i < TLMX) {
411 	    tagtemp[i] = (char) *ptr;
412 	    ptr++;
413 	    i++;
414 	}
415 	/* guarantee that the string is terminated */
416 	tagtemp[i] = NUL_CHAR;
417 	/* prompt user for disposition */
418 	StealAsk(tagtemp);
419     } else {
420 	/* can not find a tagline delimited by the "square" mark */
421 	red();
422 	high();
423 	printf("\nno tag found\n");
424 	clear();
425     }
426 }
427 
428 
429 /*
430  * AddTag, enter a tagline interactively.
431  */
432 static void
AddTag(void)433 AddTag(void)
434 {
435     char *tagtemp, tprompt[80];
436     sprintf(tprompt, "%s", "enter tagline: ");
437     do {
438 	tagtemp = readline(tprompt, do_scroll);
439     } while (tagtemp == NULL);
440     if (tagtemp != NULL) {
441 	if (strlen(tagtemp) > TLMX) {
442 	    printf("too long... \n\n");
443 	} else {
444 	    StealAsk(tagtemp);
445 	}
446 	free_string(tagtemp);
447     }
448 }				/* end addtag */
449 
450 
451 /*
452  * TagHelp, display tagline manager help screen.
453  */
454 static void
TagHelp(void)455 TagHelp(void)
456 {
457     int j = 0;
458     white();
459     high();
460     printf("\n%s", taghlp[1]);
461     clear();
462     printf("\n");
463     for (; j < (int) strlen(taghlp[1]); j++)
464 	(void)putchar('-');
465     printf("\n");
466     high();
467     printf("\t tag list\t%s\n", taghlp[2]);
468     printf("\t tag ?   \t%s\n", taghlp[3]);
469     printf("\t tag `n' \t%s\n", taghlp[4]);
470     printf("\t tag random\t%s\n", taghlp[5]);
471     printf("\t tag swap\t%s\n", taghlp[6]);
472     printf("\t tag auto\t%s\n", taghlp[7]);
473     printf("\t tag     \t%s\n", taghlp[8]);
474     printf("\t tag help\t%s\n", taghlp[9]);
475     printf("\t tag steal\t%s\n", taghlp[11]);
476     printf("\t tag add\t%s\n", taghlp[12]);
477     printf("\t fido    \t%s\n", taghlp[10]);
478     printf("\n");
479     printf("Current TagLine is:");
480     printf("%s\n", CurTag);
481 }
482 
483 
484 /*
485  * TagSwap, called from Tag() to swap taglines.
486  */
487 static atp_BOOL_T
TagSwap(atp_BOOL_T dflag)488 TagSwap(atp_BOOL_T dflag)
489 {
490     dflag = (dflag ? FALSE : TRUE);
491     if (fido)
492 	strcpy(CurTag, FidoTag);
493     else
494 	strcpy(CurTag, TagLine);
495     if (dflag)
496 	strcat(CurTag, OrigTag);
497     else
498 	strcat(CurTag, UserTag);
499     printf("Current Tag now set to:");
500     printf("%s\n", CurTag);
501     return dflag ;
502 }
503 
504 
505 /*
506  * TagAuto, called from Tag() to toggle automatic taglines.
507  */
508 static void
TagAuto(void)509 TagAuto(void)
510 {
511     toglauto();
512     if (autotag) {
513 	printf("\nautotag is ON\n");
514 	ChooseTag();
515 	printf("Current Tag now set to:");
516 	printf("%s\n", CurTag);
517     } else {
518 	printf("\nautotag is OFF\n\n");
519     }
520 }
521 
522 
523 /*
524  * TagList, called from Tag() to list taglines in taglines.atp file.
525  */
526 static void
TagList(char * tmp,char * tmp2)527 TagList(char *tmp, char *tmp2)
528 {
529     sprintf(tmp2, "%s%s", HomePath, TAGFILE);
530     printf("%s\n", tmp2);
531     if (access(tmp2, R_OK) == SUCCESS){
532 	tmp[0] = NUL_CHAR ;
533 	sprintf(tmp, "%s", HomePath);
534 	tagview(tmp, TAGFILE);
535     } else {
536 	printf("\nDefault Tag : %s", OrigTag);
537 	printf("User defined: %s", UserTag);
538 	printf("\n");
539     }
540 }
541 
542 
543 /*
544  * TagNumb, called from Tag() to select a specific numbered tagline from file.
545  */
546 static void
TagNumb(char * tmp)547 TagNumb(char *tmp)
548 {
549     int i = atoi((char *) tmp);
550     i = i < 0 ? -i : i;
551     TagSeek((unsigned) i);
552     printf("Current Tag now set to:");
553     printf("%s\n", CurTag);
554 }
555 
556 /*
557  * TagFido,  toggle tagline styles between fido and pcb.
558  */
559 static void
TagFido(char * tmp)560 TagFido(char *tmp)
561 {
562     strcpy(tmp, CurTag);
563     toglfido();
564     if (fido) {
565 	strcpy(CurTag, FidoTag);
566 	strcat(CurTag, (tmp + strlen(TagLine)));
567     } else {
568 	strcpy(CurTag, TagLine);
569 	strcat(CurTag, (tmp + strlen(FidoTag)));
570     }
571     printf("Current Tag now set to:");
572     printf("%s\n", CurTag);
573 }
574 
575 
576 /*
577  * TagUser, change current tag to user defined tagline.
578  */
579 static atp_BOOL_T
TagUser(const char * line,atp_BOOL_T dflag)580 TagUser(const char *line, atp_BOOL_T dflag)
581 {
582     line += 4;
583     strcpy(UserTag, line);
584     strcat(UserTag, "\n");
585     if (fido)
586 	strcpy(CurTag, FidoTag);
587     else
588 	strcpy(CurTag, TagLine);
589     strcat(CurTag, UserTag);
590     printf("Tag is now set to :");
591     printf("%s\n", CurTag);
592     dflag = FALSE;
593     return dflag ;
594 }
595 
596 
597 static atp_BOOL_T tag_flag = TRUE;
598 /*
599  * get_tag_flag - returns flag indicating if taglines are on or off.
600  */
601 atp_BOOL_T
get_tag_flag(void)602 get_tag_flag(void)
603 {
604 	return tag_flag;
605 }
606 
607 
608 /*
609  * Tag - wrapper to invoke various tagline manager functions.
610  */
611 void
Tag(const char * line)612 Tag(const char *line)
613 {
614     static atp_BOOL_T dflag = FALSE;	/* toggle for default and user defined tagline */
615     char dummy[50], tmp[256], tmp2[256];
616     tmp2[0] = tmp[0] = NUL_CHAR;
617     sscanf(line, "%s %s %s", dummy, tmp, tmp2);
618     if ( /*@i1 */ tmp2[0] == NUL_CHAR) {
619 	if (strnicmp((char *) tmp, "list", 4) == SUCCESS) {	/* list taglines */
620 	    TagList(tmp, tmp2);
621 	} else if (Numeric(tmp)) {	/* try to get a tagline from the list */
622 	    TagNumb(tmp);
623 	} else if ( /*@i1 */ tmp[0] == '?') {	/* Print current tag */
624 	    printf("Current TagLine is:");
625 	    printf("%s\n", CurTag);
626 	} else if (stricmp((char *) tmp, "off") == SUCCESS) {	/* select tag at random  */
627 	    tag_flag = FALSE;
628 	    printf("taglines are now disabled\n");
629 	} else if (stricmp((char *) tmp, "on") == SUCCESS) {	/* select tag at random  */
630 	    tag_flag = TRUE;
631 	    printf("taglines are now enabled\n");
632 	} else if (strnicmp((char *) tmp, "rand", 4) == SUCCESS) {	/* select tag at random  */
633 	    ChooseTag();
634 	    printf("Current Tag now set to:");
635 	    printf("%s\n", CurTag);
636 	} else if ((strnicmp((char *) tmp, "help", 4) == SUCCESS) || /*@i1 */ line[3] == NUL_CHAR) {	/* select tag help menu */
637 	    TagHelp();
638 	} else if (strnicmp((char *) tmp, "auto", 4) == SUCCESS) {	/* toggle autotag line selection */
639 	    TagAuto();
640 	} else if (strnicmp((char *) tmp, "steal", 5) == SUCCESS) {
641 	    StealTag();		/* invoke stealtag (tg) */
642 	} else if (strnicmp((char *) tmp, "add", 3) == SUCCESS) {
643 	    AddTag();		/* add a tagline to your collection (tg) */
644 	} else if (strnicmp((char *) tmp, "fido", 4) == SUCCESS) {
645 	    TagFido(tmp);
646 	} else if (strnicmp((char *) tmp, "swap", 4) == SUCCESS) {	/* restore standard tag */
647 	    dflag = TagSwap(dflag);
648 	}
649     } else if ( /*@i1 */ line[3] == SPC_CHAR) {
650 	dflag = TagUser(line, dflag);
651     }
652 }
653 
654 
655