|
|
1.1 ! root 1: #include "parms.h" ! 2: #include "structs.h" ! 3: #include "newsgate.h" ! 4: ! 5: #ifdef RCSIDENT ! 6: static char *RCSid = "$Header: newsdump.c,v 1.7.0.8 85/07/20 13:43:56 notes Rel $"; ! 7: #endif RCSIDENT ! 8: ! 9: /* ! 10: * newsnote - take a note and dump it in a format that news will ! 11: * understand. Submit the article to the news program as ! 12: * defined in newsgate.h ! 13: * ! 14: * newsresp - similar to newsnote, but it dumps a response instead. ! 15: * ! 16: * The routines build some title lines and other headers for ! 17: * submission to the news insertion program. The rest of the ! 18: * article is fed to the news program through a pipe. ! 19: * This turned out to be mucho mucho easier than building the ! 20: * properly formatted intersystem files. ! 21: * ! 22: * Original Coding: Ray Essick April 1982 ! 23: * Modified to produce cleaner looking output: ! 24: * Ray Essick May 1, 1982 ! 25: * (with good help from Brian Redman (harpo!ber) ! 26: * Modified to solve meta-character ("'`) problems in popen() ! 27: * Ray Essick September 1982 ! 28: * ! 29: * Lots of code by Tw Cook at Hewlett-Packard to implement ! 30: * compatibility with the USENET standards for news. ! 31: * January 1984. ! 32: */ ! 33: ! 34: extern char *mnames[]; /* month names */ ! 35: FILE * popen (); ! 36: ! 37: char *Version = "$Revision: 1.7.0.8 $"; /* Use RCS info */ ! 38: ! 39: newsnote (io, note, notenum, ngroup, backwards) ! 40: struct io_f *io; ! 41: struct note_f *note; ! 42: char *ngroup; /* to this newsgroup */ ! 43: { ! 44: FILE * rnews; /* rnews pipe */ ! 45: char cmdline[CMDLEN]; /* command line */ ! 46: char line[TITLEN + 50]; /* scratch line */ ! 47: int i; ! 48: char *p, ! 49: *q; ! 50: char ntitle[TITLEN + 10]; /* title */ ! 51: char from[SYSSZ + NAMESZ + 3]; /* formatted author */ ! 52: char path[BUFSIZ]; /* path to author */ ! 53: char *author; /* for Path line */ ! 54: ! 55: /* ! 56: * format some of the internal data structures in a suitable ! 57: * format to send to the news system. ! 58: */ ! 59: ! 60: strcpy (ntitle, note -> ntitle); /* make a title */ ! 61: if (backwards) ! 62: { ! 63: strcat (ntitle, " "); /* separate */ ! 64: strcat (ntitle, NFSUFFIX); /* add suffix */ ! 65: } ! 66: ! 67: /* ! 68: * From: ! 69: * author information ! 70: */ ! 71: sprintf (from, "%s@%s", /* author */ ! 72: note -> n_auth.aname, note -> n_auth.asystem); ! 73: #ifdef notdef ! 74: /* ! 75: * decided it was better to NOT append a domain here... ! 76: */ ! 77: if (index (note -> n_auth.asystem, '.') != (char *) NULL)/* domained */ ! 78: { ! 79: sprintf (from, "%s@%s", ! 80: note -> n_auth.aname, note -> n_auth.asystem); ! 81: } ! 82: else ! 83: { ! 84: sprintf (from, "%s@%s.%s", ! 85: note -> n_auth.aname, note -> n_auth.asystem, ! 86: DFLTDOMAIN); /* append default */ ! 87: } ! 88: #endif notdef ! 89: /* ! 90: * Path: ! 91: * where the article has been ! 92: * Maybe we want to use some format besides a!b!c, something like ! 93: * a,b,c ! 94: */ ! 95: if (!strcmp (System, note -> n_id.sys)) /* local */ ! 96: { ! 97: sprintf (path, "%s", note -> n_id.sys); ! 98: } ! 99: else ! 100: { ! 101: if (!strcmp (note -> n_id.sys, note -> n_from)) /* one hop */ ! 102: { ! 103: sprintf (path, "%s!%s", ! 104: System, ! 105: note -> n_id.sys); ! 106: } ! 107: else ! 108: { ! 109: sprintf (path, "%s!%s!%s", /* several hops */ ! 110: System, note -> n_from, note -> n_id.sys); ! 111: } ! 112: } ! 113: #ifdef UGLYPATH /* usually so */ ! 114: /* ! 115: * Fill in the "authorname" with either a placeholder ! 116: * or the real author name. Key this off whether the unique ! 117: * id matches the author's home system. ! 118: * ! 119: * This will usually use AUTHORPLACEHOLDER on new systems ! 120: * since the unique id's don't have the domains in yet. ! 121: * ! 122: * hacked at to satisfy the public at large still using the ! 123: * Path line although it's not supposed to be good any longer. ! 124: * new code checks to see if things are a common prefix. and ! 125: * that the next character in the longer string is a "." ! 126: * if so, it declares things good enough and uses the real author. ! 127: */ ! 128: { ! 129: int idlen, ! 130: authlen; ! 131: int isok; ! 132: int minlen; ! 133: ! 134: idlen = strlen (note -> n_id.sys); ! 135: authlen = strlen (note -> n_auth.asystem); ! 136: minlen = idlen < authlen ? idlen : authlen; /* get shortest */ ! 137: isok = (strncmp (note -> n_id.sys, note -> n_auth.asystem, minlen) == 0); ! 138: if (isok && idlen < authlen) /* id is short */ ! 139: { ! 140: isok &= (note -> n_auth.asystem[idlen] == '.'); ! 141: } ! 142: else ! 143: { ! 144: if (isok && authlen < idlen) ! 145: isok &= (note -> n_id.sys[authlen] == '.'); ! 146: } ! 147: if (isok) ! 148: author = note -> n_auth.aname; /* ok for him */ ! 149: else ! 150: author = AUTHORPLACEHOLDER; /* not local */ ! 151: } ! 152: #else !UGLYPATH ! 153: /* ! 154: * the bnews code all assumes that the last component of ! 155: * the Path line is a user name. If we don't append something, ! 156: * that system will see the articles again, since news will ! 157: * disregard it when comparing to see where things have been. ! 158: */ ! 159: author = AUTHORPLACEHOLDER; ! 160: #endif UGLYPATH ! 161: /* ! 162: * dump the article ! 163: */ ! 164: ! 165: if ((rnews = popen (rnewscmd, "w")) == NULL) /* open news pipe */ ! 166: return (-1); /* report failure */ ! 167: ! 168: fprintf (rnews, "Relay-Version: Notesfiles %s; site %s\n", ! 169: Version, System); ! 170: /* ! 171: * Here we make a slight deviation from what one would expect. ! 172: * We use the LOCAL version of the notes/news gateway to pick ! 173: * the Posting Version line. This is because we are the version ! 174: * that actually makes the insertion into the news system. ! 175: * ! 176: * To back it up, the Usenet Standards papr (rfc whatever) says ! 177: * that the Posting-version "identifies the software responsible ! 178: * for entering this message into the network". ! 179: * Whether the "site" field should be the gatewaying site or where ! 180: * the article originated is a good question. ! 181: * I chose to make it the notes->news gateway running locally and ! 182: * the site where the article originated. ! 183: * ! 184: * The stuff with the #ifdef notdef is to preserve the old code ! 185: * that just labeled article we gateway with a Posting version ! 186: * of "Notesfiles" instead of "Notesfiles 1.x". ! 187: */ ! 188: #ifdef notdef ! 189: if (!strcmp (System, note -> n_id.sys)) /* local note */ ! 190: #endif notdef ! 191: { ! 192: /* ! 193: * always consider ourselves the posting version. We are the ! 194: * site that posted it to news! There could be a question ! 195: * about articles gated in two places or which site should be ! 196: * there. ! 197: */ ! 198: fprintf (rnews, "Posting-Version: Notesfiles %s; site %s\n", ! 199: Version, note -> n_id.sys); ! 200: } ! 201: #ifdef notdef ! 202: else /* remote note */ ! 203: fprintf (rnews, "Posting-Version: Notesfiles; site %s.%s\n", ! 204: note -> n_id.sys, DFLTDOMAIN); /* unknown version */ ! 205: #endif notdef ! 206: fprintf (rnews, "From: %s\n", from); /* formatted */ ! 207: /* ! 208: * Sample format that is legal ! 209: * fprintf (rnews, "Date: 13-Jan-83 12:08 PST\n"); ! 210: */ ! 211: fprintf (rnews, "Date: %02d-%3s-%02d %02d:%02d %3s\n", ! 212: note -> n_date.w_day, ! 213: mnames[note -> n_date.w_month], ! 214: note -> n_date.w_year - 1900, ! 215: note -> n_date.w_hours, ! 216: note -> n_date.w_mins, ! 217: tzone (¬e -> n_date)); ! 218: fprintf (rnews, "Newsgroups: %s\n", ngroup); ! 219: fprintf (rnews, "Subject: %s\n", ntitle); ! 220: fprintf (rnews, "Message-ID: <%ld@%s>\n", note -> n_id.uniqid, ! 221: note -> n_id.sys); ! 222: fprintf (rnews, "Path: %s!%s\n", path, author); ! 223: ! 224: /* ! 225: * send out the notesfile specfic headers ! 226: */ ! 227: if (note -> n_addr.addr == 0) /* make sure */ ! 228: note -> n_addr.textlen = 0; /* on empty text */ ! 229: ! 230: fprintf (rnews, "%s: #N:%s:%ld:%03o:%ld\n", /* nf header */ ! 231: NFLINE1, /* "NF-line1" */ ! 232: note -> n_id.sys, note -> n_id.uniqid, ! 233: note -> n_stat, ((long) note -> n_addr.textlen)); ! 234: ! 235: fprintf (rnews, "%s: %s!%s %3s %2d %02d:%02d:00 %4d\n", ! 236: NFLINE2, /* "Nf-line2" */ ! 237: note -> n_auth.asystem, note -> n_auth.aname,/* author */ ! 238: mnames[note -> n_date.w_month], /* date written */ ! 239: note -> n_date.w_day, ! 240: note -> n_date.w_hours, ! 241: note -> n_date.w_mins, ! 242: note -> n_date.w_year); ! 243: /* ! 244: * Optional headers that we don't hassle with right now: ! 245: * Organization: make a table driven routine to grab ! 246: */ ! 247: ! 248: putc ('\n', rnews); /* separator */ ! 249: if (backwards) /* include old stuff */ ! 250: { ! 251: fprintf (rnews, "#N:%s:%ld:%03o:%ld\n", /* nf header */ ! 252: note -> n_id.sys, note -> n_id.uniqid, ! 253: note -> n_stat, ((long) note -> n_addr.textlen)); ! 254: ! 255: fprintf (rnews, "%s!%s %3s %2d %02d:%02d:00 %4d\n", ! 256: note -> n_auth.asystem, note -> n_auth.aname,/* author */ ! 257: mnames[note -> n_date.w_month], /* date written */ ! 258: note -> n_date.w_day, ! 259: note -> n_date.w_hours, ! 260: note -> n_date.w_mins, ! 261: note -> n_date.w_year); ! 262: } ! 263: putc ('\n', rnews); /* separator */ ! 264: pageout (io, ¬e -> n_addr, rnews); /* dump text */ ! 265: fprintf (rnews, "\n"); /* ensure newline */ ! 266: pclose (rnews); /* close it */ ! 267: sleep (SLEEPTIME); /* wait a while */ ! 268: return (0); ! 269: } ! 270: ! 271: /* ! 272: * newsresp ! 273: * ! 274: * Dump a response to the news system. ! 275: */ ! 276: ! 277: newsresp (io, note, notenum, rsprec, roffset, respnum, ngroup, backwards) ! 278: struct io_f *io; ! 279: struct note_f *note; ! 280: struct resp_f *rsprec; ! 281: char *ngroup; ! 282: { ! 283: char cmdline[CMDLEN]; /* leggo brand */ ! 284: char line[TITLEN + 50]; /* scratch */ ! 285: FILE * rnews; ! 286: int i; ! 287: char *p, ! 288: *q; ! 289: char ntitle[TITLEN + 20]; /* formatted title */ ! 290: char from[SYSSZ + NAMESZ + 3]; /* formatted author */ ! 291: char path[BUFSIZ]; /* path to author */ ! 292: char *author; /* for Path: */ ! 293: long uniquenum; ! 294: ! 295: /* ! 296: * pre-format a few fields like titles, author information, ! 297: * paths to authors, and that sort of gunk. ! 298: */ ! 299: ! 300: ntitle[0] = '\0'; /* empty string */ ! 301: if (strncmp (note -> ntitle, "Re:", 3) && /* is it already */ ! 302: strncmp (note -> ntitle, "RE:", 3) && /* a response-like */ ! 303: strncmp (note -> ntitle, "re:", 3)) /* title? */ ! 304: { /* flag it as a */ ! 305: strcat (ntitle, "Re: "); /* response */ ! 306: } ! 307: strcat (ntitle, note -> ntitle); /* include title */ ! 308: if (backwards) ! 309: { ! 310: strcat (ntitle, " "); ! 311: strcat (ntitle, NFSUFFIX); /* include old */ ! 312: } ! 313: ! 314: /* ! 315: * From: ! 316: * author information ! 317: */ ! 318: sprintf (from, "%s@%s", /* author */ ! 319: rsprec -> r_auth[roffset].aname, rsprec -> r_auth[roffset].asystem); ! 320: #ifdef notdef ! 321: /* ! 322: * decided it was better to NOT append a domain at this point ! 323: */ ! 324: if (index (rsprec -> r_auth[roffset].asystem, '.') != (char *) NULL) ! 325: { /* already domained */ ! 326: sprintf (from, "%s@%s", ! 327: rsprec -> r_auth[roffset].aname, rsprec -> r_auth[roffset].asystem); ! 328: } ! 329: else ! 330: { ! 331: sprintf (from, "%s@%s.%s", ! 332: rsprec -> r_auth[roffset].aname, rsprec -> r_auth[roffset].asystem, ! 333: DFLTDOMAIN); ! 334: } ! 335: #endif notdef ! 336: /* ! 337: * Path: ! 338: * Where the article has been ! 339: */ ! 340: if (!strcmp (System, rsprec -> r_id[roffset].sys)) /* local */ ! 341: { ! 342: sprintf (path, "%s", rsprec -> r_id[roffset].sys); ! 343: } ! 344: else ! 345: { ! 346: if (!strcmp (rsprec -> r_id[roffset].sys, rsprec -> r_from[roffset])) ! 347: { /* one hop */ ! 348: sprintf (path, "%s!%s", ! 349: System, ! 350: rsprec -> r_id[roffset].sys); ! 351: } ! 352: else ! 353: { ! 354: sprintf (path, "%s!%s!%s", /* several hops */ ! 355: System, ! 356: rsprec -> r_from[roffset], ! 357: rsprec -> r_id[roffset].sys); ! 358: } ! 359: } ! 360: #ifdef UGLYPATH /* usually so */ ! 361: /* ! 362: * See if we can use the author's name instead of ! 363: * AUTHORPLACEHOLDER. Check this by comparin unique id's ! 364: * and the author's system. ! 365: * ! 366: * see similar code above in newsnote() for explanation of the ! 367: * gyrations here. ! 368: */ ! 369: { ! 370: int idlen, ! 371: authlen; ! 372: int isok; ! 373: int minlen; ! 374: ! 375: idlen = strlen (rsprec -> r_id[roffset].sys); ! 376: authlen = strlen (rsprec -> r_auth[roffset].asystem); ! 377: minlen = idlen < authlen ? idlen : authlen; ! 378: isok = (strncmp (rsprec -> r_id[roffset].sys, rsprec -> r_auth[roffset].asystem, minlen) == 0); ! 379: if (isok && idlen < authlen) /* id is short */ ! 380: { ! 381: isok &= (rsprec -> r_auth[roffset].asystem[idlen] == '.'); ! 382: } ! 383: else ! 384: { ! 385: if (isok && authlen < idlen) /* author syste is short */ ! 386: isok &= (rsprec -> r_id[roffset].sys[authlen] == '.'); ! 387: } ! 388: if (isok) ! 389: author = rsprec -> r_auth[roffset].aname; ! 390: else ! 391: author = AUTHORPLACEHOLDER; ! 392: } ! 393: #else !UGLYPATH ! 394: /* ! 395: * since bnews programs all assume the last component of the ! 396: * path line is a user name, we have to put something there ! 397: * to keep them from disregarding the system name when trying ! 398: * to see where the article has been. ! 399: */ ! 400: author = AUTHORPLACEHOLDER; ! 401: #endif UGLYPATH ! 402: ! 403: /* ! 404: * Time to send the article to the news system ! 405: */ ! 406: ! 407: if ((rnews = popen (rnewscmd, "w")) == NULL) /* will it work */ ! 408: return (-1); /* report failure */ ! 409: ! 410: fprintf (rnews, "Relay-Version: Notesfiles %s; site %s\n", ! 411: Version, System); ! 412: #ifdef notdef ! 413: if (!strcmp (System, rsprec -> r_id[roffset].sys)) /* local note */ ! 414: #endif notdef ! 415: { ! 416: /* ! 417: * always consider ourselves the posting version. We are the ! 418: * site that posted it to news! There could be a question ! 419: * about articles gated in two places or which site should be ! 420: * there. ! 421: * ! 422: * See comments around similar lines within the newsnote() ! 423: * routine above ! 424: */ ! 425: fprintf (rnews, "Posting-Version: Notesfiles %s; site %s\n", ! 426: Version, rsprec -> r_id[roffset].sys); ! 427: } ! 428: #ifdef notdef ! 429: else /* remote note */ ! 430: fprintf (rnews, "Posting-Version: Notesfiles; site %s.%s\n", ! 431: rsprec -> r_id[roffset].sys, DFLTDOMAIN);/* unknown version */ ! 432: #endif notdef ! 433: fprintf (rnews, "From: %s\n", from); /* formatted */ ! 434: /* ! 435: * Sample format that is legal ! 436: * fprintf (rnews, "Date: 13-Jan-83 12:08 PST\n"); ! 437: */ ! 438: fprintf (rnews, "Date: %02d-%3s-%02d %02d:%02d %3s\n", ! 439: rsprec -> r_when[roffset].w_day, ! 440: mnames[rsprec -> r_when[roffset].w_month], ! 441: rsprec -> r_when[roffset].w_year - 1900, ! 442: rsprec -> r_when[roffset].w_hours, ! 443: rsprec -> r_when[roffset].w_mins, ! 444: tzone (&rsprec -> r_when[roffset])); ! 445: fprintf (rnews, "Newsgroups: %s\n", ngroup); ! 446: fprintf (rnews, "Subject: %s\n", ntitle); ! 447: fprintf (rnews, "Message-ID: <%ld@%s>\n", ! 448: rsprec -> r_id[roffset].uniqid, rsprec -> r_id[roffset].sys); ! 449: fprintf (rnews, "Path: %s!%s\n", path, author); ! 450: ! 451: /* ! 452: * send out the notesfile specfic headers ! 453: */ ! 454: fprintf (rnews, "%s: #R:%s:%ld:%s:%ld:%03o:%ld\n", ! 455: NFLINE1, /* Nf-ID */ ! 456: note -> n_id.sys, note -> n_id.uniqid, ! 457: rsprec -> r_id[roffset].sys, ! 458: rsprec -> r_id[roffset].uniqid, ! 459: rsprec -> r_stat[roffset], ! 460: ((long) rsprec -> r_addr[roffset].textlen));/* force it long */ ! 461: ! 462: ! 463: fprintf (rnews, "%s: %s!%s %3s %2d %02d:%02d:00 %4d\n", ! 464: NFLINE2, /* NF-From */ ! 465: rsprec -> r_auth[roffset].asystem, rsprec -> r_auth[roffset].aname, ! 466: mnames[rsprec -> r_when[roffset].w_month], /* date written */ ! 467: rsprec -> r_when[roffset].w_day, ! 468: rsprec -> r_when[roffset].w_hours, ! 469: rsprec -> r_when[roffset].w_mins, ! 470: rsprec -> r_when[roffset].w_year); ! 471: if ((uniquenum = note -> n_id.uniqid) < 0) /* re-invert news */ ! 472: uniquenum /= (-100); /* back to normal */ ! 473: fprintf (rnews, "References: <%ld@%s>\n", ! 474: uniquenum, note -> n_id.sys); ! 475: ! 476: putc ('\n', rnews); /* separator */ ! 477: if (backwards) /* old stuff included */ ! 478: { ! 479: fprintf (rnews, "#R:%s:%ld:%s:%ld:%03o:%ld\n", ! 480: note -> n_id.sys, note -> n_id.uniqid, ! 481: rsprec -> r_id[roffset].sys, ! 482: rsprec -> r_id[roffset].uniqid, ! 483: rsprec -> r_stat[roffset], ! 484: ((long) rsprec -> r_addr[roffset].textlen));/* force it long */ ! 485: ! 486: fprintf (rnews, "%s!%s %3s %2d %02d:%02d:00 %4d\n", ! 487: rsprec -> r_auth[roffset].asystem, rsprec -> r_auth[roffset].aname, ! 488: mnames[rsprec -> r_when[roffset].w_month],/* date written */ ! 489: rsprec -> r_when[roffset].w_day, ! 490: rsprec -> r_when[roffset].w_hours, ! 491: rsprec -> r_when[roffset].w_mins, ! 492: rsprec -> r_when[roffset].w_year); ! 493: } ! 494: putc ('\n', rnews); /* separator */ ! 495: pageout (io, &rsprec -> r_addr[roffset], rnews); /* dump text */ ! 496: fprintf (rnews, "\n"); /* ensure a newline */ ! 497: pclose (rnews); /* close it */ ! 498: sleep (SLEEPTIME); /* and wait */ ! 499: return (0); ! 500: } ! 501: ! 502: /* ! 503: * A quick and cheap way to calculate a timezone. ! 504: * ! 505: * This routine makes the assumption that a notesfile site ! 506: * we gateway for is in the same timezone as our site. ! 507: * ! 508: */ ! 509: ! 510: char *tzone (when) ! 511: struct when_f when; /* unused */ ! 512: { ! 513: #ifdef BSD42 ! 514: #include <sys/time.h> /* it moved! */ ! 515: #else ! 516: #include <time.h> ! 517: #endif BSD42 ! 518: #include <sys/types.h> /* for ftime */ ! 519: ! 520: struct tm *ltime; ! 521: extern struct tm *localtime (); ! 522: long timenow; ! 523: ! 524: #ifdef USG ! 525: struct tm *bp; ! 526: extern char *tzname[]; ! 527: ! 528: time (&timenow); ! 529: ltime = localtime (&timenow); ! 530: return (tzname[ltime -> tm_isdst]); ! 531: #else ! 532: /* ! 533: * for systems that still have the "timezone" function from V7 ! 534: */ ! 535: #include <sys/timeb.h> /* for ftime */ ! 536: struct timeb rawtime; ! 537: extern char *timezone (); /* please lint */ ! 538: ! 539: ftime (&rawtime); /* get information */ ! 540: time (&timenow); /* get now */ ! 541: ltime = localtime (&timenow); /* see if DST */ ! 542: return (timezone ((int) rawtime.timezone, ltime -> tm_isdst)); ! 543: #endif ! 544: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.