]> diplodocus.org Git - nmh/blob - docs/historical/mh-jun-1982/progs/scansub.c
Replaced use of snprintf() with memcpy()/memmove().
[nmh] / docs / historical / mh-jun-1982 / progs / scansub.c
1 #ifdef COMMENT
2 Proprietary Rand Corporation, 1981.
3 Further distribution of this software
4 subject to the terms of the Rand
5 license agreement.
6 #endif
7
8 /* the only thing wrong with this version is that
9 the numeric date format needs to be adjusted for
10 the timezone. See adjtime() at the end of the file.
11 -- dave yost, june, 1981
12 */
13 #include "../mh.h"
14 #include <whoami.h>
15 #include <stdio.h>
16 #include <ctype.h>
17 #include <time.h>
18 #include "../adrparse.h"
19 #include "scansub.h"
20
21 #define Block
22
23 #define _FROM 1
24 #define _NOTFROM 0
25
26 #define MSGN 0 /* Start of msg name field */
27 #define SMSGN DMAXFOLDER /* Length */
28 #define SFLGS 2 /* Width of flag field */
29 #define SDATE 7 /* Length of Date field */
30 #define STIME 8 /* Length of time field */
31 #define SNDATE 6 /* Length of numeric date */
32 #define SNTIME 4 /* Length of numeric time */
33 #define SFROM 16 /* Length of " " */
34 #define SLINE 79 /* size of line */
35 #define BSUBJ 20 /* Room needed in Sub field to */
36 /* add stuff from the body */
37
38 FILE *scnout;
39 char scanl[512];
40 int local;
41 int hostseen;
42 char *frmtok();
43
44 scan(inb, innum, outnum, curflg, howdate, header)
45 FILE *inb;
46 int outnum;
47 {
48
49 char buf[BUFSIZ], name[NAMESZ], tobuf[32], frombuf[32];
50 register char *cp, **tok1;
51 int state, subsz, first, compnum;
52 static char *myname;
53 int f_msgn; /* Start of msg name field */
54 int f_smsgn; /* Length */
55 int f_flgs; /* Start of flags field */
56 int f_sflgs; /* Width of flag field */
57 int f_date; /* Start of Date field */
58 int f_sdate; /* Length */
59 int f_from; /* Start of From field */
60 int f_sfrom; /* Length of " " */
61 int f_subj; /* Start of Subject field */
62 int f_ssubj; /* Size of Subject field */
63 int f_bsubj; /* Room needed in Sub field to */
64 /* add stuff from the body */
65
66 f_msgn = MSGN;
67 f_smsgn = SMSGN;
68 f_flgs = f_msgn + f_smsgn;
69 f_sflgs = SFLGS;
70 f_date = f_flgs + f_sflgs;
71
72 switch (howdate) {
73 default:
74 f_sdate = SDATE;
75 break;
76
77 case DOTIME:
78 f_sdate = SDATE + 1 + STIME;
79 break;
80
81 case NUMDATE:
82 f_sdate = SNDATE;
83 break;
84
85 case DOTIME | NUMDATE:
86 f_sdate = SNDATE + SNTIME;
87 break;
88 }
89 f_from = f_date + f_sdate + 1;
90 f_sfrom = SFROM;
91 f_subj = f_from + f_sfrom + 2;
92 f_ssubj = SLINE - f_subj;
93 f_bsubj = BSUBJ;
94
95 local = 0; hostseen = 0;
96 if(!myname)
97 myname = getenv("USER");
98 tobuf[0] = 0; frombuf[0] = 0;
99 first = 0;
100 state = FLD;
101 compnum = 1;
102
103 if (header)
104 printf (" # %-*sFrom Subject [<<Body]\n\n",
105 f_from - f_date - 1,
106 howdate == DOTIME ? "Date Time" : "Date");
107 for(;;) {
108
109 state = m_getfld(state, name, buf, sizeof buf, inb);
110 if(!first++ && state != FILEEOF) { /*##*/
111 if(outnum) {
112 cp = m_name(outnum);
113 if(*cp == '?') /* msg num out of range */
114 return(-2);
115 if((scnout = fopen(cp, "w")) == NULL) {
116 fprintf(stderr, "Error creating msg ");
117 perror(cp); done(-1);
118 }
119 VOID chmod(cp, m_gmprot());
120 }
121 sfill(scanl, sizeof scanl);
122 scanl[sizeof scanl - 1] = 0;
123 subsz = 0;
124 tobuf[0] = 0;
125 }
126
127 switch(state) {
128
129 case FLD:
130 case FLDEOF:
131 case FLDPLUS:
132 compnum++;
133 if(uleq(name, "from"))
134 frombuf[cpyfrm(buf,frombuf,sizeof frombuf,_FROM)]
135 = 0;
136 else if(uleq(name, "date"))
137 cpydat(buf, &scanl[f_date], f_sdate, howdate);
138 else if(uleq(name, "subject") && scanl[f_subj] == ' ')
139 subsz = cpy(buf, &scanl[f_subj], f_ssubj);
140 else if(uleq(name, "to") && !tobuf[0])
141 tobuf[
142 cpyfrm(buf,tobuf,sizeof tobuf-1,_NOTFROM)]=0;
143 else if(uleq(name, "replied"))
144 VOID cpy("-", &scanl[f_flgs+1], 1);
145 put(name, buf, scnout);
146 while(state == FLDPLUS) {
147 state=m_getfld(state,name,buf,sizeof buf,inb);
148 if(scnout)
149 fputs(buf, scnout);
150 }
151 if(state == FLDEOF)
152 goto putscan;
153 continue;
154
155 case BODY:
156 case BODYEOF:
157 compnum = -1;
158 if(buf[0] && subsz < f_ssubj - f_bsubj) {
159 int bodsz;
160 scanl[f_subj+subsz+1] = '<';
161 scanl[f_subj+subsz+2] = '<';
162 bodsz= cpy(buf, scanl+f_subj+subsz+3,
163 f_ssubj-subsz-3);
164 if(bodsz < f_ssubj - subsz - 3)
165 scanl[f_subj+subsz+3 + bodsz] = '>';
166 if(bodsz < f_ssubj - subsz - 4)
167 scanl[f_subj+subsz+4 + bodsz] = '>';
168 subsz = f_ssubj;
169 }
170 if(buf[0] && scnout) {
171 putc('\n', scnout);
172 fputs(buf, scnout);
173 if(ferror(scnout)) {
174 fprintf(stderr, "Write error on ");
175 perror(m_name(outnum));done(-1);
176 }
177 }
178 body:
179 if (!scnout)
180 state = FILEEOF; /* stop now if scan cmd */
181 else while(state == BODY) { /*else inc, so copy body*/
182 state=m_getfld(state,name,buf,sizeof buf,inb);
183 if(state != FILEEOF)
184 fputs(buf, scnout);
185 }
186 if(state == BODYEOF || state == FILEEOF) {
187 putscan: cpymsgn(m_name(innum), &scanl[f_msgn], f_smsgn);
188 tok1= brkstring(getcpy(frombuf), " ", "\n");
189 if(!frombuf[0] || uleq(frombuf, myname) ||
190 (local && uleq(*tok1, myname))) {
191 VOID cpy("To:", &scanl[f_from], 3);
192 VOID cpy(tobuf, &scanl[f_from+3], f_sfrom-3);
193 } else
194 VOID cpy(frombuf, &scanl[f_from], f_sfrom);
195 if(curflg)
196 VOID cpy("+", &scanl[f_flgs], f_sflgs);
197 trim(scanl);
198 fputs(scanl, stdout);
199
200 if(scnout) {
201 VOID fflush(scnout);
202 if(ferror(scnout)) {
203 perror("Write error on ");
204 perror(m_name(outnum));
205 done(-1);
206 }
207 VOID fclose(scnout);
208 scnout = NULL;
209 }
210 return(1);
211 }
212 break;
213
214 case LENERR:
215 case FMTERR:
216 fprintf(stderr, "??Message Format Error ");
217 fprintf(stderr, "(Message %d) ", outnum ? outnum :innum);/*##*/
218 if(compnum < 0) fprintf(stderr, "in the Body.\n");
219 else fprintf(stderr, "in Component #%d.\n", compnum);
220 fprintf(stderr, "-----------------------------------------");
221 fprintf(stderr, "-------------------------------------\n");
222 goto badret;
223 default:
224 fprintf(stderr, "Getfld returned %d\n", state);
225
226
227 badret: if(outnum) {
228 fputs("\n\nBAD MSG:\n", scnout);
229 if(compnum < 0)
230 fputs(buf, scnout);
231 else {
232 fputs(name, scnout);
233 putc('\n', scnout);
234 }
235 /*** ungetc(inb); ***/
236 state = BODY;
237 goto body;
238
239 }
240 if(scnout)
241 VOID fflush(scnout);
242 return(-1);
243 case FILEEOF:
244 return(0);
245
246 }
247
248 }
249 }
250
251
252 trim(str)
253 char *str;
254 {
255 register char *cp;
256
257 cp = str;
258 while(*cp) cp++;
259 while(*--cp == ' ') ;
260 cp++;
261 *cp++ = '\n';
262 *cp++ = 0;
263 }
264
265 sfill(str, cnt)
266 char *str;
267 {
268 register char *cp;
269 register int i;
270
271 cp = str; i = cnt;
272 do
273 *cp++ = ' ';
274 while(--i);
275 }
276
277
278 put(name, buf, ip)
279 char *name, *buf;
280 register FILE *ip;
281 {
282 if(ip) {
283 fputs(name, ip);
284 putc(':', ip);
285 fputs(buf, ip);
286 if(ferror(ip)) { perror("Write error");done(-1);}
287 }
288 }
289
290
291 cpy(from, to, cnt)
292 register char *from, *to;
293 register int cnt;
294 {
295 register int c;
296 char *savto;
297
298 savto = to;
299 while(*from == ' ' || *from == '\t' || *from == '\n' || *from == '\f')
300 from++;
301 while(cnt--)
302 if(c = *from) {
303 if(c == '\t' || c == ' ' || c == '\n' || c == '\f') {
304 *to++ = ' ';
305 do
306 from++;
307 while((c= *from)==' '||c=='\t'||c=='\n'||c=='\f');
308 continue;
309 } else {
310 *to++ = c;
311 from++;
312 }
313 } else
314 break;
315 return(to - savto); /*Includes 1 char trailing white space, if any*/
316 }
317
318 struct tm *localtime();
319 long time();
320 char *findmonth();
321
322 struct date {
323 char *day;
324 char *month;
325 char *year;
326 char *timestr;
327 char *zone;
328 char zoneadd;
329 };
330
331 cpydat(sfrom, sto, cnt, how)
332 char *sfrom, *sto;
333 {
334 register char *cp;
335 register char *to;
336 static struct tm *locvec;
337 char frombuf[100];
338 char buf[30]; /* should be char buf[cnt + 1] */
339 long now;
340 struct date dt;
341
342 strncpy(frombuf, sfrom, sizeof frombuf);
343 frombuf[sizeof frombuf -1] = '\0';
344 if(!locvec) {
345 now = time((long *)0);
346 locvec = localtime(&now);
347 }
348
349 /* Collect the various fields of the date */
350 for(cp = frombuf; *cp < '0' || *cp > '9'; cp++)
351 if(!*cp)
352 return;
353
354 /* get the day */
355 dt.day = cp;
356 while (isdigit(*cp))
357 cp++;
358 if (*cp)
359 *cp++ = '\0';
360
361 /* get the month */
362 while (*cp && !isalpha(*cp))
363 cp++;
364 dt.month = cp;
365 while (isalpha (*cp))
366 cp++;
367 if (*cp)
368 *cp++ = '\0';
369
370 /* get the year */
371 while (*cp && !isdigit(*cp))
372 cp++;
373 dt.year = cp;
374 while (isdigit(*cp))
375 cp++;
376 if (*cp)
377 *cp++ = '\0';
378
379 /* Point timestr at the time, and remove colons, if present */
380 while (*cp && !isdigit(*cp))
381 cp++;
382 dt.timestr = to = cp;
383 for (; isdigit(*cp) || *cp == ':'; cp++)
384 if (*cp != ':')
385 *to++ = *cp;
386 if (*cp)
387 cp++;
388 *to = '\0';
389
390 /* get the time zone. */
391 /* Can be alphas as in PST */
392 /* If plus/minus digits, then set zoneadd to the + or - */
393 /* point zone at the string of digits or alphas */
394 dt.zoneadd = '\0';
395 while (*cp && !isalpha(*cp) && !isdigit(*cp)) {
396 if (*cp == '+' || *cp == '-')
397 dt.zoneadd = *cp;
398 cp++;
399 }
400 dt.zone = cp;
401 if (isdigit(*cp))
402 while (isdigit (*cp))
403 cp++;
404 else {
405 dt.zoneadd = '\0';
406 while (isalpha (*cp))
407 cp++;
408 }
409 if (*cp)
410 *cp++ = '\0';
411
412 /* printf ("Yr='%s' Mo='%s' Day='%s' Time='%s' Zone='%s'\n",
413 dt.year, dt.month, dt.day, dt.timestr, dt.zone);
414 if(cp = findmonth(dt.month))
415 printf ("month='%s'\n", cp);
416 return;
417 /**/
418 to = buf;
419 if(cp = findmonth(dt.month)) {
420 if (how & NUMDATE) {
421 adjtime(&dt);
422 if(strlen(dt.year) >= 2) {
423 cp = &dt.year[strlen(dt.year) - 2];
424 *to++ = *cp++;
425 *to++ = *cp++;
426 }
427 else {
428 *to++ = ' ';
429 *to++ = ' ';
430 }
431 if ((cp = findmonth(dt.month))[1])
432 *to++ = *cp++;
433 else
434 *to++ = '0';
435 *to++ = *cp++;
436 if (*(cp = dt.day)) {
437 if (cp[1])
438 *to++ = *cp++;
439 else
440 *to++ = '0';
441 *to++ = *cp++;
442 }
443 else {
444 *to++ = ' ';
445 *to++ = ' ';
446 }
447 *to = '\0';
448 if (how & DOTIME) {
449 /* kludge for now */
450 dt.timestr[4] = '\0';
451 strcpy (to, dt.timestr);
452 }
453 }
454 else {
455 if(!cp[1])
456 *to++ = ' ';
457 while(*cp)
458 *to++ = *cp++;
459 *to++ = '/';
460
461 cp = dt.day;
462 if(!cp[1])
463 *to++ = ' ';
464 while(*cp >= '0' && *cp <= '9')
465 *to++ = *cp++;
466 Block {
467 register int yr;
468 if( ( (yr = atoi(dt.year)) > 1970
469 && yr - 1900 < locvec->tm_year
470 )
471 || yr < locvec->tm_year
472 ) {
473 *to++ = '/';
474 *to++ = (yr - (yr < 100 ? 70 : 1970))
475 % 10 + '0';
476 }
477 else {
478 *to++ = ' ';
479 *to++ = ' ';
480 }
481 }
482 *to = '\0';
483 if (how & DOTIME) {
484 *to++ = ' ';
485 sprintf (to, "%4.4s", dt.timestr);
486 to += 4;
487 if (*dt.zone) {
488 *to++ = '-';
489 strncpy(to, dt.zone, 3);
490 }
491 }
492 }
493 }
494 else {
495 cp = dt.day;
496 if(!cp[1])
497 *to++ = ' ';
498 while(*cp)
499 *to++ = *cp++;
500 }
501 Block {
502 register int tmp;
503 if (cnt < (tmp = strlen(buf)))
504 tmp = cnt;
505 strncpy(sto, buf, tmp);
506 }
507 return;
508 }
509
510
511 char *fromp, fromdlm, pfromdlm;
512
513 cpyfrm(sfrom, sto, cnt, fromcall)
514 char *sfrom, *sto;
515 {
516 register char *to, *cp;
517 register int c;
518
519 fromdlm = ' ';
520 fromp = sfrom; to = sto;
521 cp = frmtok();
522 do
523 if(c = *cp++)
524 *to++ = c;
525 else
526 break;
527 while(--cnt);
528 for(;;) {
529 if(cnt < 3) break;
530 if(*(cp = frmtok()) == 0) break;
531 if(*cp == '@' || uleq(cp, "at")) {
532 cp = frmtok();
533 if(uleq(cp, HOSTNAME)) {
534 /* if the first "From:" host is local */
535 if(fromcall != _NOTFROM && !hostseen++)
536 local++;
537 } else {
538 *to++ = '@';
539 cnt--;
540 do
541 if(c = *cp++)
542 *to++ = c;
543 else
544 break;
545 while(--cnt);
546 }
547 } else if(cnt > 4) {
548 cnt--; *to++ = pfromdlm;
549 do
550 if(c = *cp++)
551 *to++ = c;
552 else
553 break;
554 while(--cnt);
555 }
556 }
557 if(fromcall != _NOTFROM)
558 hostseen++;
559 return(to - sto);
560 }
561
562
563 char *frmtok()
564 {
565 static char tokbuf[64];
566 register char *cp;
567 register int c;
568
569 pfromdlm = fromdlm;
570 cp = tokbuf; *cp = 0;
571 while(c = *fromp++) {
572 if(c == '\t')
573 c = ' ';
574 if(c == ' ' && cp == tokbuf)
575 continue;
576 if(c == ' ' || c == '\n' || c == ',')
577 break;
578 *cp++ = c;
579 *cp = 0;
580 if(c == '@' || *fromp == '@' || cp == &tokbuf[63])
581 break;
582 }
583 fromdlm = c;
584 return(tokbuf);
585 }
586
587
588 /* num specific! */
589
590 /* copy msgnam to addr, right justified */
591 cpymsgn(msgnam, addr, len)
592 char *msgnam, *addr;
593 {
594 register char *cp, *sp;
595
596 sp = msgnam;
597 cp = &addr[len - strlen(sp)];
598 if (cp < addr)
599 cp = addr;
600 while(*sp)
601 *cp++ = *sp++;
602 }
603
604 char *monthtab[] = {
605 "jan", "feb", "mar", "apr", "may", "jun",
606 "jul", "aug", "sep", "oct", "nov", "dec",
607 };
608
609 char *findmonth(str)
610 char *str;
611 {
612 register char *cp, *sp;
613 register int i;
614 static char buf[4];
615
616 for(cp=str, sp=buf; (*sp++ = *cp++) && sp < &buf[3] && *cp != ' '; )
617 continue;
618 *sp = 0;
619 for(i = 0; i < 12; i++)
620 if(uleq(buf, monthtab[i])) {
621 VOID sprintf(buf, "%d", i+1);
622 return buf;
623 }
624 return(0);
625 }
626
627 struct tzone {
628 char *z_nam;
629 int z_hour;
630 int z_min;
631 };
632 struct tzone zonetab[] = {
633 { "GMT", 0, 0, },
634 { "NST", -3, -30, },
635 { "AST", -4, 0, },
636 { "ADT", -3, 0, },
637 { "EST", -5, 0, },
638 { "EDT", -4, 0, },
639 { "CST", -6, 0, },
640 { "CDT", -5, 0, },
641 { "MST", -7, 0, },
642 { "MDT", -6, 0, },
643 { "PST", -8, 0, },
644 { "PDT", -7, 0, },
645 { "YST", -9, 0, },
646 { "YDT", -8, 0, },
647 { "HST", -10, 0, },
648 { "HDT", -9, 0, },
649 { "BST", -11, 0, },
650 { "BDT", -10, 0, },
651 { "Z", 0, 0, },
652 { "A", -1, 0, },
653 { "M", -12, 0, },
654 { "N", 1, 0, },
655 { "Y", 12, 0, },
656 { 0 }
657 };
658
659 /* adjust for timezone */
660 adjtime(dt)
661 register struct date *dt;
662 {
663 /* what we should do here is adjust all other timezones to our own */
664 return;
665
666 /* if (isdigit (dt->zone[0])) {
667 atoi ...
668 if (dt->zoneadd == '+')
669 ;
670 }
671 else {
672 }
673 return;