|
|
1.1 ! root 1: /* ! 2: * This software is Copyright (c) 1985 by Rick Adams. ! 3: * ! 4: * Permission is hereby granted to copy, reproduce, redistribute or ! 5: * otherwise use this software as long as: there is no monetary ! 6: * profit gained specifically from the use or reproduction or this ! 7: * software, it is not sold, rented, traded or otherwise marketed, and ! 8: * this copyright notice is included prominently in any copy ! 9: * made. ! 10: * ! 11: * The author make no claims as to the fitness or correctness of ! 12: * this software for any use whatsoever, and it is provided as is. ! 13: * Any use of this software is at the user's own risk. ! 14: * ! 15: * ! 16: * funcs2 - functions used by both inews and readnews. ! 17: */ ! 18: ! 19: #ifdef SCCSID ! 20: static char *SccsId = "@(#)funcs2.c 1.13 1/17/86"; ! 21: #endif /* SCCSID */ ! 22: ! 23: #include "params.h" ! 24: ! 25: #ifdef SunIII ! 26: #ifndef INTERNET ! 27: #define INTERNET ! 28: #endif /* !INTERNET */ ! 29: #endif /* SunIII */ ! 30: ! 31: /*LINTLIBRARY*/ ! 32: ! 33: /* ! 34: * Get user name and home directory. ! 35: */ ! 36: getuser() ! 37: { ! 38: static int flag = TRUE; ! 39: register struct passwd *p; ! 40: ! 41: if (flag) { ! 42: if ((p = getpwuid(uid)) == NULL) ! 43: xerror("Cannot get user's name"); ! 44: if ( username == NULL || username[0] == 0) ! 45: username = AllocCpy(p->pw_name); ! 46: userhome = AllocCpy(p->pw_dir); ! 47: flag = FALSE; ! 48: } ! 49: (void) strcpy(header.path, username); ! 50: } ! 51: ! 52: static FILE *sysfile; ! 53: ! 54: char *fldget(); ! 55: ! 56: static int sfline; ! 57: ! 58: /* ! 59: * Open SUBFILE. ! 60: */ ! 61: s_openr() ! 62: { ! 63: sysfile = xfopen(SUBFILE, "r"); ! 64: sfline = 0; ! 65: } ! 66: ! 67: /* ! 68: * Read SUBFILE. ! 69: */ ! 70: s_read(sp) ! 71: register struct srec *sp; ! 72: { ! 73: register char *p; ! 74: register int c; ! 75: char *e; ! 76: int chop_spaces = 0; ! 77: again: ! 78: p = bfr; ! 79: /* ! 80: * Read the SUBFILE (/usr/lib/news/sys) from the current ! 81: * position to the first unescaped newline. If a newline is ! 82: * escaped with a backslash (\) continue reading but throw away ! 83: * the backslash and newline; read the next line skipping spaces ! 84: * and tabs until the first non-space/tab character, then start ! 85: * looking for a newline again. Skipping the leading ! 86: * spaces/tabs after a escaped newline keeps the news groups ! 87: * together. If a line begins with a newline, just skip it. ! 88: */ ! 89: for (e=p+LBUFLEN; p < e && (c=getc(sysfile)) != EOF; p++) { ! 90: *p = c; ! 91: if (c == '\n') { ! 92: sfline++; ! 93: if (p == bfr || p[-1] != '\\') { ! 94: p[1] = '\0'; ! 95: break; ! 96: } else { ! 97: chop_spaces++; ! 98: p -= 2; ! 99: } ! 100: } else if (chop_spaces) { ! 101: if (c == '\t' || c == ' ') ! 102: p--; ! 103: else ! 104: chop_spaces = 0; ! 105: } ! 106: } ! 107: if (c == EOF) { ! 108: return FALSE; ! 109: } ! 110: p = bfr; ! 111: if (*p == '\n') ! 112: goto again; /* skip newlines */ ! 113: if (!nstrip(p)) ! 114: xerror("SUBFILE (%s) line %d too long.", SUBFILE, sfline); ! 115: if (*p == '#') ! 116: goto again; ! 117: sp->s_xmit[0] = '\0'; ! 118: sp->s_flags[0] = '\0'; ! 119: sp->s_nosend = (char *)0; ! 120: ! 121: p = fldget(sp->s_name, p); ! 122: if (*p++ == '\0') ! 123: xerror("Bad SUBFILE (%s) line %d.", SUBFILE, sfline); ! 124: /* ! 125: * A sys file line reading "ME" means the name of the local system. ! 126: */ ! 127: if (strcmp(sp->s_name, "ME") == 0) ! 128: (void) strcpy(sp->s_name, FULLSYSNAME); ! 129: e = index(sp->s_name, '/'); ! 130: if (e) { ! 131: *e++ = '\0'; ! 132: sp->s_nosend = e; ! 133: } ! 134: p = fldget(sp->s_nbuf, p); ! 135: lcase(sp->s_nbuf); ! 136: if (*p++ == '\0') ! 137: return TRUE; ! 138: ! 139: p = fldget(sp->s_flags, p); ! 140: if (*p++ == '\0') ! 141: return TRUE; ! 142: ! 143: (void) fldget(sp->s_xmit, p); ! 144: return TRUE; ! 145: } ! 146: ! 147: char * ! 148: fldget(q, p) ! 149: register char *q, *p; ! 150: { ! 151: while (*p && *p != ':') { ! 152: if (*p == '\\' && p[1]==':') ! 153: p++; ! 154: *q++ = *p++; ! 155: } ! 156: *q = '\0'; ! 157: return p; ! 158: } ! 159: ! 160: /* ! 161: * Find the SUBFILE record for a system. ! 162: */ ! 163: s_find(sp, system) ! 164: register struct srec *sp; ! 165: char *system; ! 166: { ! 167: s_openr(); ! 168: while (s_read(sp)) ! 169: if (strncmp(system, sp->s_name, SNLN) == 0) { ! 170: s_close(); ! 171: return TRUE; ! 172: } ! 173: s_close(); ! 174: return FALSE; ! 175: } ! 176: ! 177: /* ! 178: * Close sysfile. ! 179: */ ! 180: s_close() ! 181: { ! 182: (void) fclose(sysfile); ! 183: } ! 184: ! 185: time_t ! 186: cgtdate(datestr) ! 187: char *datestr; ! 188: { ! 189: char junk[40],month[40],day[30],tod[60],year[50]; ! 190: static time_t lasttime; ! 191: static char lastdatestr[BUFLEN] = ""; ! 192: ! 193: if ( lastdatestr[0] && strcmp(datestr, lastdatestr) == 0) ! 194: return lasttime; ! 195: lasttime = getdate(datestr, (struct timeb *)NULL); ! 196: if (lasttime < 0 && ! 197: sscanf(datestr, "%s %s %s %s %s", junk, month, day, tod, year) == 5) { ! 198: (void) sprintf(bfr, "%s %s, %s %s", month, day, year, tod); ! 199: lasttime = getdate(bfr, (struct timeb *)NULL); ! 200: } ! 201: strncpy(lastdatestr, datestr, BUFLEN); ! 202: return lasttime; ! 203: } ! 204: ! 205: lcase(s) ! 206: register char *s; ! 207: { ! 208: register char *ptr; ! 209: ! 210: for (ptr = s; *ptr; ptr++) ! 211: if (isupper(*ptr)) ! 212: *ptr = tolower(*ptr); ! 213: } ! 214: ! 215: /* ! 216: * Return a compact representation of the person who posted the given ! 217: * message. A sender or internet name will be used, otherwise ! 218: * the last part of the path is used preceded by an optional ".." ! 219: */ ! 220: char * ! 221: tailpath(hp) ! 222: struct hbuf *hp; ! 223: { ! 224: char *p, *r; ! 225: static char resultbuf[BUFLEN]; ! 226: char pathbuf[PATHLEN]; ! 227: char *malloc(); ! 228: ! 229: /* ! 230: * This only happens for articles posted by old news software ! 231: * in non-internet format. ! 232: */ ! 233: resultbuf[0] = '\0'; ! 234: (void) strncpy(pathbuf, hp->path, PATHLEN); ! 235: p = index(pathbuf, ' '); ! 236: if (p) ! 237: *p = '\0'; /* Chop off trailing " (name)" */ ! 238: r = rindex(pathbuf, '!'); ! 239: if (r == 0) { ! 240: r = pathbuf; ! 241: } else { ! 242: while (r > pathbuf && *--r != '!') ! 243: ; ! 244: if (r > pathbuf) { ! 245: r++; ! 246: (void) strcpy(resultbuf, "..!"); ! 247: } ! 248: } ! 249: (void) strcat(resultbuf, r); ! 250: return resultbuf; ! 251: } ! 252: ! 253: /* ! 254: * arpadate is like ctime(3) except that the time is returned in ! 255: * an acceptable ARPANET time format instead of ctime format. ! 256: */ ! 257: char * ! 258: arpadate(longtime) ! 259: time_t *longtime; ! 260: { ! 261: register char *p, *q, *ud; ! 262: register int i; ! 263: static char b[40]; ! 264: extern struct tm *gmtime(); ! 265: extern char *asctime(); ! 266: ! 267: /* Get current time. This will be used resolve the timezone. */ ! 268: ud = asctime(gmtime(longtime)); ! 269: ! 270: /* Crack the UNIX date line in a singularly unoriginal way. */ ! 271: q = b; ! 272: ! 273: #ifdef notdef ! 274: /* until every site installs the fix to getdate.y, the day ! 275: of the week can cause time warps */ ! 276: p = &ud[0]; /* Mon */ ! 277: *q++ = *p++; ! 278: *q++ = *p++; ! 279: *q++ = *p++; ! 280: *q++ = ','; *q++ = ' '; ! 281: #endif ! 282: ! 283: p = &ud[8]; /* 16 */ ! 284: if (*p == ' ') ! 285: p++; ! 286: else ! 287: *q++ = *p++; ! 288: *q++ = *p++; *q++ = ' '; ! 289: ! 290: p = &ud[4]; /* Sep */ ! 291: *q++ = *p++; *q++ = *p++; *q++ = *p++; *q++ = ' '; ! 292: ! 293: p = &ud[22]; /* 1979 */ ! 294: *q++ = *p++; *q++ = *p++; *q++ = ' '; ! 295: ! 296: p = &ud[11]; /* 01:03:52 */ ! 297: for (i = 8; i > 0; i--) ! 298: *q++ = *p++; ! 299: ! 300: *q++ = ' '; ! 301: *q++ = 'G'; /* GMT */ ! 302: *q++ = 'M'; ! 303: *q++ = 'T'; ! 304: *q = '\0'; ! 305: ! 306: return b; ! 307: } ! 308: ! 309: char * ! 310: replyname(hptr) ! 311: struct hbuf *hptr; ! 312: { ! 313: register char *ptr; ! 314: static char tbuf[PATHLEN]; ! 315: ! 316: ptr = hptr->path; ! 317: if (prefix(ptr, FULLSYSNAME) && ! 318: index(NETCHRS, ptr[strlen(FULLSYSNAME)])) ! 319: ptr = index(ptr, '!') + 1; ! 320: #ifdef INTERNET ! 321: if (hptr->from[0]) ! 322: ptr = hptr->from; ! 323: if (hptr->replyto[0]) ! 324: ptr = hptr->replyto; ! 325: #endif ! 326: (void) strcpy(tbuf, ptr); ! 327: ptr = index(tbuf, '('); ! 328: if (ptr) { ! 329: while (ptr[-1] == ' ') ! 330: ptr--; ! 331: *ptr = 0; ! 332: } ! 333: #ifdef SunIII ! 334: if (ptr = rindex(tbuf, '.')) { ! 335: if (prefix(++ptr, "OZ")) { ! 336: /* some people only allow it in lower case ... */ ! 337: strcpy(ptr, "oz"); ! 338: return tbuf; ! 339: } ! 340: if (prefix(ptr, "UUCP") || prefix(ptr, "ARPA") || ! 341: prefix(ptr, "DEC") || prefix(ptr, "CSNET")) { ! 342: strcat(tbuf, "@munnari.oz"); /* via sun to munnari */ ! 343: return tbuf; ! 344: } ! 345: } ! 346: /* ! 347: * must(?) have come from a uucp site, lets look see if path passes ! 348: * through munnari, and if so delete the fake uucp path after that. ! 349: */ ! 350: for (ptr = tbuf ;; ptr++) { ! 351: if (prefix(ptr, "munnari!")) { ! 352: strcpy(tbuf, ptr+8); ! 353: break; ! 354: } ! 355: ptr = index(ptr, '!'); ! 356: if (ptr == (char *)0) ! 357: break; ! 358: } ! 359: /* ! 360: * now, just send the address we have left to munnari, and ! 361: * hope that something sensible will be done with it there. ! 362: * (This works in more cases than you'd think ...) ! 363: */ ! 364: strcat(tbuf, "@munnari.oz"); ! 365: #else /* !SunIII */ ! 366: #ifndef INTERNET ! 367: /* ! 368: * Play games stripping off multiple berknet ! 369: * addresses (a!b!c:d:e => a!b!d:e) here. ! 370: */ ! 371: for (ptr=tbuf; *ptr; ptr++) { ! 372: register char *ptr2; ! 373: ! 374: if (index(NETCHRS, *ptr) && *ptr == ':' && ! 375: (ptr2=index(ptr+1, ':'))) ! 376: (void) strcpy(ptr, ptr2); ! 377: } ! 378: #endif /* !INTERNET */ ! 379: #endif /* SunIII */ ! 380: return tbuf; ! 381: } ! 382: ! 383: #ifdef DBM ! 384: typedef struct { ! 385: char *dptr; ! 386: int dsize; ! 387: } datum; ! 388: #endif /* DBM */ ! 389: ! 390: /* ! 391: * Given an article ID, find the line in the history file that mentions it. ! 392: * Return the text of the line, or NULL if not found. A pointer to a ! 393: * static area is returned. ! 394: */ ! 395: char * ! 396: findhist(artid) ! 397: char *artid; ! 398: { ! 399: static char lbuf[256]; ! 400: char oidbuf[BUFSIZ]; ! 401: FILE *hfp; ! 402: register char *p; ! 403: #ifdef DBM ! 404: datum lhs, rhs; ! 405: datum fetch(); ! 406: long fpos; /* We have to use an explicit variable to insure alignment */ ! 407: #else /* !DBM */ ! 408: char *histfile(); ! 409: #endif /* !DBM */ ! 410: ! 411: /* Try to understand old artid's as well. Assume .UUCP domain. */ ! 412: if (artid[0] != '<') { ! 413: p = index(artid, '.'); ! 414: if (p) ! 415: *p++ = '\0'; ! 416: (void) sprintf(oidbuf, "<%s@%s.UUCP>", p, artid); ! 417: if (p) ! 418: *--p = '.'; ! 419: } else ! 420: (void) strcpy(oidbuf, artid); ! 421: lcase(oidbuf); ! 422: #ifdef DBM ! 423: initdbm(ARTFILE); ! 424: lhs.dptr = oidbuf; ! 425: lhs.dsize = strlen(lhs.dptr) + 1; ! 426: rhs = fetch(lhs); ! 427: if (rhs.dptr == NULL) ! 428: return NULL; ! 429: hfp = xfopen(ARTFILE, "r"); ! 430: /* The bcopy is NECESSARY to insure alignment on some machines */ ! 431: bcopy(rhs.dptr, (char *)&fpos, sizeof (long)); ! 432: fseek(hfp, fpos, 0); ! 433: #else /* !DBM */ ! 434: hfp = xfopen(histfile(oidbuf), "r"); ! 435: #endif /* !DBM */ ! 436: while (fgets(lbuf, BUFLEN, hfp) != NULL) { ! 437: p = index(lbuf, '\t'); ! 438: if (p == NULL) ! 439: p = index(lbuf, '\n'); ! 440: *p = 0; ! 441: if (strcmp(lbuf, artid) == 0 || strcmp(lbuf, oidbuf) == 0) { ! 442: (void) fclose(hfp); ! 443: *p = '\t'; ! 444: *(lbuf + strlen(lbuf) - 1) = 0; /* zap the \n */ ! 445: return lbuf; ! 446: } ! 447: #ifdef DBM ! 448: break; ! 449: #endif /* DBM */ ! 450: } ! 451: (void) fclose(hfp); ! 452: return NULL; ! 453: } ! 454: ! 455: /* ! 456: * Hunt up the article "artid", and return the newsgroup/artnum ! 457: * where it can be found. ! 458: */ ! 459: char * ! 460: findfname(artid) ! 461: char *artid; ! 462: { ! 463: char *line, *p, *q; ! 464: char *findhist(); ! 465: static char fname[BUFLEN]; ! 466: ! 467: line = findhist(artid); ! 468: if (line) { ! 469: /* Look for it stored as an article, where it should be */ ! 470: p = index(line, '\t'); ! 471: p = index(p+1, '\t'); ! 472: p++; ! 473: if (*p) { ! 474: q = index(p, ' '); ! 475: if (q) ! 476: *q = 0; ! 477: (void) strcpy(fname, p); ! 478: return fname; ! 479: } ! 480: } ! 481: return NULL; ! 482: } ! 483: ! 484: /* ! 485: * Hunt up the article "artid", fopen it for read, and return a ! 486: * file descriptor to it. We look everywhere we can think of. ! 487: */ ! 488: FILE * ! 489: hfopen(artid) ! 490: char *artid; ! 491: { ! 492: char *p; ! 493: char *findhist(); ! 494: FILE *rv = NULL; ! 495: char fname[BUFLEN]; ! 496: ! 497: p = findfname(artid); ! 498: if (p) { ! 499: (void) strcpy(fname, dirname(p)); ! 500: rv = fopen(fname, "r"); /* NOT xfopen! */ ! 501: if (rv == NULL) ! 502: xerror("Cannot hfopen article %s", artid); ! 503: } ! 504: return rv; ! 505: } ! 506: ! 507: #ifdef DBM ! 508: /* ! 509: ** Avoid problems of multiple dbminit calls. ! 510: */ ! 511: initdbm(name) ! 512: char *name; ! 513: { ! 514: static int called = 0; ! 515: ! 516: if (called != 0) ! 517: return; ! 518: called = 1; ! 519: (void) dbminit(name); ! 520: } ! 521: #endif ! 522: ! 523: #ifndef BSD4_2 ! 524: /* ! 525: * move n bytes from a to b ! 526: */ ! 527: bcopy(a, b, n) ! 528: register char *a, *b; ! 529: register n; ! 530: { ! 531: while (--n >= 0) ! 532: *b++ = *a++; ! 533: } ! 534: #endif ! 535: ! 536: #if !defined(BSD4_2) && !defined(BSD4_1C) ! 537: rename(from,to) ! 538: register char *from, *to; ! 539: { ! 540: (void) unlink(to); ! 541: if (link(from, to) < 0) ! 542: return -1; ! 543: ! 544: (void) unlink(from); ! 545: return 0; ! 546: } ! 547: #endif /* !BSD4_2 && ! BSD4_1C */ ! 548: ! 549: #ifndef DBM ! 550: /* ! 551: ** Generate the appropriate history subfile name ! 552: */ ! 553: char * ! 554: histfile(hline) ! 555: char *hline; ! 556: { ! 557: char *p; ! 558: char chr; /* least significant digit of article number */ ! 559: static char subfile[BUFLEN]; ! 560: ! 561: p = strchr(hline, '@'); ! 562: if (p != NULL && p > hline) ! 563: chr = *(p - 1); ! 564: else ! 565: chr = '0'; ! 566: if (!isdigit(chr)) ! 567: chr = '0'; ! 568: sprintf(subfile, "%s.d/%c", ARTFILE, chr); ! 569: if (access(subfile, 04) < 0) ! 570: return(ARTFILE); ! 571: return(subfile); ! 572: } ! 573: #endif /* !DBM */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.