1772
|
1 /* rnews.c --This is the main program to process and distribute Usenet news.
|
|
2 Copyright (C) 1994 Brad Spencer
|
|
3
|
|
4 This file is part of the OS-9 UUCP package, UUCPbb.
|
|
5
|
|
6 This program is free software; you can redistribute it and/or modify
|
|
7 it under the terms of the GNU General Public License as published by
|
|
8 the Free Software Foundation; either version 2 of the License, or
|
|
9 (at your option) any later version.
|
|
10
|
|
11 This program is distributed in the hope that it will be useful,
|
|
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
14 GNU General Public License for more details.
|
|
15
|
|
16 You should have received a copy of the GNU General Public License
|
|
17 along with this program; if not, write to the Free Software
|
|
18 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
|
19
|
|
20 The author of UUCPbb, Bob Billson, can be contacted at:
|
|
21 bob@kc2wz.bubble.org or uunet!kc2wz!bob or by snail mail:
|
|
22 21 Bates Way, Westfield, NJ 07090
|
|
23 */
|
|
24
|
|
25 /* main function */
|
|
26
|
|
27 #define MAIN
|
|
28 #include "uucp.h"
|
|
29 #include "rnews.h"
|
|
30 #include "mbuf.h"
|
|
31 #include "getopt.h"
|
|
32 #include <direct.h>
|
|
33
|
|
34 QQ int debuglvl = 0;
|
|
35 struct mbuf *getgroups();
|
|
36
|
2106
|
37 int main(argc,argv)
|
1772
|
38 int argc;
|
|
39 char *argv[];
|
|
40 {
|
|
41 char lbuf[512], buf[BIGBUF], filename[100], initng[100];
|
|
42 struct fildes fdes;
|
|
43 FILE *batchfile;
|
|
44 int savein, saveout, fd, pipefd;
|
|
45 char *bigbuf;
|
|
46 int e,p,option,zflag=0;
|
|
47 struct mbuf *g,*gg;
|
|
48 long length = -1;
|
|
49
|
|
50 initng[0] = '\0';
|
|
51
|
|
52 #ifndef _OSK
|
|
53 pflinit();
|
|
54 #endif
|
|
55
|
|
56 /* On the CC3 there seems to be a bit of arcane lore that is needed to
|
|
57 make setbuf() work without crashing on exit. This malloc is part of
|
|
58 what I discovered to work. */
|
|
59
|
|
60 if ((bigbuf = (char *) malloc (BUFSIZ+16)) == NULL)
|
|
61 {
|
|
62 fprintf (stderr, "Can't allocate file buffer\n");
|
|
63 exit(207);
|
|
64 }
|
|
65
|
|
66 /* I suppose that this is true */
|
|
67 if (getuid() != 0)
|
|
68 {
|
|
69 fprintf (stderr,"Must be root\n");
|
|
70 exit (214);
|
|
71 }
|
|
72
|
|
73 while (((option = getopt (argc, argv, "x:n:mz?")) != NONOPT)
|
|
74 || optarg != NULL)
|
|
75 {
|
|
76 switch (option)
|
|
77 {
|
|
78 /* Set the debug level */
|
|
79 case 'x':
|
|
80 debuglvl = atoi (optarg);
|
|
81 break;
|
|
82
|
|
83 /* Set a newsgroup that is forced, if this is just a single
|
|
84 article */
|
|
85 case 'n':
|
|
86 strcpy (initng, optarg);
|
|
87 break;
|
|
88
|
|
89 /* Force logging to standard output with no reguard to the
|
|
90 debugging level */
|
|
91 case 'z':
|
|
92 zflag++;
|
|
93 break;
|
|
94
|
|
95 /* Must be the file to process */
|
|
96 case NONOPT:
|
|
97 strcpy (filename, optarg);
|
|
98 break;
|
|
99
|
|
100 case '?': /* Help */
|
|
101 default:
|
|
102 usage();
|
|
103 break;
|
|
104 }
|
|
105 }
|
|
106
|
|
107 if (getparam() == FALSE)
|
|
108 exit (ABORT);
|
|
109
|
|
110 if ((logdir = getenv ("LOGDIR")) != NULL)
|
|
111 logdir = strdup (logdir);
|
|
112 else
|
|
113 logdir = LOGDIR;
|
|
114
|
|
115 if ((newsdir = getdirs ("newsdir")) == NULL)
|
|
116 fatal ("newsdir not in Parameters");
|
|
117
|
|
118 /* Set up the log file. The fprintf below is important, as it makes sure
|
|
119 that standard error has been opened */
|
|
120
|
|
121 if (zflag || debuglvl > 4)
|
|
122 {
|
|
123 fprintf (stderr, "\nLogging to stderr\n");
|
|
124 inizlog ("rnews", 3);
|
|
125 }
|
|
126 else
|
|
127 inizlog ("rnews", 1);
|
|
128
|
|
129 /* Get the groups from the active file */
|
|
130 g = getgroups();
|
|
131
|
|
132 if (debuglvl > 5)
|
|
133 for (gg = g; gg != NULL; gg = gg->mbuf_next)
|
|
134 {
|
|
135 sprintf (lbuf, "ACTIVE IN: %s, %d, %d",
|
|
136 ((struct groups *)gg->cbuf)->name,
|
|
137 ((struct groups *)gg->cbuf)->min,
|
|
138 ((struct groups *)gg->cbuf)->max);
|
|
139 log (lbuf);
|
|
140 }
|
|
141
|
|
142 /* Got to be able to open the file */
|
|
143 if ((fd = open (filename, 1)) < 0)
|
|
144 {
|
|
145 sprintf (lbuf, "Can't open '%s'", filename);
|
|
146 log (lbuf);
|
|
147 exit (1);
|
|
148 }
|
|
149
|
|
150 if (debuglvl > 3)
|
|
151 {
|
|
152 sprintf (lbuf, "Opened '%s'", filename);
|
|
153 log (lbuf);
|
|
154 }
|
|
155
|
|
156 /* Hopefully the first bit of the file will tell us what sort of
|
|
157 thing it is */
|
|
158
|
|
159 if ((e = read (fd, buf, BUFSIZ-1)) <= 0)
|
|
160 {
|
|
161 sprintf (lbuf, "Can't read from '%s'", filename);
|
|
162 log (lbuf);
|
|
163 exit (1);
|
|
164 }
|
|
165
|
|
166 /* Ok, it seems to be a compressed file, possibly batched */
|
|
167 if (strncmp (buf, "#! cunbatch", 11) == 0)
|
|
168 {
|
|
169 if (debuglvl > 1)
|
|
170 log ("A compressed news file");
|
|
171
|
|
172 /* Ok, move to the proper place in the file to begin decompression
|
|
173 */
|
|
174
|
|
175 lseek (fd, 12l, 0);
|
|
176
|
|
177 /* Save stdin, stdout and close the originals */
|
|
178 savein = dup (0);
|
|
179 saveout = dup (1);
|
|
180 close (0);
|
|
181 close (1);
|
|
182
|
|
183 /* Try making the file's fd stdin, fail if we can't */
|
|
184 if (dup (fd) != 0)
|
|
185 {
|
|
186 log ("Can't dup fd 0");
|
|
187 exit (1);
|
|
188 }
|
|
189
|
|
190 /* The pipe better be stdout !!! */
|
|
191
|
|
192 if ((pipefd = open ("/pipe", 3)) != 1)
|
|
193 {
|
|
194 log ("Can't open /pipe");
|
|
195 exit (1);
|
|
196 }
|
|
197
|
|
198 /* Fork compress, complain otherwise */
|
|
199 if ((p = os9fork ("compress", 3, "-d\n", 0, 0, 0)) < 0)
|
|
200 {
|
|
201 log ("Could not fork compress");
|
|
202 exit (1);
|
|
203 }
|
|
204
|
|
205 /* Increase my priority, hopefully, above compress.
|
|
206
|
|
207 The theory is that we will spend most of our time processing and
|
|
208 writing the article file, rather then reading from the pipe.
|
|
209 And when we read from the pipe, we aren't doing anything else
|
|
210 anyway [i.e. possibly sleeping on I/O]. So, don't take up CPU
|
|
211 time on compress, because it will be given the CPU when needed
|
|
212 anyway. This may all be nuts, however....
|
|
213
|
|
214 I've noted that making the priority the same makes for terrible
|
|
215 performance */
|
|
216
|
|
217 setpr (getpid(), 200);
|
|
218 setpr (p, 100);
|
|
219
|
|
220 /* It is important to close the file, on our side, or the end of
|
|
221 file on the pipe won't be detected. */
|
|
222
|
|
223 close (0);
|
|
224
|
|
225 /* Unredirect the file descriptors. More arcane stuff, you really
|
|
226 shouldn't have to do this */
|
|
227
|
|
228 pipefd = dup (1);
|
|
229 close (1);
|
|
230 dup (savein);
|
|
231 dup (saveout);
|
|
232
|
|
233 /* Make a FILE pointer for the pipefd */
|
|
234 if ((batchfile = fdopen (pipefd, "r+")) == NULL)
|
|
235 {
|
|
236 log ("Couldn't fdopen the pipe fd");
|
|
237 exit (1);
|
|
238 }
|
|
239 setbuf (batchfile, bigbuf);
|
|
240
|
|
241 /* Get the first line, which may indicate that this is a batch of
|
|
242 articles */
|
|
243
|
|
244 if (getline (batchfile, buf) == -1)
|
|
245 {
|
|
246 log ("Nothing on the pipe");
|
|
247 exit (1);
|
|
248 }
|
|
249 }
|
|
250 else
|
|
251 {
|
|
252 /* Must not be compressed. This is also the place where one might
|
|
253 process other compression schemes, like lha. In general, one
|
|
254 should check for each type of compression before assuming that
|
|
255 the file is uncompressed */
|
|
256
|
|
257 if (debuglvl > 1)
|
|
258 log ("An uncompressed news file");
|
|
259
|
|
260 /* Rewind the file and get the size, so we can pass it along, if
|
|
261 needed */
|
|
262
|
|
263 lseek (fd, 0l, 0);
|
|
264
|
|
265 if (_gs_gfd (fd, &fdes, sizeof (fdes)) != -1)
|
|
266 length = (long)fdes.fd_fsize;
|
|
267
|
|
268 /* Make a FILE pointer out of the file fd, instead of the pipe, as
|
|
269 above */
|
|
270
|
|
271 if ((batchfile = fdopen (fd, "r")) == NULL)
|
|
272 {
|
|
273 log ("Can't fdopen news file");
|
|
274 exit (1);
|
|
275 }
|
|
276 setbuf (batchfile, bigbuf);
|
|
277
|
|
278 /* Get a line, which could mean that this is a batch of articles */
|
|
279 getline (batchfile, buf);
|
|
280 }
|
|
281
|
|
282 /* Ok, we seem to have a batch of articles. Process them, as such */
|
|
283
|
|
284 if (strncmp (buf, "#! rnews ", 9) == 0)
|
|
285 {
|
|
286 if (debuglvl > 1)
|
|
287 log ("A batch of news articles");
|
|
288
|
|
289 procbatch (batchfile, buf, g);
|
|
290 }
|
|
291 else
|
|
292 {
|
|
293 /* Not a batch of articles, assume that it is a single article */
|
|
294 if (debuglvl > 1)
|
|
295 log ("A single news article");
|
|
296
|
|
297 procart (batchfile, buf, initng, g, length);
|
|
298 }
|
|
299
|
|
300 /* Put the updated active file back */
|
|
301 if (debuglvl > 3)
|
|
302 log ("Updating active file");
|
|
303
|
|
304 putgroups (g);
|
|
305
|
|
306 /* Clean things up */
|
|
307 if (debuglvl > 4)
|
|
308 log ("Exiting.....");
|
|
309
|
|
310 fclose (batchfile);
|
|
311 close (pipefd);
|
|
312 close (fd);
|
|
313 wait (0);
|
|
314
|
|
315 /* Close up the log */
|
|
316 deinizlog();
|
|
317 exit (0);
|
|
318 }
|
|
319
|
|
320
|
|
321
|
|
322 /* Cheap fatal */
|
|
323
|
|
324 int fatal (s)
|
|
325 char *s;
|
|
326 {
|
|
327 fprintf (stderr, "'%s'\n");
|
|
328 exit (ABORT);
|
|
329 }
|
|
330
|
|
331
|
|
332
|
|
333 /* Cheaper usage */
|
|
334
|
|
335 int usage()
|
|
336 {
|
|
337 fprintf (stderr,
|
|
338 "rnews [-x debug_level] [-n inital_newsgroup] [-z] newsfile\n");
|
|
339 exit (1);
|
|
340 }
|