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