|
|
1.1 ! root 1: #ifndef lint ! 2: static char *sccsid = "@(#)misc.c 1.4 (Berkeley) 3/8/86"; ! 3: #endif ! 4: ! 5: #include "common.h" ! 6: ! 7: /* ! 8: * open_valid_art -- determine if a given article name is valid; ! 9: * if it is, return a file pointer to the open article, ! 10: * along with a unique id of the article. ! 11: * ! 12: * Parameters: "artname" is a string containing the ! 13: * name of the article. ! 14: * "id" is space for us to put the article ! 15: * id in. ! 16: * ! 17: * Returns: File pointer to the open article if the ! 18: * article is valid; NULL otherwise ! 19: * ! 20: * Side effects: None. ! 21: */ ! 22: ! 23: FILE * ! 24: open_valid_art(artname, id) ! 25: char *artname; ! 26: char *id; ! 27: { ! 28: static int crnt_art_num; ! 29: static char crnt_art_id[MAX_STRLEN]; ! 30: int fd; ! 31: struct stat statbuf; ! 32: ! 33: if (art_fp != NULL) { ! 34: if (crnt_art_num == atoi(artname)) { ! 35: if (fseek(art_fp, (long) 0, 0) < 0) ! 36: close_crnt(); ! 37: else { ! 38: (void) strcpy(id, crnt_art_id); ! 39: return(art_fp); ! 40: } ! 41: } else ! 42: close_crnt(); ! 43: } ! 44: ! 45: art_fp = fopen(artname, "r"); ! 46: ! 47: if (art_fp == NULL) ! 48: return(NULL); ! 49: ! 50: fd = fileno(art_fp); ! 51: ! 52: if (fstat(fd, (struct stat *) &statbuf) < 0) { ! 53: close_crnt(); ! 54: return(NULL); ! 55: } ! 56: ! 57: if ((statbuf.st_mode & S_IFREG) != S_IFREG) { ! 58: close_crnt(); ! 59: return(NULL); ! 60: } ! 61: ! 62: get_id(art_fp, id); ! 63: (void) strcpy(crnt_art_id, id); ! 64: crnt_art_num = atoi(artname); ! 65: return(art_fp); ! 66: } ! 67: ! 68: ! 69: /* ! 70: * openartbyid -- open an article by message-id. ! 71: * ! 72: * Parameters: "msg_id" is the message ID of the ! 73: * article, enclosed in <>'s. ! 74: * ! 75: * Returns: A file pointer to the open article, ! 76: * or NULL if the article doesn't exist. ! 77: * ! 78: * Side effects: Displays article, opens dbm database ! 79: * (only once, keeps it open after that). ! 80: * Converts "msg_id" to lower case. ! 81: */ ! 82: ! 83: FILE * ! 84: openartbyid(msg_id) ! 85: char *msg_id; ! 86: { ! 87: char line[MAX_STRLEN], path[MAX_STRLEN]; ! 88: char *tmp; ! 89: register char *cp; ! 90: FILE *art_fp; ! 91: #ifdef DBM ! 92: static int dbopen; ! 93: datum fetch(); ! 94: #else ! 95: static DBM *db; /* History file, dbm version */ ! 96: #endif ! 97: static FILE *hfp; /* history file, text version */ ! 98: datum key, content; ! 99: ! 100: #ifdef DBM ! 101: if (!dbopen) { ! 102: if (dbminit(HISTORY_FILE) < 0) { ! 103: syslog(LOG_ERR, "nntpd: openartbyid: dbminit %s: %m\n", ! 104: HISTORY_FILE); ! 105: return (NULL); ! 106: } else ! 107: dbopen = 1; ! 108: } ! 109: #else ! 110: if (db == NULL) { ! 111: db = dbm_open(HISTORY_FILE, O_RDONLY, 0); ! 112: if (db == NULL) { ! 113: syslog(LOG_ERR, "nntpd: openartbyid: dbm_open %s: %m\n", ! 114: HISTORY_FILE); ! 115: return (NULL); ! 116: } ! 117: } ! 118: #endif ! 119: ! 120: for (cp = msg_id; *cp != '\0'; ++cp) ! 121: if (isupper(*cp)) ! 122: *cp = tolower(*cp); ! 123: ! 124: key.dptr = msg_id; ! 125: key.dsize = strlen(msg_id) + 1; ! 126: ! 127: #ifdef DBM ! 128: content = fetch(key); ! 129: #else ! 130: content = dbm_fetch(db, key); ! 131: #endif ! 132: if (content.dptr == NULL) ! 133: return (NULL); ! 134: ! 135: if (hfp == NULL) { ! 136: hfp = fopen(HISTORY_FILE, "r"); ! 137: if (hfp == NULL) { ! 138: syslog(LOG_ERR, "nntpd: message: fopen %s: %m\n", ! 139: HISTORY_FILE); ! 140: return (NULL); ! 141: } ! 142: } ! 143: ! 144: if (fseek(hfp, (long) *(int *)content.dptr, 0) < 0) { ! 145: syslog(LOG_ERR, "nntpd: message: fseek: %m\n"); ! 146: return (NULL); ! 147: } ! 148: ! 149: (void) fgets(line, sizeof(line), hfp); ! 150: if ((cp = index(line, '\n')) != NULL) ! 151: *cp = '\0'; ! 152: cp = index(line, '\t'); ! 153: if (cp != NULL) ! 154: cp = index(cp+1, '\t'); ! 155: if (cp == NULL) { ! 156: syslog(LOG_ERR, ! 157: "nntpd: message: malformed line in history file (%d bytes)\n", ! 158: (int) *(int *)content.dptr); ! 159: return (NULL); ! 160: } ! 161: tmp = cp+1; ! 162: ! 163: if ((cp = index(tmp, ' ')) != NULL) ! 164: *cp = '\0'; ! 165: ! 166: while ((cp = index(tmp, '.')) != NULL) ! 167: *cp = '/'; ! 168: ! 169: (void) strcpy(path, homedir); ! 170: (void) strcat(path, "/"); ! 171: (void) strcat(path, tmp); ! 172: ! 173: art_fp = fopen(path, "r"); ! 174: return (art_fp); ! 175: ! 176: } ! 177: ! 178: ! 179: /* ! 180: * spew -- spew out the contents of a file to stdout, doing ! 181: * the necessary cr-lf additions at the end. Finish with ! 182: * a "." on a line by itself, and an fflush(stdout). ! 183: * ! 184: * Parameters: "how" tells what part of the file we ! 185: * want spewed: ! 186: * ARTICLE The entire thing. ! 187: * HEAD Just the first part. ! 188: * BODY Just the second part. ! 189: * "fp" is the open file to spew from. ! 190: * ! 191: * Returns: Nothing. ! 192: * ! 193: * Side effects: Changes current position in file. ! 194: */ ! 195: ! 196: spew(fp, how) ! 197: FILE *fp; ! 198: int how; ! 199: { ! 200: char line[512]; ! 201: register char *cp; ! 202: ! 203: #ifdef LOG ! 204: ++arts_acsd; ! 205: #endif ! 206: ! 207: if (how == STAT) { ! 208: (void) fflush(stdout); ! 209: return; ! 210: } ! 211: ! 212: while (fgets(line, sizeof(line)-6, fp) != NULL && *line != '\n') { ! 213: if (how == BODY) /* We need to skip this anyway */ ! 214: continue; ! 215: cp = index(line, '\n'); ! 216: if (cp != NULL) ! 217: *cp = '\0'; ! 218: if (*line == '.') ! 219: putchar('.'); ! 220: printf("%s\r\n", line); ! 221: if (cp == NULL) { ! 222: for (;;) { ! 223: if ((fgets(line, sizeof(line)-6, fp) == NULL) ! 224: || (index(line, '\n') != NULL)) ! 225: break; ! 226: } ! 227: } ! 228: } ! 229: ! 230: if (how == HEAD) { ! 231: putchar('.'); ! 232: putchar('\r'); ! 233: putchar('\n'); ! 234: (void) fflush(stdout); ! 235: return; ! 236: } else if (how == ARTICLE) { ! 237: putchar('\r'); ! 238: putchar('\n'); ! 239: } ! 240: ! 241: while (fgets(line, sizeof(line)-6, fp) != NULL) { ! 242: cp = index(line, '\n'); ! 243: if (cp != NULL) ! 244: *cp = '\0'; ! 245: if (*line == '.') ! 246: putchar('.'); ! 247: printf("%s\r\n", line); ! 248: ! 249: if (cp == NULL) { ! 250: for (;;) { ! 251: if ((fgets(line, sizeof(line)-6, fp) == NULL) ! 252: || (index(line, '\n') != NULL)) ! 253: break; ! 254: } ! 255: } ! 256: } ! 257: putchar('.'); ! 258: putchar('\r'); ! 259: putchar('\n'); ! 260: (void) fflush(stdout); ! 261: } ! 262: ! 263: ! 264: /* ! 265: * get_id -- get the message id of the current article. ! 266: * ! 267: * Parameters: "art_fp" is a pointer to the open file. ! 268: * "id" is space for the message ID. ! 269: * ! 270: * Returns: Nothing. ! 271: * ! 272: * Side effects: Seeks and rewinds on "art_fp". ! 273: * Changes space pointed to by "id". ! 274: */ ! 275: ! 276: get_id(art_fp, id) ! 277: register FILE *art_fp; ! 278: char *id; ! 279: { ! 280: char line[MAX_STRLEN]; ! 281: register char *cp; ! 282: ! 283: while (fgets(line, sizeof(line), art_fp) != NULL) { ! 284: if ((cp = index(line, '\n')) != NULL) ! 285: *cp = '\0'; ! 286: if (*line == '\0') ! 287: break; ! 288: if ((cp = index(line, ' ')) != NULL) { ! 289: *cp = '\0'; ! 290: if (streql(line, "Message-ID:")) { ! 291: (void) strcpy(id, cp + 1); ! 292: (void) rewind(art_fp); ! 293: return; ! 294: } ! 295: } ! 296: } ! 297: (void) strcpy(id, "<0>"); ! 298: (void) rewind(art_fp); ! 299: } ! 300: ! 301: /* ! 302: * close_crnt -- close the current article file pointer, if it's ! 303: * open. ! 304: * ! 305: * Parameters: None. ! 306: * ! 307: * Returns: Nothing. ! 308: * ! 309: * Side effects: Closes "art_fp" if it's open; sets "art_fp" to NULL. ! 310: */ ! 311: ! 312: close_crnt() ! 313: { ! 314: if (art_fp != NULL) ! 315: (void) fclose(art_fp); ! 316: art_fp = NULL; ! 317: } ! 318: ! 319: ! 320: /* ! 321: * findart -- find an article number in the article array. ! 322: * ! 323: * Parameters: "artname" is a string containing ! 324: * the name of the article. ! 325: * ! 326: * Returns: An index into "art_array", ! 327: * or -1 if "artname" isn't in "art_array". ! 328: * ! 329: * Side effects: None. ! 330: * ! 331: * Improvement: Replace this linear search with a binary one. ! 332: */ ! 333: ! 334: findart(artname) ! 335: char *artname; ! 336: { ! 337: register int i, artnum; ! 338: ! 339: artnum = atoi(artname); ! 340: ! 341: for (i = 0; i < num_arts; ++i) ! 342: if (art_array[i] == artnum) ! 343: return(i); ! 344: ! 345: return(-1); ! 346: } ! 347: ! 348: ! 349: /* ! 350: * get_distlist -- return a nicely set up array of distribution groups ! 351: * along with a count, when given an NNTP-spec distribution list ! 352: * in the form <dist1,dist2,...,distn>. ! 353: * ! 354: * Parameters: "array" is storage for our array, ! 355: * set to point at some static data. ! 356: * "list" is the NNTP distribution list. ! 357: * ! 358: * Returns: Number of distributions found. ! 359: * -1 on error. ! 360: * ! 361: * Side effects: Changes static data area. ! 362: */ ! 363: ! 364: get_distlist(array, list) ! 365: char ***array; ! 366: char *list; ! 367: { ! 368: char *cp; ! 369: int distcount; ! 370: static char **dist_list = (char **) NULL; ! 371: ! 372: if (list[0] != '<') ! 373: return (-1); ! 374: ! 375: cp = index(list + 1, '>'); ! 376: if (cp != NULL) ! 377: *cp = '\0'; ! 378: else ! 379: return (-1); ! 380: ! 381: for (cp = list + 1; *cp != '\0'; ++cp) ! 382: if (*cp == ',') ! 383: *cp = ' '; ! 384: distcount = parsit(list + 1, &dist_list); ! 385: *array = dist_list; ! 386: return (distcount); ! 387: } ! 388: ! 389: ! 390: /* ! 391: * spawn -- create a child process with the input from the client ! 392: * as stdin. ! 393: * ! 394: * Parameters: "path" is the path of the program to invoke. ! 395: * "name" is the name to call the program. ! 396: * "flag" is a single flag to be passed to the program. ! 397: * "cont_code" is the response code to transmit ! 398: * on successful startup. ! 399: * "err_code" is the response code to transmit when ! 400: * something goes wrong. ! 401: * ! 402: * Returns: -1 on non-zero return from child, ! 403: * 0 on error before fork/exec, ! 404: * 1 otherwise. ! 405: * ! 406: * Side effects: Creates and removes temporary file; ! 407: * accepts input from client; forks and execs. ! 408: */ ! 409: ! 410: spawn(path, name, flag, cont_code, err_code) ! 411: char *path; ! 412: char *name; ! 413: char *flag; ! 414: int cont_code; ! 415: int err_code; ! 416: { ! 417: char tempfile[256], line[MAX_STRLEN]; ! 418: register char *cp; ! 419: int i, nds, fd; ! 420: int exit_status; ! 421: union wait status; ! 422: register FILE *fp; ! 423: ! 424: (void) strcpy(tempfile, "/tmp/rpostXXXXXX"); ! 425: (void) mktemp(tempfile); ! 426: ! 427: fp = fopen(tempfile, "w"); ! 428: if (fp == NULL) { ! 429: printf("%d Cannot create temporary file.\r\n", err_code); ! 430: (void) fflush(stdout); ! 431: return (0); ! 432: } else { ! 433: printf("%d Enter news, period on a line by itself to end.\r\n", ! 434: cont_code); ! 435: (void) fflush(stdout); ! 436: } ! 437: ! 438: while (fgets(line, sizeof(line), stdin) != NULL) { ! 439: if ((cp = index(line, '\r')) != NULL) ! 440: *cp = '\0'; ! 441: else if ((cp = index(line, '\n')) != NULL) ! 442: *cp = '\0'; ! 443: ! 444: if (strcmp(line, ".") == 0) ! 445: break; ! 446: ! 447: if (line[0] == '.') ! 448: fprintf(fp, "%s\n", line+1); ! 449: else ! 450: fprintf(fp, "%s\n", line); ! 451: } ! 452: (void) fclose(fp); ! 453: ! 454: /* ! 455: * Ok, now we have the article in "tempfile". We ! 456: * should be able to fork off, close fd's 0 to 31 (or ! 457: * whatever), open "tempfile" for input, thus making ! 458: * it stdin, and then execl the inews. We think. ! 459: */ ! 460: ! 461: if (fork() == 0) { /* We're in child */ ! 462: #ifdef POSTER ! 463: (void) setuid(uid_poster); ! 464: (void) setgid(gid_poster); ! 465: #endif ! 466: ! 467: nds = getdtablesize(); ! 468: for (i = 0; i < nds; ++i) ! 469: (void) close(i); ! 470: fd = open(tempfile, O_RDONLY); ! 471: if (fd != 0) { ! 472: (void) dup2(fd, 0); ! 473: (void) close(fd); ! 474: } ! 475: fd = open("/", O_RDONLY); ! 476: if (fd != 1) { ! 477: (void) dup2(fd, 1); ! 478: (void) close(fd); ! 479: } ! 480: (void) dup2(1, 2); ! 481: ! 482: execl(path, name, flag, (char *) NULL); ! 483: exit(-1); /* Error */ ! 484: } else { ! 485: while (wait(&status) > 0) ! 486: exit_status = status.w_T.w_Retcode; ! 487: (void) unlink(tempfile); ! 488: (void) fflush(stdout); ! 489: return (exit_status ? -1 : 1); ! 490: } ! 491: } ! 492: ! 493: ! 494: /* ! 495: * streql -- determine if two strings are equal, ignoring case. ! 496: * ! 497: * Parameters: "a" and "b" are the pointers ! 498: * to characters to be compared. ! 499: * ! 500: * Returns: 1 if the strings are equal, 0 otherwise. ! 501: * ! 502: * Side effects: None. ! 503: */ ! 504: ! 505: streql(a, b) ! 506: register char *a, *b; ! 507: { ! 508: char lower(); ! 509: ! 510: while (lower(*a) == lower(*b)) { ! 511: if (*a == '\0') ! 512: return (1); ! 513: a++; ! 514: b++; ! 515: } ! 516: return (0); ! 517: } ! 518: ! 519: /* ! 520: * lower -- convert a character to lower case, if it's ! 521: * upper case. ! 522: * ! 523: * Parameters: "c" is the character to be ! 524: * converted. ! 525: * ! 526: * Returns: "c" if the character is not ! 527: * upper case, otherwise the lower ! 528: * case eqivalent of "c". ! 529: * ! 530: * Side effects: None. ! 531: */ ! 532: ! 533: char lower(c) ! 534: register char c; ! 535: { ! 536: if (isascii(c) && isupper(c)) ! 537: c = c - 'A' + 'a'; ! 538: return(c); ! 539: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.