|
|
1.1 ! root 1: /* formatsbr.c - format string interpretation */ ! 2: ! 3: #include "../h/mh.h" ! 4: #include "../h/addrsbr.h" ! 5: #include "../h/formatsbr.h" ! 6: #include "../zotnet/tws.h" ! 7: #include "../h/fmtcompile.h" ! 8: #include <ctype.h> ! 9: #include <stdio.h> ! 10: #include <sys/types.h> ! 11: #include <sys/stat.h> ! 12: ! 13: /* */ ! 14: ! 15: ! 16: #define NFMTS MAXARGS ! 17: #define QUOTE '\\' ! 18: ! 19: static char *formats = 0; ! 20: extern char *formataddr (); /* hook for custom address formatting */ ! 21: ! 22: int fmt_norm = AD_NAME; ! 23: struct mailname fmt_mnull; ! 24: ! 25: /* */ ! 26: ! 27: /* MAJOR HACK: See MHCHANGES for discussion */ ! 28: ! 29: char *new_fs (form, format, def) ! 30: register char *form, ! 31: *format, ! 32: *def; ! 33: { ! 34: struct stat st; ! 35: register FILE *fp; ! 36: ! 37: if (formats) ! 38: free (formats); ! 39: ! 40: if (form) { ! 41: if ((fp = fopen (libpath (form), "r")) == NULL) ! 42: adios (form, "unable to open format file"); ! 43: ! 44: if (fstat (fileno (fp), &st) == NOTOK) ! 45: adios (form, "unable to stat format file"); ! 46: ! 47: if ((formats = malloc ((unsigned) st.st_size)) == NULLCP) ! 48: adios (form, "unable to allocate space for format"); ! 49: ! 50: if (read (fileno(fp), formats, st.st_size) != st.st_size) ! 51: adios (form, "error reading format file"); ! 52: ! 53: (void) fclose (fp); ! 54: } ! 55: else { ! 56: formats = getcpy (format ? format : def); ! 57: } ! 58: ! 59: normalize (formats); ! 60: ! 61: return formats; ! 62: } ! 63: ! 64: /* */ ! 65: ! 66: static normalize (cp) ! 67: register char *cp; ! 68: { ! 69: register char *dp; ! 70: ! 71: for (dp = cp; *cp; cp++) ! 72: if (*cp != QUOTE) ! 73: *dp++ = *cp; ! 74: else ! 75: switch (*++cp) { ! 76: #define grot(x) case 'x': *dp++ = '\x'; break; ! 77: grot (b); ! 78: grot (f); ! 79: grot (n); ! 80: grot (r); ! 81: grot (t); ! 82: ! 83: case '\n': ! 84: break; ! 85: ! 86: case NULL: ! 87: cp--; /* fall */ ! 88: default: ! 89: *dp++ = *cp; ! 90: break; ! 91: } ! 92: ! 93: *dp = NULL; ! 94: } ! 95: ! 96: /* */ ! 97: /* ! 98: * test if string "sub" appears anywhere in string "str" ! 99: * (case insensitive). ! 100: */ ! 101: ! 102: static int match (str, sub) ! 103: register char *str, ! 104: *sub; ! 105: { ! 106: register int c1; ! 107: register int c2; ! 108: register char *s1; ! 109: register char *s2; ! 110: ! 111: while (c1 = *sub) { ! 112: while ((c2 = *str++) && (c1 | 040) != (c2 | 040)) ! 113: ; ! 114: if (! c2) ! 115: return 0; ! 116: s1 = sub + 1; s2 = str; ! 117: while ((c1 = *s1++) && (c1 | 040) == (*s2++ | 040)) ! 118: ; ! 119: if (! c1) ! 120: return 1; ! 121: } ! 122: return 1; ! 123: } ! 124: /* */ ! 125: ! 126: /* macros to format data */ ! 127: ! 128: #define PUTDF(cp, num, wid, fill) if (cp + wid < ep){\ ! 129: if((i = (num))<0) i = -(num);\ ! 130: sp = cp + wid;\ ! 131: do {\ ! 132: *--sp = (i % 10) + '0';\ ! 133: i /= 10;\ ! 134: } while (i > 0 && sp > cp);\ ! 135: if (i > 0)\ ! 136: *sp = '?';\ ! 137: else if ((num) < 0 && sp > cp)\ ! 138: *--sp = '-';\ ! 139: while (sp > cp)\ ! 140: *--sp = fill;\ ! 141: cp += wid;\ ! 142: } ! 143: #define PUTD(cp, num) if (cp < ep){\ ! 144: if((i = (num))==0) *cp++ = '0';\ ! 145: else {\ ! 146: if((i = (num))<0) \ ! 147: *cp++ = '-', i = -(num);\ ! 148: c = 10;\ ! 149: while (c <= i) \ ! 150: c *= 10;\ ! 151: while (cp < ep && c > 1) {\ ! 152: c /= 10;\ ! 153: *cp++ = (i / c) + '0';\ ! 154: i %= c;\ ! 155: }\ ! 156: }\ ! 157: } ! 158: #define PUTSF(cp, str, wid, fill) {\ ! 159: i = (wid);\ ! 160: if (sp = (str)) {\ ! 161: while ((c = *sp) && c <= 32)\ ! 162: sp++;\ ! 163: while( (c = *sp++) && --i >= 0 && cp < ep)\ ! 164: if ( c > 32 ) \ ! 165: *cp++ = c;\ ! 166: else {\ ! 167: while ( (c = *sp) && c <= 32 )\ ! 168: sp++;\ ! 169: *cp++ = ' ';\ ! 170: }\ ! 171: }\ ! 172: while( --i >= 0 && cp < ep)\ ! 173: *cp++ = fill;\ ! 174: } ! 175: #define PUTS(cp, str) {\ ! 176: if (sp = (str)) {\ ! 177: while ((c = *sp) && c <= 32)\ ! 178: sp++;\ ! 179: while( (c = *sp++) && cp < ep)\ ! 180: if ( c > 32 ) \ ! 181: *cp++ = c;\ ! 182: else {\ ! 183: while ( (c = *sp) && c <= 32 )\ ! 184: sp++;\ ! 185: *cp++ = ' ';\ ! 186: }\ ! 187: }\ ! 188: } ! 189: ! 190: ! 191: static char *lmonth[] = { "January", "February","March", "April", ! 192: "May", "June", "July", "August", ! 193: "September","October", "November","December" }; ! 194: ! 195: ! 196: fmtscan (format, scanl, width, dat) ! 197: struct format *format; ! 198: char *scanl; ! 199: int width; ! 200: int dat[]; ! 201: { ! 202: register char *cp = scanl; ! 203: register char *ep = scanl + width - 1; ! 204: register struct format *fmt = format; ! 205: register char *str = NULLCP; ! 206: register int value = 0; ! 207: register char *sp; ! 208: register int i; ! 209: register int c; ! 210: register struct comp *comp; ! 211: register struct tws *tws; ! 212: register struct mailname *mn; ! 213: char *savestr; ! 214: char buffer[BUFSIZ]; ! 215: ! 216: while (cp < ep) { ! 217: switch (fmt->f_type) { ! 218: ! 219: case FT_COMP: ! 220: PUTS (cp, fmt->f_comp->c_text); ! 221: break; ! 222: case FT_COMPF: ! 223: PUTSF (cp, fmt->f_comp->c_text, fmt->f_width, fmt->f_fill); ! 224: break; ! 225: ! 226: case FT_LIT: ! 227: sp = fmt->f_text; ! 228: while( (c = *sp++) && cp < ep) ! 229: *cp++ = c; ! 230: break; ! 231: case FT_LITF: ! 232: sp = fmt->f_text; i = fmt->f_width; ! 233: while( (c = *sp++) && --i >= 0 && cp < ep) ! 234: *cp++ = c; ! 235: while( --i >= 0 && cp < ep) ! 236: *cp++ = fmt->f_fill; ! 237: break; ! 238: ! 239: case FT_STR: ! 240: PUTS (cp, str); ! 241: break; ! 242: case FT_STRF: ! 243: PUTSF (cp, str, fmt->f_width, fmt->f_fill); ! 244: break; ! 245: case FT_STRFW: ! 246: adios (NULLCP, "internal error (FT_STRFW)"); ! 247: ! 248: case FT_NUM: ! 249: PUTD (cp, value); ! 250: break; ! 251: case FT_NUMF: ! 252: PUTDF (cp, value, fmt->f_width, fmt->f_fill); ! 253: break; ! 254: ! 255: case FT_CHAR: ! 256: *cp++ = fmt->f_char; ! 257: break; ! 258: ! 259: case FT_DONE: ! 260: goto finished; ! 261: ! 262: case FT_IF_S: ! 263: if (str == NULLCP || *str == NULL) { ! 264: fmt += fmt->f_skip; ! 265: continue; ! 266: } ! 267: break; ! 268: ! 269: case FT_IF_S_NULL: ! 270: if (str != NULLCP && *str != NULL) { ! 271: fmt += fmt->f_skip; ! 272: continue; ! 273: } ! 274: break; ! 275: ! 276: case FT_IF_V_EQ: ! 277: if (value != fmt->f_value) { ! 278: fmt += fmt->f_skip; ! 279: continue; ! 280: } ! 281: break; ! 282: ! 283: case FT_IF_V_NE: ! 284: if (value == fmt->f_value) { ! 285: fmt += fmt->f_skip; ! 286: continue; ! 287: } ! 288: break; ! 289: ! 290: case FT_IF_V_GT: ! 291: if (value <= fmt->f_value) { ! 292: fmt += fmt->f_skip; ! 293: continue; ! 294: } ! 295: break; ! 296: ! 297: case FT_IF_MATCH: ! 298: if (! match (str, fmt->f_text)) { ! 299: fmt += fmt->f_skip; ! 300: continue; ! 301: } ! 302: break; ! 303: ! 304: case FT_V_MATCH: ! 305: value = match (str, fmt->f_text); ! 306: break; ! 307: ! 308: case FT_IF_AMATCH: ! 309: if (! uprf (str, fmt->f_text)) { ! 310: fmt += fmt->f_skip; ! 311: continue; ! 312: } ! 313: break; ! 314: ! 315: case FT_V_AMATCH: ! 316: value = uprf (str, fmt->f_text); ! 317: break; ! 318: ! 319: case FT_S_NONNULL: ! 320: value = (str != NULLCP && *str != NULL); ! 321: break; ! 322: ! 323: case FT_S_NULL: ! 324: value = (str == NULLCP || *str == NULL); ! 325: break; ! 326: ! 327: case FT_V_EQ: ! 328: value = (fmt->f_value == value); ! 329: break; ! 330: ! 331: case FT_V_NE: ! 332: value = (fmt->f_value != value); ! 333: break; ! 334: ! 335: case FT_V_GT: ! 336: value = (fmt->f_value > value); ! 337: break; ! 338: ! 339: case FT_GOTO: ! 340: fmt += fmt->f_skip; ! 341: continue; ! 342: ! 343: case FT_NOP: ! 344: break; ! 345: ! 346: case FT_LS_COMP: ! 347: str = fmt->f_comp->c_text; ! 348: break; ! 349: case FT_LS_LIT: ! 350: str = fmt->f_text; ! 351: break; ! 352: ! 353: case FT_LV_COMPFLAG: ! 354: value = fmt->f_comp->c_flags; ! 355: break; ! 356: case FT_LV_COMP: ! 357: value = (comp = fmt->f_comp)->c_text ? atoi(comp->c_text) : 0; ! 358: break; ! 359: case FT_LV_LIT: ! 360: value = fmt->f_value; ! 361: break; ! 362: case FT_LV_DAT: ! 363: value = dat[fmt->f_value]; ! 364: break; ! 365: case FT_LV_STRLEN: ! 366: value = strlen(str); ! 367: break; ! 368: case FT_LV_CHAR_LEFT: ! 369: value = width - (cp - scanl); ! 370: break; ! 371: case FT_LV_PLUS_L: ! 372: value += fmt->f_value; ! 373: break; ! 374: case FT_LV_MINUS_L: ! 375: value = fmt->f_value - value; ! 376: break; ! 377: case FT_SAVESTR: ! 378: savestr = str; ! 379: break; ! 380: ! 381: case FT_LV_SEC: ! 382: value = fmt->f_comp->c_tws->tw_sec; ! 383: break; ! 384: case FT_LV_MIN: ! 385: value = fmt->f_comp->c_tws->tw_min; ! 386: break; ! 387: case FT_LV_HOUR: ! 388: value = fmt->f_comp->c_tws->tw_hour; ! 389: break; ! 390: case FT_LV_MDAY: ! 391: value = fmt->f_comp->c_tws->tw_mday; ! 392: break; ! 393: case FT_LV_MON: ! 394: value = fmt->f_comp->c_tws->tw_mon + 1; ! 395: break; ! 396: case FT_LS_MONTH: ! 397: str = tw_moty[fmt->f_comp->c_tws->tw_mon]; ! 398: break; ! 399: case FT_LS_LMONTH: ! 400: str = lmonth[fmt->f_comp->c_tws->tw_mon]; ! 401: break; ! 402: case FT_LS_ZONE: ! 403: str = dtwszone (fmt->f_comp->c_tws); ! 404: break; ! 405: case FT_LV_YEAR: ! 406: value = fmt->f_comp->c_tws->tw_year; ! 407: break; ! 408: case FT_LV_WDAY: ! 409: if (!(((tws = fmt->f_comp->c_tws)->tw_flags) & (TW_SEXP|TW_SIMP))) ! 410: set_dotw (tws); ! 411: value = tws->tw_wday; ! 412: break; ! 413: case FT_LS_DAY: ! 414: if (!(((tws = fmt->f_comp->c_tws)->tw_flags) & (TW_SEXP|TW_SIMP))) ! 415: set_dotw (tws); ! 416: str = tw_dotw[tws->tw_wday]; ! 417: break; ! 418: case FT_LS_WEEKDAY: ! 419: if (!(((tws = fmt->f_comp->c_tws)->tw_flags) & (TW_SEXP|TW_SIMP))) ! 420: set_dotw (tws); ! 421: str = tw_ldotw[tws->tw_wday]; ! 422: break; ! 423: case FT_LV_YDAY: ! 424: value = fmt->f_comp->c_tws->tw_yday; ! 425: break; ! 426: case FT_LV_ZONE: ! 427: value = fmt->f_comp->c_tws->tw_zone; ! 428: break; ! 429: case FT_LV_CLOCK: ! 430: if ((value = fmt->f_comp->c_tws->tw_clock) == 0) ! 431: value = twclock(fmt->f_comp->c_tws); ! 432: break; ! 433: case FT_LV_RCLOCK: ! 434: if ((value = fmt->f_comp->c_tws->tw_clock) == 0) ! 435: value = twclock(fmt->f_comp->c_tws); ! 436: value = time((long *) 0) - value; ! 437: break; ! 438: case FT_LV_DAYF: ! 439: if (!(((tws = fmt->f_comp->c_tws)->tw_flags) & (TW_SEXP|TW_SIMP))) ! 440: set_dotw (tws); ! 441: switch (fmt->f_comp->c_tws->tw_flags & TW_SDAY) { ! 442: case TW_SEXP: ! 443: value = 1; break; ! 444: case TW_SIMP: ! 445: value = 0; break; ! 446: default: ! 447: value = -1; break; ! 448: } ! 449: break; ! 450: case FT_LV_TZONEF: ! 451: value = fmt->f_comp->c_tws->tw_flags & TW_DST; ! 452: break; ! 453: case FT_LS_822DATE: ! 454: str = dasctime ( fmt->f_comp->c_tws , TW_ZONE); ! 455: break; ! 456: case FT_LS_PRETTY: ! 457: str = dasctime ( fmt->f_comp->c_tws, TW_NULL); ! 458: break; ! 459: ! 460: case FT_LS_PERS: ! 461: str = fmt->f_comp->c_mn->m_pers; ! 462: break; ! 463: case FT_LS_MBOX: ! 464: str = fmt->f_comp->c_mn->m_mbox; ! 465: break; ! 466: case FT_LS_HOST: ! 467: str = fmt->f_comp->c_mn->m_host; ! 468: break; ! 469: case FT_LS_PATH: ! 470: str = fmt->f_comp->c_mn->m_path; ! 471: break; ! 472: case FT_LS_GNAME: ! 473: str = fmt->f_comp->c_mn->m_gname; ! 474: break; ! 475: case FT_LS_NOTE: ! 476: str = fmt->f_comp->c_mn->m_note; ! 477: break; ! 478: case FT_LS_822ADDR: ! 479: str = adrformat( fmt->f_comp->c_mn ); ! 480: break; ! 481: case FT_LV_HOSTTYPE: ! 482: value = fmt->f_comp->c_mn->m_type; ! 483: break; ! 484: case FT_LV_INGRPF: ! 485: value = fmt->f_comp->c_mn->m_ingrp; ! 486: break; ! 487: case FT_LV_NOHOSTF: ! 488: value = fmt->f_comp->c_mn->m_nohost; ! 489: break; ! 490: case FT_LS_FRIENDLY: ! 491: #ifdef BERK ! 492: str = fmt->f_comp->c_mn->m_mbox; ! 493: #else not BERK ! 494: mn = fmt -> f_comp -> c_mn; ! 495: if ((str = mn -> m_pers) == NULL) ! 496: switch (mn -> m_type) { ! 497: case LOCALHOST: ! 498: str = mn -> m_mbox; ! 499: break; ! 500: case UUCPHOST: ! 501: (void) sprintf (buffer, "%s!%s", ! 502: mn -> m_host, mn -> m_mbox); ! 503: str = buffer; ! 504: break; ! 505: default: ! 506: if (mn -> m_mbox) { ! 507: (void) sprintf (buffer, "%s@%s", ! 508: mn -> m_mbox, mn -> m_host); ! 509: str= buffer; ! 510: } ! 511: else ! 512: str = mn -> m_text; ! 513: break; ! 514: } ! 515: #endif BERK ! 516: break; ! 517: ! 518: case FT_PARSEDATE: ! 519: comp = fmt->f_comp; ! 520: if ((sp = comp->c_text) && (tws = dparsetime(sp))) { ! 521: *comp->c_tws = *tws; ! 522: comp->c_flags = 0; ! 523: } else if (comp->c_flags >= 0) { ! 524: bzero ((char *) comp -> c_tws, sizeof *comp -> c_tws); ! 525: comp->c_flags = 1; ! 526: } ! 527: break; ! 528: ! 529: case FT_FORMATADDR: ! 530: /* hook for custom address list formatting (see replsbr.c) */ ! 531: str = formataddr (savestr, str); ! 532: break; ! 533: ! 534: case FT_PUTADDR: ! 535: /* output the str register as an address component, ! 536: * splitting it into multiple lines if necessary. The ! 537: * value reg. contains the max line length. The lit. ! 538: * field may contain a string to prepend to the result ! 539: * (e.g., "To: ") ! 540: */ ! 541: { ! 542: register char *lp = str; ! 543: register int indent; ! 544: register int wid = value; ! 545: register int len = strlen (str); ! 546: register char *lastb; ! 547: ! 548: sp = fmt->f_text; ! 549: indent = strlen (sp); ! 550: wid -= indent; ! 551: while( (c = *sp++) && cp < ep) ! 552: *cp++ = c; ! 553: while (len > wid) { ! 554: /* try to break at a comma; failing that, break at a ! 555: * space, failing that, just split the line. ! 556: */ ! 557: lastb = 0; sp = lp + wid; ! 558: while (sp > lp && (c = *--sp) != ',') { ! 559: if (! lastb && isspace(c)) ! 560: lastb = sp - 1; ! 561: } ! 562: if (sp == lp) ! 563: if (! (sp = lastb)) ! 564: sp = lp + wid - 1; ! 565: len -= sp - lp + 1; ! 566: while (cp < ep && lp <= sp) ! 567: *cp++ = *lp++; ! 568: *cp++ = '\n'; ! 569: for (i=indent; cp < ep && i > 0; i--) ! 570: *cp++ = ' '; ! 571: while (isspace(*lp)) ! 572: lp++, len--; ! 573: } ! 574: PUTS (cp, lp); ! 575: } ! 576: break; ! 577: ! 578: case FT_PARSEADDR: ! 579: comp = fmt->f_comp; ! 580: if (comp->c_mn != &fmt_mnull) ! 581: mnfree (comp->c_mn); ! 582: if ((sp = comp->c_text) && (sp = getname(sp)) && ! 583: (mn = getm (sp, NULLCP, 0, fmt_norm, NULLCP))) { ! 584: comp->c_mn = mn; ! 585: while (getname("")) ! 586: ; ! 587: } else ! 588: comp->c_mn = &fmt_mnull; ! 589: break; ! 590: ! 591: case FT_MYMBOX: ! 592: /* ! 593: * if there's no component, we say true. Otherwise we ! 594: * say "true" only if we can parse the address and it ! 595: * matches one of our addresses. ! 596: */ ! 597: comp = fmt->f_comp; ! 598: if (comp->c_mn != &fmt_mnull) ! 599: mnfree (comp->c_mn); ! 600: if ((sp = comp->c_text) && (sp = getname(sp)) && ! 601: (mn = getm (sp, NULLCP, 0, AD_NAME, NULLCP))) { ! 602: comp->c_mn = mn; ! 603: comp->c_flags = ismymbox(mn); ! 604: while (getname("")) ! 605: ; ! 606: } else { ! 607: comp->c_flags = (comp->c_text == 0); ! 608: comp->c_mn = &fmt_mnull; ! 609: } ! 610: break; ! 611: } ! 612: fmt++; ! 613: } ! 614: finished:; ! 615: if (cp[-1] != '\n') ! 616: *cp++ = '\n'; ! 617: *cp = NULL; ! 618: return (value); ! 619: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.