Initial revision
[citadel.git] / citadel / rcit.c
1 #define UNCOMPRESS "/usr/bin/gunzip"
2
3 /* Citadel/UX rnews
4  * version 2.8
5  *
6  * This program functions the same as the standard rnews program for
7  * UseNet. It accepts standard input, and looks for rooms to post messages
8  * (translated from UseNet format to the Citadel/UX binary message format)
9  * in that match the names of the newsgroups. network/rnews.xref is checked
10  * in case the sysop wants to cross-reference room names to newsgroup names.
11  * If standard input is already in binary, the -c flag should be used.
12  *   The netproc program is then called to do the processing.
13  *
14  * If you have a separate newsreader and don't want to use Citadel for news,
15  * just call this program something else (rcit, for example) -- but make sure
16  * to tell your Citadel network neighbors the new name of the program to call.
17  * 
18  * usage:
19  *      rnews [-c] [-z] [-s]
20  * flags:
21  *      -c      Input is already in Citadel binary format
22  *              (default is UseNet news format)
23  *      -z      Input is compressed, run uncompress on it before processing
24  *      -s      Don't run netproc now, just accept the input into spoolin
25  */
26
27 #include <stdlib.h>
28 #include <unistd.h>
29 #include <fcntl.h>
30 #include <stdio.h>
31 #include <ctype.h>
32 #include <string.h>
33 #include <time.h>
34 #include "citadel.h"
35
36 void get_config();
37 struct config config;
38
39 char roomlist[MAXROOMS][20];
40
41 void load_roomlist() {
42         FILE *fp;
43         struct quickroom QRtemp;
44         int a;
45
46         for (a=0; a<MAXROOMS; ++a) strcpy(roomlist[a],TWITROOM);
47         fp=fopen("quickroom","r");
48         if (fp==NULL) return;
49         for (a=0; a<MAXROOMS; ++a) {
50                 fread((char *)&QRtemp,sizeof(struct quickroom),1,fp);
51                 if (QRtemp.QRflags & QR_INUSE)
52                         strcpy(roomlist[a],QRtemp.QRname);
53                 }
54         fclose(fp);
55         }
56
57 int struncmp(lstr,rstr,len)
58 char lstr[],rstr[];
59 int len; {
60         int pos = 0;
61         char lc,rc;
62         while (pos<len) {
63                 lc=tolower(lstr[pos]);
64                 rc=tolower(rstr[pos]);
65                 if ((lc==0)&&(rc==0)) return(0);
66                 if (lc<rc) return(-1);
67                 if (lc>rc) return(1);
68                 pos=pos+1;
69                 }
70         return(0);
71         }
72
73
74 int rnewsxref(room,ngroup)              /* xref table */
75 char room[]; 
76 char ngroup[]; {
77         FILE *fp;
78         int a,b;
79         char aaa[50],bbb[50];
80         
81         strcpy(room,ngroup);
82         fp=fopen("network/rnews.xref","r");
83 GNA:    strcpy(aaa,""); strcpy(bbb,"");
84         do {
85                 a=getc(fp);
86                 if (a==',') a=0;
87                 if (a>0) { b=strlen(aaa); aaa[b]=a; aaa[b+1]=0; }
88                 } while(a>0);
89         do {
90                 a=getc(fp);
91                 if (a==10) a=0;
92                 if (a>0) { b=strlen(bbb); bbb[b]=a; bbb[b+1]=0; }
93                 } while(a>0);
94         if (a<0) {
95                 fclose(fp);
96                 return(1);
97                 }
98         if (strucmp(ngroup,aaa)) goto GNA;
99         fclose(fp);
100         strcpy(room,bbb);
101         return(0);
102         }
103
104
105 void getroom(room,ngroup)
106 char room[];
107 char ngroup[]; {
108         char ngbuf[256];
109         char tryme[256];
110         int a,b;
111         struct quickroom qbuf;
112
113         strcpy(ngbuf,ngroup);
114         strcat(ngbuf,",");
115         for (a=0; a<strlen(ngbuf); ++a) {
116                 if ((ngbuf[a]==',')||(ngbuf[a]==0)) {
117                         strcpy(tryme,ngbuf);    
118                         tryme[a]=0;
119                         if (!rnewsxref(room,tryme)) return;
120                         room[sizeof(qbuf.QRname)-1]=0;
121                         for (b=0; b<MAXROOMS; ++b) {
122                                 if (!strucmp(roomlist[b],room)) return;
123                                 }
124                         strcpy(ngbuf,&ngbuf[a+1]);
125                         a=(-1);
126                         }
127                 }
128         }
129
130 void main(argc,argv)
131 int argc;
132 char *argv[]; {
133         char aaa[128],bbb[128],ccc[128];
134         char author[128],recipient[128],room[128],node[128],path[512];
135         char subject[128];
136         char orgname[128];
137         long mid = 0L;
138         long now,bcount,aa;
139         int a;
140         char flnm[128],tname[128];
141         FILE *minput,*mout,*mtemp;
142         char binary_input = 0;
143         char compressed_input = 0;
144         char spool_only = 0;
145
146         get_config();
147         sprintf(flnm,"./network/spoolin/rnews.%d",getpid());
148         sprintf(tname,"/tmp/rnews.%d",getpid());
149
150         for (a=1; a<argc; ++a) {
151                 if (!strcmp(argv[a],"-c")) binary_input = 1;
152                 if (!strcmp(argv[a],"-z")) compressed_input = 1;
153                 if (!strcmp(argv[a],"-s")) spool_only = 1;
154                 }
155
156         minput=stdin;
157         if (compressed_input) minput=popen(UNCOMPRESS,"r");
158         if (minput==NULL) fprintf(stderr,"rnews: can't open input!!!!\n");
159
160         mout=fopen(flnm,"w");
161
162         /* process Citadel/UX binary format input */
163         if (binary_input) {
164                 while ((a=getc(minput))>=0) putc(a,mout);
165                 goto END;
166                 }
167
168         /* process UseNet news input */
169         load_roomlist();
170 A:      if (fgets(aaa,128,minput)==NULL) goto END;
171         aaa[strlen(aaa)-1]=0;
172         if (strncmp(aaa,"#! rnews ",9)) goto A;
173         bcount=atol(&aaa[9]);
174         mtemp=fopen(tname,"w");
175         for (aa=0L; aa<bcount; ++aa) {
176                 a=getc(minput);
177                 if (a<0) goto NMA;
178                 if (a>=0) putc(a,mtemp);
179                 }
180 NMA:    fclose(mtemp);
181         if (a<0) {
182                 fprintf(stderr,"rnews: EOF unexpected\n");
183                 goto END;
184                 }
185
186         mtemp=fopen(tname,"r");
187         strcpy(author,"");
188         strcpy(recipient,"");
189         strcpy(room,"");
190         strcpy(node,"");
191         strcpy(path,"");
192         strcpy(orgname,"");
193         strcpy(subject,"");
194
195 B:      if (fgets(aaa,128,mtemp)==NULL) goto ABORT;
196         aaa[strlen(aaa)-1]=0;
197         if (strlen(aaa)==0) goto C;
198
199
200         if (!strncmp(aaa,"From: ",6)) {
201                 strcpy(author,&aaa[6]);
202                 while((author[0]==' ')&&(strlen(author)>0))
203                         strcpy(author,&author[1]);
204                 for (a=0; a<strlen(author); ++a) {
205                         if (author[a]=='<') author[a-1]=0;
206                         if (author[a]==')') author[a]=0;
207                         if (author[a]=='(') {
208                                 strcpy(author,&author[a+1]);
209                                 a=0;
210                                 }
211                         }
212                 if (!strcmp(author,")")) {
213                         strcpy(author,&aaa[6]);
214                         for (a=0; a<strlen(author); ++a)
215                                 if (author[a]=='@') author[a]=0;
216                         }
217                 strcpy(node,&aaa[6]);
218                 for (a=0; a<strlen(node); ++a) {
219                         if ((node[a]=='<')||(node[a]=='@')) {
220                                 strcpy(node,&node[a+1]);
221                                 a=0;
222                                 }
223                         if (node[a]=='>') node[a]=0;
224                         if (node[a]=='(') node[a-1]=0;
225                         }
226                 for (a=0; a<strlen(author); ++a)
227                         if (author[a]=='@') author[a]=0;
228                 }
229
230         if (!strncmp(aaa,"Path: ",6)) strcpy(path,&aaa[6]);
231         if (!strncmp(aaa,"To: ",4)) strcpy(recipient,&aaa[4]);
232         if (!strncmp(aaa,"Subject: ",9)) strcpy(subject,&aaa[9]);
233         if (!strncmp(aaa,"Organization: ",14)) strcpy(orgname,&aaa[14]);
234
235         if (!strncmp(aaa,"Newsgroups: ",11)) {
236                 strcpy(room,&aaa[12]);
237                 for (a=0; a<strlen(aaa); ++a) if (aaa[a]==',') aaa[a]=0;
238                 goto B;
239                 }
240
241         if (!strncmp(aaa,"Message-ID: ",11)) {
242                 strcpy(bbb,&aaa[13]);
243                 for (a=0; a<strlen(bbb); ++a) if (bbb[a]=='@') bbb[a]=0;
244                 mid=atol(bbb);
245                 while((aaa[0]!='@')&&(aaa[0]!=0)) {
246                         strcpy(&aaa[0],&aaa[1]);
247                         }
248                 strcpy(&aaa[0],&aaa[1]);
249                 for (a=0; a<strlen(aaa); ++a) if (aaa[a]=='>') aaa[a]=0;
250                 strcpy(node,aaa);
251                 goto B;
252                 }
253                 goto B;
254
255 C:      if ((author[0]==0)||(room[0]==0)||(node[0]==0)) goto ABORT;
256         putc(255,mout);                 /* start of message */
257         putc(MES_NORMAL,mout);          /* not anonymous */
258         putc(1,mout);                   /* not formatted */
259         time(&now);
260
261         fprintf(mout,"I%ld",mid); putc(0,mout);
262         fprintf(mout,"P%s",path); putc(0,mout);
263         fprintf(mout,"T%ld",now); putc(0,mout);
264         fprintf(mout,"A%s",author); putc(0,mout);
265         strcpy(ccc,room);
266         getroom(room,ccc);
267         fprintf(mout,"O%s",room); putc(0,mout);
268         fprintf(mout,"N%s",node); putc(0,mout);
269         if (orgname[0]!=0) {
270                 fprintf(mout,"H%s",orgname); putc(0,mout);
271                 }
272         if (recipient[0]!=0) {
273                 fprintf(mout,"R%s",recipient); putc(0,mout);
274                 }
275         if (subject[0]!=0) {
276                 fprintf(mout,"U%s",subject); putc(0,mout);
277                 }
278         fprintf(mout,"M");
279         a=0;
280         aaa[0]=0;
281
282         do {
283                 a=getc(mtemp);
284                 if (a>0) putc(a,mout);
285                 } while (a>0);
286         putc(0,mout);
287 ABORT:  fclose(mtemp);
288         unlink(tname);
289         goto A;
290
291 END:    putc(0,mout);
292         fclose(mout);
293         unlink(tname);
294         if (compressed_input) pclose(minput);
295         if (!spool_only) execlp("./netproc","netproc",NULL);
296         exit(0);
297 }
298
299