|
|
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.